Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/Objective-Arts/lens --skill java명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | java |
| description | Effective Java patterns |
| allowed-tools | [] |
Josh Bloch's core belief: APIs should be easy to use correctly and hard to use incorrectly. Every design decision should make the right thing easy and the wrong thing difficult or impossible.
"When in doubt, leave it out."
If you're unsure whether a feature, parameter, or method belongs, it probably doesn't. You can always add later. You can never remove without breaking clients.
Immutable objects are simple, thread-safe, and can be shared freely.
Make classes immutable unless there's a good reason not to:
Not this:
public class Period {
private Date start;
private Date end;
public void setStart(Date start) { this.start = start; }
public Date getStart() { return start; } // Leaks mutable reference
}
This:
public final class Period {
private final Date start;
private final Date end;
public Period(Date start, Date end) {
this.start = new Date(start.getTime()); // Defensive copy
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0)
throw new IllegalArgumentException("start after end");
}
public Date getStart() { return new Date(start.getTime()); } // Defensive copy
}
Static factories have names, don't require new object creation, and can return subtypes.
Not this:
Boolean flag = new Boolean(true); // Always creates object
This:
Boolean flag = Boolean.valueOf(true); // Can return cached instance
Name conventions:
from - type conversion: Date.from(instant)of - aggregation: EnumSet.of(JACK, QUEEN, KING)valueOf - verbose alternative to ofgetInstance / instance - returns instance (may be cached)newInstance / create - guarantees new instancegetType / newType - factory in different classInheritance violates encapsulation. The subclass depends on implementation details of the superclass.
Not this:
public class InstrumentedHashSet<E> extends HashSet<E> {
private int addCount = 0;
@Override
public boolean add(E e) {
addCount++;
return super.add(e); // What if HashSet.addAll calls add()?
}
@Override
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c); // Double counting!
}
}
This (composition with forwarding):
public class InstrumentedSet<E> implements Set<E> {
private final Set<E> s;
private int addCount = 0;
public InstrumentedSet(Set<E> s) { this.s = s; }
public boolean add(E e) {
addCount++;
return s.add(e);
}
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return s.addAll(c);
}
// ... delegate all other Set methods to s
}
If you allow inheritance, document precisely what subclasses can rely on. If you don't want to make that commitment, make the class final.
Refer to objects by their interfaces. This allows flexibility to change implementations.
Not this:
LinkedHashSet<String> names = new LinkedHashSet<>();
This:
Set<String> names = new LinkedHashSet<>();
Never force callers to write null checks for collections.
Not this:
public List<Item> getItems() {
if (items.isEmpty()) return null; // Forces null check
return items;
}
This:
public List<Item> getItems() {
return items.isEmpty()
? Collections.emptyList()
: new ArrayList<>(items);
}
Optionals are for return values that might legitimately be absent. Never use for fields, parameters, or collections.
Appropriate:
public Optional<Item> findById(long id) {
return Optional.ofNullable(cache.get(id));
}
Never:
// Don't do any of these
private Optional<Item> item; // Field
public void process(Optional<Item> item) { } // Parameter
public Optional<List<Item>> getItems() { } // Optional of collection
Detect errors as early as possible. Validate parameters at the start of methods.
Not this:
public void process(String input) {
// ... 50 lines of code ...
input.toLowerCase(); // NullPointerException here, far from cause
}
This:
public void process(String input) {
Objects.requireNonNull(input, "input must not be null");
if (input.isEmpty()) {
throw new IllegalArgumentException("input must not be empty");
}
// ... proceed with valid input ...
}
If you override equals, you must override hashCode. Objects that are equal must have equal hash codes.
The equals contract:
x.equals(x) is truex.equals(y) iff y.equals(x)x.equals(y) and y.equals(z), then x.equals(z)x.equals(null) is falseWhen constructors have many parameters (especially optional ones), use the Builder pattern.
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
.calories(100)
.sodium(35)
.carbohydrate(27)
.build();
Before committing any API or class design, ask:
Apply these checks:
Use a different skill when:
simplicity (Go Proverbs, small interfaces)design-patterns (23 patterns catalog)correctness (invariants, weakest preconditions)clarity (readability, naming)optimization (cache behavior, profiling)Bloch is the Java/Kotlin skill—use it for defensive API design and robust object-oriented code.
"APIs should be easy to use correctly and hard to use incorrectly." — Josh Bloch