Install
openclaw skills install @joeyliu1/java-code-format-reviewUse when reviewing AI-generated code for formatting consistency. Enforces naming, structure, comments, and style conventions. Optimized for Java.
openclaw skills install @joeyliu1/java-code-format-reviewReview AI-generated code for compliance with team formatting standards. Focus on
readability, consistency, and maintainability — not functional correctness
(that's the job of requesting-code-review).
This skill is Java-centric, incorporating conventions from the Alibaba Java Development Manual.
Rule Levels (aligned with the Alibaba Manual):
- [Mandatory]: Must follow — violation blocks the commit (P0)
- [Recommended]: Strongly advised (P1)
- [Reference]: Optional (P2)
Not for: Bug investigation, security scanning, performance tuning — use requesting-code-review for those.
| Item | [Mandatory] Rule | Example |
|---|---|---|
| Forbidden prefixes/suffixes | Must not start or end with _ or $ | ✗ _name, name_, $Object |
| No Pinyin | No Pinyin or Pinyin-English mixing, no Chinese names | ✗ DaZhePromotion, getPingfenByName() |
| Class names | UpperCamelCase; exceptions: DO/BO/DTO/VO/AO | MarcoPolo, UserDO ✗ macroPolo |
| Methods/variables/params | lowerCamelCase | localValue, getHttpMessage() |
| Constants | UPPER_SNAKE_CASE, semantically complete | MAX_STOCK_COUNT ✗ MAX_COUNT |
| Abstract classes | Prefix with Abstract or Base | AbstractUserService |
| Exception classes | Suffix with Exception | UserNotFoundException |
| Test classes | Tested class name + Test | UserServiceTest |
| Arrays | Brackets are part of the type | String[] args ✗ String args[] |
| Package names | All lowercase, singular, one word per segment | com.alibaba.open.util |
| Abbreviations | No non-standard abbreviations | ✗ AbsClass, condi |
[Mandatory] POJO boolean fields must NOT have is prefix (causes framework serialization errors):
// ✗ BAD — RPC framework resolves the property name as "deleted" instead of "isDeleted"
private Boolean isDeleted;
// ✓ GOOD
private Boolean deleted;
[Recommended] Names should reflect the design pattern:
// ✓ GOOD
public class OrderFactory { ... }
public class LoginProxy { ... }
public class ResourceObserver { ... }
[Mandatory] Interface and implementation class naming:
// ✓ Service/DAO implementation classes end with Impl
public class CacheServiceImpl implements CacheService { ... }
// ✓ Capability interfaces use -able suffix
public interface Translatable { ... }
public abstract class AbstractTranslator implements Translatable { ... }
[Reference] Enum naming:
// ✓ Enum class names end with Enum; members are ALL_CAPS
public enum ProcessStatusEnum {
SUCCESS,
UNKNOWN_REASON;
}
[Reference] Service/DAO layer method naming:
| Action | Prefix | Example |
|---|---|---|
| Get single object | get | getUserById() |
| Get multiple objects | list | listUsersByDept() |
| Get count | count | countActiveUsers() |
| Insert | save / insert | saveUser() |
| Delete | remove / delete | removeExpiredTokens() |
| Update | update | updateUserStatus() |
[Reference] Domain model naming:
| Model | Suffix | Description |
|---|---|---|
| Data Object | DO | Maps to DB table, e.g. UserDO |
| Data Transfer Object | DTO | Business domain related |
| View Object | VO | Display/page related |
| Collective term | POJO | Umbrella for DO/DTO/BO/VO — never name xxxPOJO |
Common AI naming issues:
theCurrentLoggedInUserInformation → currentUserd, tmp, res → use meaningful namesuser / usr / u → unify as useruserInfo() → getUserInfo()is: isActive → active (POJO context)HTTP vs Http vs http → class HttpClient, variable httpClient[Mandatory] No magic values in code:
// ✗ BAD
String key = "Id#taobao_" + tradeId;
cache.put(key, value);
// ✓ GOOD
private static final String CACHE_KEY_PREFIX = "Id#taobao_";
cache.put(CACHE_KEY_PREFIX + tradeId, value);
[Mandatory] Use uppercase L for long/Long literals:
// ✗ Lowercase l is easily confused with digit 1
Long a = 2l;
// ✓ GOOD
Long a = 2L;
[Recommended] Group constants by function — don't use one god-constant class:
// ✓ Cache-related constants
public final class CacheConsts {
public static final long DEFAULT_EXPIRE_MS = 30_000L;
}
// ✓ System config constants
public final class ConfigConsts {
public static final String DEFAULT_ENCODING = "UTF-8";
}
[Recommended] Constant reuse levels: cross-app → app-wide → sub-project → package → class (private static final)
[Recommended] Prefer enums over constants when values are in a fixed range with extended attributes:
public enum DayEnum {
MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4),
FRIDAY(5), SATURDAY(6), SUNDAY(7);
private final int code;
DayEnum(int code) { this.code = code; }
public int getCode() { return code; }
}
[Mandatory] Brace usage:
// Empty block — write as {}
public void noOp() {}
// Non-empty block
if (condition) { // No line break before opening brace
doSomething(); // Line break after opening brace
} else { // No line break when followed by else
doOther(); // Line break before closing brace
} // Must line break after terminal closing brace
[Mandatory] No spaces inside parentheses:
// ✗ if ( a == b )
// ✓ if (a == b)
[Mandatory] if/for/while/do must use braces (even for single-line bodies):
// ✗ Single line without braces
if (condition) return;
// ✓ Must use braces
if (condition) {
return;
}
[Mandatory] Spacing rules:
a + b, x == y? and :: (a > b) ? a : bmethod(a, b, c)for (Item item : items)[Mandatory] Indentation and line width:
\n)[Mandatory] Break long method signatures with aligned parameters:
// ✓ Long method signature — break and align
public Result<UserDTO> createUserWithProfile(
String name,
String email,
AddressDTO address,
UserProfileDTO profile) {
...
}
[Mandatory] Access static variables/methods via class name:
// ✗ BAD
object.staticMethod();
// ✓ GOOD
ClassName.staticMethod();
[Mandatory] All overridden methods must have @Override:
@Override
public boolean equals(Object obj) { ... }
@Override
public int hashCode() { ... }
[Mandatory] Varargs must be the last parameter; prefer Object over primitives:
// ✓ GOOD
public void method(String name, Object... args) { ... }
[Mandatory] Prevent NPE in equals calls:
// ✗ BAD — str may be null, causing NPE
str.equals("abc");
// ✓ GOOD — constant/certain value on the left
"abc".equals(str);
// ✓ Use Objects.equals (Java 7+)
Objects.equals(str1, str2);
[Mandatory] Use equals for all wrapper type comparisons — never ==:
// ✗ Integer a = 128; Integer b = 128; a == b → false (beyond cache range)
// ✓ GOOD
Integer a = 128;
Integer b = 128;
a.equals(b); // true
[Mandatory] Use BigDecimal for floating-point — no float/double:
// ✗ BAD — precision loss
double price = 0.1 + 0.2; // 0.30000000000000004
// ✓ GOOD
BigDecimal price = new BigDecimal("0.1").add(new BigDecimal("0.2"));
[Mandatory] Use wrapper types for POJO/RPC return values and parameters:
// ✗ BAD — caller cannot distinguish 0 from "not called"
int getScore();
// ✓ GOOD
Integer getScore();
[Mandatory] POJO classes must not set default values for fields:
// ✗ BAD
public class UserDO {
private Integer age = 0; // caller should assign
}
// ✓ GOOD
public class UserDO {
private Integer age;
}
[Mandatory] No business logic in constructors (put initialization in init methods)
[Recommended] Method order within a class: public/protected → private → getter/setter
[Recommended] Use StringBuilder for string concatenation in loops:
// ✗ BAD
String result = "";
for (String item : items) {
result += item + ",";
}
// ✓ GOOD
StringBuilder sb = new StringBuilder();
for (String item : items) {
sb.append(item).append(",");
}
String result = sb.toString();
[Recommended] Use instanceof only for classes with inheritance relationships:
// ✗ No inheritance — structural code problem
if (animal instanceof Car) { ... }
[Recommended] Use Builder pattern for constructors with many parameters:
// ✓ Use Builder when more than 4 parameters
var order = Order.builder()
.userId(userId)
.items(items)
.shippingAddress(address)
.paymentMethod(PaymentMethod.CREDIT_CARD)
.build();
Immutability first:
// ✗ Mutable collection exposed externally
public List<String> getTags() {
return tags;
}
// ✓ Return unmodifiable view
public List<String> getTags() {
return Collections.unmodifiableList(tags);
}
// Or List.copyOf(tags) (Java 10+)
[Mandatory] Overriding equals requires overriding hashCode
[Mandatory] Convert collection to array with toArray(T[] array):
// ✗ BAD — loses type info
Object[] array = list.toArray();
// ✓ GOOD — returns T[] directly, no cast needed
String[] array = list.toArray(new String[0]);
[Mandatory] Arrays.asList() result must not be structurally modified:
// ✗ BAD — throws UnsupportedOperationException
List<String> list = Arrays.asList("a", "b", "c");
list.add("d");
// ✓ GOOD — wrap with new ArrayList
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
[Mandatory] No remove/add operations inside forEach:
// ✗ BAD — ConcurrentModificationException
list.forEach(item -> {
if (condition) list.remove(item);
});
// ✓ GOOD — use Iterator or removeIf
list.removeIf(item -> condition);
[Recommended] Specify initial capacity for collections:
// ✗ BAD — default capacity 16, requires multiple resizes
Map<Long, User> map = new HashMap<>();
// ✓ GOOD — estimate element count to avoid resizing
Map<Long, User> map = new HashMap<>((int) (expectedSize / 0.75) + 1);
[Mandatory] Map keys must not be modified
[Reference] Use Set for deduplication instead of List.contains (O(n) vs O(1))
[Mandatory] Singleton access must be thread-safe
[Mandatory] Use thread pools — no explicit new Thread():
// ✗ BAD
new Thread(() -> doWork()).start();
// ✓ GOOD
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> doWork());
[Mandatory] SimpleDateFormat is NOT thread-safe — must not be static:
// ✗ BAD
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");
// ✓ GOOD — DateTimeFormatter (Java 8+, thread-safe)
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
[Mandatory] Lock multiple resources in consistent order to prevent deadlocks
[Mandatory] Clean up ThreadLocal variables in finally:
try {
threadLocal.set(value);
doWork();
} finally {
threadLocal.remove();
}
[Recommended] Prefer CountDownLatch for parallel processing; handle exceptions to avoid main thread timeout
[Mandatory] switch must have default
[Mandatory] if/else/for/while/do must use braces (even single-line)
[Mandatory] Watch for type mismatch and NPE in ternary operators:
// ✗ BAD — NPE from auto-unboxing when a is null
Integer a = null;
Integer b = (flag) ? a : 0;
[Recommended] Use guard clauses instead of deep nesting:
// ✗ Deep nesting
public void process(Order order) {
if (order != null) {
if (order.isValid()) {
if (order.isPaid()) {
// core logic
}
}
}
}
// ✓ Guard clauses
public void process(Order order) {
if (order == null || !order.isValid()) {
return;
}
if (!order.isPaid()) {
return;
}
// core logic
}
[Reference] Don't embed conditional results in other expressions:
// ✗ BAD
if ((condition ? method1() : method2()) == value) { ... }
// ✓ GOOD
String result = condition ? method1() : method2();
if (result.equals(value)) { ... }
[Mandatory] Class/field/method comments must use Javadoc (/** */)
[Mandatory] All abstract methods must have Javadoc
[Mandatory] All classes must include @author
[Mandatory] Single-line comments inside methods go on a separate line above the statement:
// ✗ BAD — comment after statement
doSomething(); // handle logic
// ✓ GOOD — comment on its own line
// Handle business logic
doSomething();
[Mandatory] Update comments when modifying code; delete stale comments
[Mandatory] Comments explain why, not what:
// ✗ AI-generated redundant comment
// Get the order items
List<OrderItem> items = order.getItems();
// ✓ Explain why
// No discount calculation when order is empty — avoids meaningless division by zero
if (order.getItems().isEmpty()) {
return BigDecimal.ZERO;
}
[Mandatory] Commented-out code must include a reason; otherwise delete it (git has history)
[Recommended] Good code is self-documenting — remove unimportant comments
[Recommended] Use TODO / FIXME markers with author name and date
Javadoc tag conventions:
/**
* Queries approved tickets by ID for monthly report generation.
*
* @param ticketId ticket ID, must be greater than 0
* @return approved ticket details, or {@code null} if not found
* @throws TicketNotFoundException if ticket doesn't exist or isn't approved
* @author zhangsan
* @since 1.2.0
*/
public TicketDTO getApprovedTicket(Long ticketId) { ... }
[Mandatory] No @RequestMapping — use specific annotations (@GetMapping / @PostMapping, etc.)
[Mandatory] Prevent RuntimeExceptions with pre-checks instead of catching:
// ✗ BAD
try {
obj.method();
} catch (NullPointerException e) { ... }
// ✓ GOOD
if (obj != null) {
obj.method();
}
[Mandatory] Do not use exceptions for flow control / condition control
[Mandatory] No catch-all for large code blocks: Distinguish stable code from unstable code; catch specific exception types for unstable code
[Mandatory] Catch blocks must handle the exception (at minimum log it) — no swallowing:
// ✗ P0: Swallowed exception
try {
processPayment(order);
} catch (PaymentException e) {
// empty or only e.printStackTrace()
}
// ✗ P0: Overly broad catch
try {
parseJson(input);
} catch (Exception e) {
throw new RuntimeException(e);
}
// ✓ Catch specific exceptions, log, decide whether to recover or rethrow
try {
processPayment(order);
} catch (PaymentTimeoutException e) {
log.warn("Payment timeout, orderId: {}, will retry", order.getId(), e);
retryLater(order);
} catch (PaymentDeclinedException e) {
log.warn("Payment declined, orderId: {}", order.getId());
throw new OrderProcessingException("Payment declined", e);
}
[Mandatory] If try block is inside a transaction, manual rollback is required in catch when needed
[Mandatory] finally must close resources (use try-with-resources for JDK 7+):
// ✗ P0: Resource not closed
InputStream is = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = reader.readLine();
// Forgot to close!
// ✓ try-with-resources (must use for AutoCloseable)
try (var reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
String line = reader.readLine();
}
[Mandatory] No return inside finally blocks
[Mandatory] Caught exception must match or be a parent of the thrown exception
[Recommended] Return values may be null — document when (NPE prevention is the caller's responsibility)
[Recommended] Common NPE scenarios to guard against:
isNotEmpty checkobj.getA().getB().getC() are NPE-prone → use Optional[Recommended] Distinguish unchecked/checked exceptions; use business-meaningful custom exceptions:
// ✗ FORBIDDEN
throw new RuntimeException("error");
// ✓ GOOD
throw new UserNotFoundException("User not found: " + userId);
[Mandatory] Use SLF4J logging facade:
// ✗ BAD
System.out.println("user created: " + userId);
e.printStackTrace();
// ✓ GOOD
private static final Logger log = LoggerFactory.getLogger(UserService.class);
log.info("User created, userId={}", userId);
log.error("Processing failed, orderId={}", orderId, e);
[Mandatory] Use conditional output for trace/debug/info levels (high-volume logging impacts performance):
// ✓ Avoid unnecessary concatenation at high volume
if (log.isDebugEnabled()) {
log.debug("Order details: {}", order.toString());
}
[Mandatory] Use parameter placeholders — no string concatenation in log statements:
// ✗ BAD
log.info("user: " + user.getName() + ", age: " + user.getAge());
// ✓ GOOD
log.info("user: {}, age: {}", user.getName(), user.getAge());
[Mandatory] Production environments must not output info-level logs (use warn/error only)
[Mandatory] Log files must be retained for at least 15 days
[Recommended] Avoid logging inside loops (performance impact)
[Recommended] Use warn for business exceptions, error for system exceptions (avoid duplicate output)
[Recommended] Logs should contain key info (parameters, status, elapsed time) but be cautious with user PII
var local variable type inference (Java 10+):
// ✓ Use var when the type is obvious
var users = new ArrayList<String>();
var stream = list.stream().filter(u -> u.isActive());
// ✗ Don't use var when the type is unclear (P1)
var result = service.process(input); // What type is result?
var data = repository.findByName(name);
Rule: Only use var when the right-hand side type is immediately obvious.
Record classes (Java 16+):
// ✓ Use record for data-only DTOs/VOs
public record PointDTO(int x, int y, String label) {}
public record UserSummary(Long id, String name, String email) {}
Text Blocks (Java 15+):
String json = """
{
"name": "%s",
"age": %d
}
""".formatted(name, age);
Switch Expressions (Java 14+):
String label = switch (status) {
case PENDING -> "Pending";
case APPROVED -> "Approved";
case REJECTED -> "Rejected";
default -> "Unknown";
};
Pattern Matching:
// Java 16+ instanceof pattern matching
if (obj instanceof String s && s.length() > 5) {
log.info("Long string: {}", s);
}
// Java 21+ switch pattern matching
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
default -> throw new IllegalArgumentException("Unknown shape");
};
[Recommended] Stream chains must not exceed 3 intermediate operations — split or use loops instead:
// ✗ P1: Stream chain too long
list.stream()
.filter(x -> x.isValid())
.map(x -> x.toDTO())
.sorted(Comparator.comparing(DTO::getName))
.distinct()
.limit(10)
.collect(Collectors.toList());
// ✓ Split into meaningful steps
var validDTOs = list.stream()
.filter(Item::isValid)
.map(Item::toDTO)
.toList();
var topTen = validDTOs.stream()
.sorted(Comparator.comparing(DTO::getName))
.limit(10)
.toList();
[Recommended] Prefer method references over lambdas: Item::isValid over x -> x.isValid()
[Mandatory] No bare .get() on Optional:
// ✗ P0: Bare .get()
Optional<User> opt = repository.findById(id);
User user = opt.get();
// ✗ Not recommended: isPresent + get
if (opt.isPresent()) {
User user = opt.get();
}
// ✓ orElseThrow / ifPresent / orElseGet
User user = repository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
repository.findById(id)
.ifPresent(user -> log.info("Found user: {}", user.getName()));
[Recommended] Use Optional only for return values — not for parameters or fields
// ✗ P0: Raw type
List list = new ArrayList();
// ✓ Generics + Diamond operator
List<String> names = new ArrayList<>();
Map<Long, User> userMap = new HashMap<>();
// ✗ Declared with concrete implementation (limits flexibility)
ArrayList<String> list = new ArrayList<>();
// ✓ Declare with interface type
List<String> list = new ArrayList<>();
Map<Long, User> map = new HashMap<>();
Set<String> set = new LinkedHashSet<>();
| Pattern | Problem | Fix |
|---|---|---|
| Verbose getter/setter boilerplate | Massive hand-written POJO boilerplate | Use @Data / record / Lombok |
Overuse of instanceof + cast | Lack of polymorphism thinking | Use Visitor pattern or polymorphism |
| Swallowed exceptions | catch (Exception e) {} empty block | At minimum log, or rethrow |
| Raw types | List list without generics | List<String> list |
| Excessive null checks | Layers of if (x != null) | Use Optional or @NonNull annotations |
| String concatenation in loops | str += "..." inside loop | Use StringBuilder / String.join |
| Magic numbers/strings | if (status == 3) | Define enum or constant |
| Excessive static utility classes | All logic in static methods | Consider injectable Service |
| Over-deep Stream chains | More than 3 intermediate ops | Split into steps or use loops |
| Unclosed resources | Connection/Stream without try-with-resources | try (var x = ...) {} |
| Over-defensive programming | try-catch on every operation | Guard only where necessary |
| Redundant variables | var result = getData(); return result; | Directly return getData() |
| Duplicate code | Copy-pasted similar logic | Extract common methods |
| Unused imports | AI adds imports "just in case" | Remove unused imports |
@Autowired field injection | Tight coupling, hard to test | Use constructor injection |
e.printStackTrace() | Outputs to stderr, no logging framework | Use log.error("msg", e) |
== comparing String / Integer | Reference comparison, not value | Use .equals() / Objects.equals() |
| Double for monetary values | Precision loss | Use BigDecimal |
POJO boolean with is prefix | Framework serialization error | Remove is prefix in POJOs |
| switch without default | Unhandled unknown values | Must add default |
| Instance access to static members | Misleading to readers | Access statics via class name |
Missing @Override | Typos won't trigger compile error | Add @Override to all overrides |
System.out.println for logging | No logging framework | Use SLF4J log.info() |
HashMap without initial capacity | Multiple resizes on large data | new HashMap<>(expectedSize) |
list.remove() in loop | ConcurrentModificationException | Use removeIf() or Iterator |
git diff --cached # Staged changes
git diff # Working directory
git diff HEAD~1 HEAD # Last commit
# Java project type detection
ls pom.xml build.gradle build.gradle.kts 2>/dev/null
# Formatting / static analysis config detection
ls checkstyle.xml spotbugs-exclude.xml pmd.xml .editorconfig 2>/dev/null
grep -l 'spotless\|checkstyle\|pmd\|spotbugs\|errorprone\|alibaba' \
pom.xml build.gradle build.gradle.kts 2>/dev/null
# Lombok / MapStruct detection
grep -l 'lombok\|mapstruct' pom.xml build.gradle 2>/dev/null
# Logging framework detection
grep -l 'slf4j\|log4j\|logback' pom.xml build.gradle 2>/dev/null
If formatting tool config exists → use it as the baseline; skip rules that conflict. If not → use the default rules in this skill (Alibaba conventions as baseline).
# === Maven projects ===
which mvn && mvn checkstyle:check -q 2>&1 | head -30
which mvn && mvn spotless:check 2>&1 | head -30
which mvn && mvn pmd:check -q 2>&1 | head -30
which mvn && mvn spotbugs:check -q 2>&1 | head -30
# === Gradle projects ===
./gradlew spotlessCheck 2>&1 | head -30
./gradlew pmdMain 2>&1 | head -30
./gradlew spotbugsMain 2>&1 | head -30
# === Standalone tools ===
which google-java-format && find . -name "*.java" \
-not -path "*/target/*" -not -path "*/build/*" | \
xargs google-java-format --set-exit-if-changed -n 2>&1 | head -30
# === Alibaba P3C rule scan (if integrated) ===
which mvn && mvn p3c:p3c-check -q 2>&1 | head -30
P0 — [Mandatory] Must fix (blocks commit):
_ or $@param / @return / @throws)long/Long literal uses lowercase le.printStackTrace())catch (Exception e) without justificationList without generic parameter)String / Integer compared with ==Optional.get() without prior checkBigDecimal)is prefixswitch without default@OverrideforEach loop (add/remove)SimpleDateFormat declared staticSystem.out.println / e.printStackTrace() used for loggingequals called on potentially null object (not constant on left)P1 — [Recommended] Strongly advised to fix:
String += concatenation inside loopsvar used but right-hand type is unclear@Autowired on field) instead of constructor injectionArrayList instead of List)HashMap initialized without capacitytoArray(){}obj.getA().getB().getC()P2 — [Reference] Suggested improvements (non-blocking):
java.* → javax.* → third-party → project)x -> x.getName() → Item::getNameList.copyOf() instead of Collections.unmodifiableXxx()Enum suffixxxxPOJO)Format:
=== AI Code Format Review Report ===
File: src/main/java/com/example/user/UserService.java
[P0] L15-20: Naming inconsistency — method uses camelCase (getUserById),
but another file in the same package uses snake_case (get_user_by_id)
→ Unify to camelCase (Alibaba Manual [Mandatory])
[P0] L42: Public method missing Javadoc
public User createUser(CreateUserRequest request) {
→ Add Javadoc with @param and @return (Alibaba Manual [Mandatory])
[P0] L88-95: Exception swallowed
catch (IOException e) { /* empty */ }
→ At minimum log or rethrow (Alibaba Manual [Mandatory])
[P0] L105: Magic value
if (status == 3) { ... }
→ Define StatusEnum or constant (Alibaba Manual [Mandatory])
[P1] L55-95: Method body is 40 lines — consider splitting
→ Extract validation logic to validateCreateRequest()
[P1] L102: String concatenation in loop
result += item.getName() + ",";
→ Use StringBuilder (Alibaba Manual [Recommended])
[P2] L7: Unused import
import java.util.stream.Stream;
→ Remove
Stats: P0 x4, P1 x2, P2 x1
# Maven: Spotless auto-format (google-java-format)
mvn spotless:apply
# Gradle: Spotless auto-format
./gradlew spotlessApply
# Standalone: google-java-format direct fix
find . -name "*.java" -not -path "*/target/*" -not -path "*/build/*" | \
xargs google-java-format --replace
# Remove unused imports (IDE operation)
# IntelliJ: Ctrl+Alt+O (Optimize Imports)
# VS Code + Java Extension: "Organize Imports"