java — правило для Cursor: стандарты Java 21/25
Правило задаёт агенту стиль кода Java: Google Java Style, именование, иммутабельность, Stream API и работа с ресурсами.
.cursor/rules/java.mdcЧто делает java
Файл .cursor/rules/java.mdc подключается к Cursor и действует на все файлы проекта. Внутри — набор требований к форматированию и структуре: отступ в 4 пробела, запрет табов, скобки K&R, обязательные фигурные скобки даже для однострочных тел if и while, явные импорты без *, кодировка UTF-8.
Отдельные разделы посвящены именованию и паттернам. Пакеты пишутся строчными через точку, классы и record — в PascalCase, константы — в SCREAMING_SNAKE_CASE, булевы методы получают префиксы is, has, can, should, коллекции — имена во множественном числе. Для простых неизменяемых данных правило советует record (Java 16+), для обработки коллекций — Stream API и Optional, для закрытия ресурсов — try-with-resources.
Есть блок про производительность: StringBuilder вместо конкатенации в цикле, параметризованное логирование вместо склейки строк. Последний раздел предупреждает об изменяемых статических полях — они ломают тесты и создают гонки. Правило рассчитано на Java 21/25 и опирается на Google Java Style Guide, поэтому в проектах со своим стайлгайдом его придётся править под себя.
Какие задачи решает
- привести форматирование Java-кода к Google Java Style без ручной правки
- заменить изменяемые классы на record там, где это уместно
- убрать wildcard-импорты и разложить импорты по порядку
- переписать конкатенацию строк в цикле на StringBuilder
- найти изменяемые статические поля, которые мешают тестам
Примеры запросов агенту
- Отрефактори этот класс по правилам java: убери сеттеры и сделай record
- Проверь файл на соответствие правилу java и покажи нарушения по именованию
- Перепиши этот цикл с конкатенацией строк так, как требует правило java
Как установить java
Вручную: положить файлы
.cursor/rules/java.mdcВо frontmatter: description, globs, alwaysApply
Вручную: положить файлы
.claude/rules/java.mdПоле paths во frontmatter ограничивает файлы: globs из источника → paths
AGENTS.md
Codex читает AGENTS.md: вставьте текст правила туда
Вручную: положить файлы
.github/instructions/java.instructions.mdПоле applyTo задаёт, к каким файлам применять: globs из источника → applyTo
Вручную: положить файлы
.devin/rules/java.mdВручную: положить файлы
.clinerules/java.mdПо шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules
Из того же набора69
Похожие
Рядом в теме «Языки программирования»
Все правила IDE по теме «Языки программирования» →Вопросы о java
Как установить правило java в Cursor?
Положите файл по пути .cursor/rules/java.mdc в корне проекта — Cursor подхватит его автоматически.
Что делает правило java?
Задаёт агенту стандарты написания Java-кода: форматирование, именование, иммутабельность, Stream API, try-with-resources и работу со строками.
На какую версию Java рассчитано правило?
На Java 21/25 и Google Java Style Guide. Если у команды свой стайлгайд, содержимое файла нужно переписать под него.
Исходный текст
java.mdc · CC0-1.0
---
description: Definitive guidelines for writing high-quality, maintainable, and performant Java code, adhering to modern best practices (Java 21/25) and enterprise standards like Google Java Style.
globs: **/*
---
# Java Best Practices
This document outlines the definitive best practices for Java development within our team. Adherence to these rules ensures consistent, high-quality, and maintainable code, leveraging modern Java features and enterprise standards.
## 1. Code Organization and Structure
### 1.1. Style Guide Adherence
Always follow the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html) for formatting, naming, and structural conventions. Configure your IDE (e.g., IntelliJ IDEA, VS Code with appropriate plugins) to automatically apply this style.
### 1.2. File Naming and Encoding
Source files must be named after the single top-level class they contain, with a `.java` extension. All source files must use **UTF-8** encoding.
### 1.3. Indentation and Whitespace
Use **4 spaces** for indentation. **Never use tabs.** For wrapped lines, use **8 spaces** (twice the normal indentation).
❌ BAD
```java
public class MyClass {
void myMethod() {
// Tab used for indentation
System.out.println("Hello");
}
}
```
✅ GOOD
```java
public class MyClass {
void myMethod() {
// 4 spaces for indentation
System.out.println("Hello");
}
}
```
### 1.4. Braces
Always use K&R style braces for non-empty blocks. Braces are mandatory for `if`, `else`, `for`, `do`, and `while` statements, even for single-line bodies.
❌ BAD
```java
if (condition)
doSomething(); // Missing braces
while (true){ // Bad K&R style
doSomething();
}
```
✅ GOOD
```java
if (condition) {
doSomething();
}
while (true) {
doSomethingElse();
}
```
### 1.5. Package and Import Statements
Every class must belong to a package. Use explicit imports; **wildcard imports (`*`) are forbidden**. Imports are ordered: static imports, then non-static imports, separated by a single blank line, both groups in ASCII sort order.
❌ BAD
```java
import java.util.*; // Wildcard import
import static com.example.Constants.*; // Wildcard static import
public class MyClass { /* ... */ }
```
✅ GOOD
```java
import static com.example.Constants.DEFAULT_VALUE;
import java.util.ArrayList;
import java.util.List;
public class MyClass { /* ... */ }
```
### 1.6. Naming Conventions
Adhere strictly to these conventions:
* **Packages**: `com.yourcompany.project.module` (all lowercase, dot-separated).
* **Classes/Enums/Records/Interfaces**: `PascalCase` (nouns).
* **Variables/Parameters**: `camelCase`.
* **Constants**: `SCREAMING_SNAKE_CASE` (for `static final` fields).
* **Methods**: `camelCase` (verbs).
* **Boolean Variables/Methods**: Prefix with `is`, `has`, `can`, `should`.
* **Collections**: Use plural names (e.g., `users`, `messages`).
* **Test Methods**: `featureUnderTest_testScenario_expectedBehavior()`.
❌ BAD
```java
public class userManager { // Class name not PascalCase
public static final String default_user_name = "guest"; // Constant not SCREAMING_SNAKE_CASE
private List userList; // Collection not plural
public boolean checkUser(User u) { /* ... */ } // Boolean method name unclear
}
```
✅ GOOD
```java
package com.example.app.users;
import java.util.List;
public class UserManager {
public static final String DEFAULT_USER_NAME = "guest";
private List<User> users;
public boolean isValidUser(User user) { /* ... */ }
}
```
## 2. Common Patterns and Anti-patterns
### 2.1. Prefer Immutability
Design classes to be immutable whenever possible. This simplifies concurrency and reasoning about state. Use `record` classes (Java 16+) for simple immutable data carriers.
❌ BAD
```java
public class User {
private String name;
public User(String name) { this.name = name; }
public String getName() { return name; }
public void setName(String name) { this.name = name; } // Mutable setter
}
```
✅ GOOD
```java
public record User(String name) {} // Immutable record (Java 16+)
// Or traditional immutable class:
public final class ImmutableUser {
private final String name;
public ImmutableUser(String name) { this.name = name; }
public String getName() { return name; }
}
```
### 2.2. Embrace Functional Programming with Streams and Optionals
Leverage Java's Stream API for collection processing and `Optional` for handling potentially absent values.
❌ BAD
```java
List<String> names = getUsers().stream()
.filter(u -> u.getAge() > 18)
.map(User::getName)
.collect(Collectors.toList());
// Handling null:
User user = findUserById(123L);
if (user != null) {
System.out.println(user.getName());
} else {
System.out.println("User not found");
}
```
✅ GOOD
```java
List<String> names = users.stream()
.filter(user -> user.getAge() > 18)
.map(User::getName)
.toList(); // Java 16+ for .toList()
// Handling Optional:
findUserById(123L)
.map(User::getName)
.ifPresentOrElse(
System.out::println,
() -> System.out.println("User not found")
);
```
### 2.3. Resource Management with Try-with-resources
Always use try-with-resources for any resource that implements `AutoCloseable`.
❌ BAD
```java
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
// ... read from fis
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
✅ GOOD
```java
try (FileInputStream fis = new FileInputStream("file.txt")) {
// ... read from fis
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}
```
## 3. Performance Considerations
### 3.1. Efficient String Concatenation
Use `StringBuilder` for concatenating multiple strings in loops or when building complex strings.
❌ BAD
```java
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // Creates many intermediate String objects
}
```
✅ GOOD
```java
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
```
### 3.2. Logging Performance
Avoid expensive string formatting or method calls in logging statements unless the log level is enabled. Use parameterized logging.
❌ BAD
```java
logger.debug("Processing user: " + user.getName() + " with ID: " + user.getId()); // String concatenation always happens
```
✅ GOOD
```java
logger.debug("Processing user: {} with ID: {}", user.getName(), user.getId()); // Parameters only evaluated if debug is enabled
```
## 4. Common Pitfalls and Gotchas
### 4.1. Avoid Mutable Static State
Mutable static fields are a common source of concurrency bugs and make testing difficult. Minimize their use.
❌ BAD
```java
public class Counter {
public static int count = 0; // Mutable static field
public static void increment() { count++; }
}
```
✅ GOOD
```java
// Use dependency injection for stateful services or pass state explicitly
public class CounterService {
private int count = 0; // Instance field
public synchronized void increment() { count++; } // Thread-safe instance method
public int getCount() { return count; }
}
```
### 4.2. Dependency Version Management
Always pin dependency versions. Use Bill-of-Materials (BOMs) for managing compatible versions across related libraries (e.g., Spring Boot BOM, Google Cloud Libraries BOM).
❌ BAD (Maven)
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- No version specified, relies on parent or latest -->
</dependency>
```
✅ GOOD (Maven with BOM)
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.2.5</version> <!-- Pin BOM version -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- Version inherited from BOM -->
</dependency>
</dependencies>
```
### 4.3. Correct `equals()` and `hashCode()` Implementation
Always override both `equals()` and `hashCode()` together, or neither. Use `Objects.equals()` and `Objects.hash()` for robust implementations. For data classes, `record` types handle this automatically.
❌ BAD
```java
public class Point {
private int x, y;
// Only equals() overridden, or incorrectly
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
// Missing hashCode()
}
```
✅ GOOD
```java
import java.util.Objects;
public final class Point { // Make final if not intended for extension
private final int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return
© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc