==객체 생성과 파괴== ===01.생성자 대신 정적 팩터리 메서드를 고려하라===
- 장점 ** 이름을 갖을수 있다(BigInteger.probablePrime 의미를 알수있다) ** 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다(immutable class, Boolean.valueOf(boolean)) ** 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다(엄청난 유연성 Collections) ** 입력 매개 변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다(EnumSet) ** 정작 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다(Service provider framework 근간, JDBC)
- 단점 ** 생성자가 없어 상속을 할 수 없다 ** 정적 팩터리 메서드는 프로그래머가 찾기 어렵다
- 이름별 의미 ** from: 매개 변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 형변환 메서드(Date.from) ** of: 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계메서드(EnumSet.of) ** valueOf: from과 of의 더 자세한 버전(BigInteger.valueOf) ** getInstance: 매개변수를 받으면 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않는다(StackWalker.getInstance) ** newInstance: 항상 새로운 인스턴스를 생성해 반환함을 보장한다(Array.newInstance) ** get(Type): 생성할 클래스가 아닌 반환할 객체의 타입을 반환, 다른 클래스의 팩터리 메서드를 정의할 때 쓴다(Files.getFileStore) ** new(Type): 생성할 클래스가 아닌 반환할 객체의 타입을 반환, 다른 클래스의 팩터리 메서드를 정의할 때 쓴다(새로운 인스턴스, Files.newBufferdReader) ** (type): getType, newType의 간결한 버전(Collections.list)
===02. 생성자에 매개변수가 많다면 빌더를 고려하라=== ===03. private 생성자나 열거 타입으로 싱글턴임을 보장하라=== ===04. 인스턴스화를 막으려거든 private 생성자를 사용하라===
===05. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라===
- 팩터리 메서드패턴
===06. 불필요한 객체 생성을 피하라===
- 정규식 캐싱
- 기본 타입 사용
===07. 다쓴 객체 참조를 해제하라===
===08.=== ===09.=== ==모든 객체의 공통 메서드== ===10.=== ===11.=== ===12.=== ===13.=== ===14.=== ==클래스와 인터페이스== ===15.=== ===16.=== ===17.=== ===18.===
=== 19. 상속을 고려해 설계하고 문서화 하라. 그러지 않았다면 상속을 금지하라 ===
- 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용해야하는지 문서로 남겨야한다.
- 재정의할 수 있는 메서드는 public, protected 접근제한제를 가진 메서드중 final이 아닌 메서드를 말한다.
- 문서는 @implSpec 태그를 메서드 주석에 붙이고 -tag “implSpec:a:Implementation Requirements:”를 지정해주면 javadoc이 태그를 활성화한다.
- 상속용 클래스틑 하위 클래스를 만들어 검증해야한다
- 하위 클래스 생성자는 재정의 가능 메서드를 호출해서는 안된다.
===20.===
===21.인터페이스는 구현하는 쪽을 생각해 설계하라===
- 인터페이스에 디폴트 메서드를 선언하면 구현하지 않은 모든 클래스에서 디폴트 구현이 쓰이게된다.
- 예를 들어 아파치 SynchronizedCollection이 removeIf를 재구현하지 않았다
- 디폴트 메서드는 기존 구현체에 런타임 오류를 일으킬 수 있다.
- 디폴트 메서드는 표준적인 메서드 구현을 제공하는 데 아주 유용한 수단이다.
===22.인터페이스는 타입을 정의하는 용도로만 사용하라===
- 상수 인터페이스틑 안티패턴이다
- 상수는 내부 구현이다
- 숫자 리터럴에 밑줄을 사용할수 있다
- 상수 클래스를 사용하고 인스턴스화할 수 없는 유틸리티 클래스를 만들어라
public class PhysicalConstants { private PhsicalConstants() {}
public static final double AVOGARDROS_NUMBER = 6.022_140_857e23; }
</source>
===23. 태그달린 클래스보다는 클래스 계층구조를 활용하라=== ===24. 멤버 클래스는 되도록 static으로 만들라===
- 중첩 클래스(nested class)란 다른 클래스 안에 정의된 클래스를 말한다
- 정적(static) 멤버 클래스 ** 나머지와 다르게 내부 클래스(inner class)가 아니다 ** 바깥 클래스 private 멤버에도 접근이 가능하다 ** 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스(예 Calculator.Operation.PLUS) ** private 정적 멤버 클래스는 흔히 바깥 클래스가 표현하는 객체의 한 부분(구성요소)을 나타낼 때 쓴다(map의 키값을 표현하는 엔트리의 getKey, getValue, setValue는 map을 직접 사용하지 않는다)
- 멤버 클래스 ** 비정적 멤버 클래스의 인스턴스는 this를 사용해 바깥 인스턴스의 참조를 가져올 수 있다 ** 비정적 멤버 클래스는 바깥 인스턴스 없이는 생성할 수 없다(독립적으로 있어야하면 정적 멤버 클래스) ** 비정적 멤버 클래스는 바깥 인스턴스와 동시에 만들어 지거나 수동으로 만든다 ** 비정적 멤버 클래스는 어댑터를 정의 할때 자주 쓰인다(Map의 keySet, entrySet, values등 컬랙션뷰과 Set, List의 반복자들을 구현할때) ** 바깥인스턴스 접근할 일이 없다면 static으로 정적 멤버 클래스로 만들자 ** 비정적 멤버 클래스의 바깥 클래스의 인스턴스는 수거(GC)가 되지 못하거나 참조 때문에 시간 공간이 낭비된다
- 익명 클래스 ** 이름이 없다 ** 바깥 클래스의 멤버도 아니다 ** 쓰이는 시점에 선언과 동시에 인스턴스가 만들어진다 ** 상수 변수 이외의 정적 멤버는 가질 수 없다 ** 초기화된 final 기본 타입과 문자열 필드만 가질 수 있다 ** 표현식 중간에 등장하므로 길면 가독성이 떨어진다 ** 작은 함수 객체나 처리 객체를 만드는대 사용했지만 람다가 그 역할을 대신한다 ** 정적 팩터리 메서드를 구현할때 쓰였다(intArrayAsList 참고)
- 지역 클래스 ** 지역변수를 선언할 수 있는 곳이면 어디서든 선언 할수 있고 유효범위도 지역변수와 같다
===25. 톱레벨 클래스는 한 파일에 하나만 담으라===
- 두클래스가 한 파일에 있으면 안된다
- 하나를 정적 멤버 클래스로 만들거나 두개의 파일로 분리하자
==제네릭== ===26. raw 타입은 사용하지 말라===
- List 인터페이스는 타입 매개변수 E를 받는다
- List
가 인터페이스의 이름이 된다 - 타입 매개변수를 받는 클래스와 인터페이스를 제네릭 클래스, 제네릭 인터페이스라고 하며 통틀어 제네릭 타입이라고 한다
- List
은 원소 타입이 String인 매개변수화 타입이라고 한다 - List는 제네릭 타입을 정의 하며 같이 정의 되는 raw 타입이며 컴파일 타임에 타입 오류가 발생하지 않기 때문에 사용하지 말아야 한다
- Collection<?>의 ?은 와일드 카드 타입이다
- 와일드 카드 타입은 안전하다
-
한정적 타입 매개변수 - <T extends Comparable
> 재귀적 타입 한정 - List<? extends Number> 한정적 와일드카드 타입
- static
List asList(E[] a) 제네릭 메서드 - 예외1: class 리터럴에 매개변수화 타입을 사용하지 못한다 ** List.class로 사용 ** List
.class 사용불가 - 예외2: instanceof연산자 사용시 raw타입을 사용한다
if (o instanceof Set) { Set<?> s = (Set<?>) o; … } </source>
===27. 비검사 경고를 제거하라===
// 경고 발생
Set<Lark> exaltation = new HashSet();
// 자바7에서 제공하는 다이아몬드 연산자를 사용하면 실제 타입을 추론해줘서 해결된다
Set<Lark> exaltation = new HashSet<>();
</source>
javac -Xlint:uncheck 옵션을 사용할경우 uncheckd conversion 비검사 경고와 함께 설명해준다.
가능하면 비검사 경고를 모두 제거해야한다.
그렇지 않다면 런타임에 ClassCastException이 발생한다.
타입이 안전하다고 확신할 수 있다면 @SuppressWarnings(“unchecked”) 어노테이션으로 경고를 숨기고 주석을 달아야한다.
===28. 배열보다는 리스트를 사용하라===
- 배열은 공변(cocariant)이다. Child[]는 Parent[]의 하위 타입이된다.
- 제네릭은 불공변(invariant)이다. 각각의 리스트는 하위 타입도 상위 타입도 아니다.
- 배열은 실체화 된다. 런타임에도 원소 타입을 인지하고 확인한다.
- 제네릭은 런타임에 타입 정보가 소거된다. 실체화가 불가능 하다(비한정적 와일드 타입은 가능)
- 배열은 런타임에 안전하고 컴파일에 안전하지 않다. (런타임에 실패한다)
- 제네릭은 런타임에 안전하지 않고 컴파일에 안전하다. (컴파일에 실패한다)
- 둘을 섞어 쓰기 힘들고 오류나 경고를 만나면 배열을 리스트로 대체하자.
===29. 이왕이면 제네릭 타입으로 만들어라===
- 클라이언트에서 제네릭으로 변환하기 보다 제네릭 타입이 안전하고 편하다
- public Object[] elements; 대신 private E[] elements;를 사용해라
// 실체화 불가 타입으로 new를 할때 사용한다
@SuppressWarning("unchecked")
return (E[]) new Object[];
</source>
-
같이 제한을 두면 바로 가능하다 - 배열이 아닌 리스트를 성능을 위해 사용할 때도 있다
===30. 이왕이면 제네릭 메서드로 만들어라===
- 메서드도 제네릭으로 만들면 안전하고 편하다
- Collections의 sort, binarySearch는 모두 제네릭 메서드이다
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
}
</source>
- identify function 항등함수(입력 값을 수정 없이 그대로 반환하는 특별함수)의 경우 Function.identify를 사용할수 있지만 직접 구현할수 있다
// 제네릭 싱글턴 팩터리 패턴
private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;
@SuppressWarnings("unchecked")
public static <T> UnaryOperator<T> identityFunction() {
return (Unaryoperator<T>) IDENTITY_FN;
}
// 사용
Unaryoperator<String> a = identityFunction();
for (String s : arr)
System.out.println(a.apply(s));
</source>
- 재귀적 한정타입
public statc <E extends Compable<E>> E max(Collection<E> o) {
if(o.isEmpty())
throw new IllegalArgumentException("비었음");
E result = null;
for (E e : o)
if (result == null || e.compareTo(result) > 0)
result = Objects.requireNonNull(e);
return result;
}
</source>
===31. === ===32. === ===33. ===
==열거 타입과 애너테이션== ===34. === ===35. === ===36. === ===37. === ===38. === ===39. === ===40. === ===41. ===
==람다와 스트림== ===42. === ===43. === ===44. === ===45. === ===46. === ===47. === ===48. ===
==메서드== ===49. === ===50. === ===51. === ===52. === ===53. === ===54. === ===55. === ===56. ===
==일반적인 프로그래밍 원칙== ===57. === ===58. === ===59. === ===60. === ===61. === ===62. === ===63. === ===64. === ===65. === ===66. === ===67. === ===68. ===
==예외== ===69. === ===70. === ===71. === ===72. === ===73. === ===74. === ===75. === ===76. === ===77. ===
==동시성== ===78. === ===79. === ===80. === ===81. === ===82. === ===83. === ===84. ===
==직렬화== ===85. === ===86. === ===87. === ===88. === ===89. === ===90. ===
== 참고링크 ==
- [https://github.com/keesun/study/tree/master/effective-java java effective java 요약]