diff --git "a/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23424_\353\251\244\353\262\204_\355\201\264\353\236\230\354\212\244\353\212\224_\353\220\230\353\217\204\353\241\235_static_\354\234\274\353\241\234_\353\247\214\353\223\244\353\235\274.md" "b/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23424_\353\251\244\353\262\204_\355\201\264\353\236\230\354\212\244\353\212\224_\353\220\230\353\217\204\353\241\235_static_\354\234\274\353\241\234_\353\247\214\353\223\244\353\235\274.md" new file mode 100644 index 0000000..9cf8696 --- /dev/null +++ "b/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23424_\353\251\244\353\262\204_\355\201\264\353\236\230\354\212\244\353\212\224_\353\220\230\353\217\204\353\241\235_static_\354\234\274\353\241\234_\353\247\214\353\223\244\353\235\274.md" @@ -0,0 +1,72 @@ +# 아이템 24. 멤버 클래스는 되도록 static 으로 만들라 + +중첩 클래스(nested class) : 다른 클래스 안에 정의된 클래스 +중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 하며, 그 외에 쓰임새가 있다면 톱레벨 클래스로 만들어야 함. + +중첩 클래스 종류 +- 정적 멤버 클래스 +- (비정적) 멤버 클래스 +- 익명 클래스 +- 지역 클래스 + +정적 멤버 클래스를 제외하고는 모두 inner class이다. + +정적 멤버 클래스는 다른 클래스 안에 선언되고, 바깥 클래스의 private member에도 접근할 수 있다는 점만 제외하고는 일반 클래스와 똑같다. 정적 멤버 클래스는 다른 정적 멤버와 똑같은 접근 규칙을 적용 받는다. 예컨대 private으로 선언하면 바깥 클래스에서만 접근할 수 있는 방식이다. + +정적 멤버 클래스는 흔히 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰임. + + +정적 멤버 클래스와 비정적 멤버 클래스의 구문상 차이는 단지 static이 붙어 있고 없고 뿐이지만, 의미상 차이는 꽤 크다. + +비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다. +비정적 멤버 클래스의 인스턴스 메서드에서 정규화된 this를 사용해 바깥 인스턴스 메소드를 호출하거나 참조를 가져올 수 있다. + +=> 중첩 클래스 인스턴스와 바깥 인스턴스가 독립적으로 존재할 수 있다면 정적 클래스로 만들어야 한다. + +비정적 멤버 클래스의 인스턴스와 바깥 인스턴스 사이의 관계는 멤버 클래스가 인스턴스화 될 때 확립되며, 변경할 수 없다. +-> 바깥 클래스의 인스턴스 메서드에서 비정적 멤버 클래스의 생성자를 호출할 때 자동으로 만들어지는 게 보통이지만, 직접 `바깥인스턴스Class.new Member Class(args);`를 호출해 만들기도 한다. + +=> 비정적 멤버 클래스의 인스턴스안에 관계정보가 만들어져 메모리를 차지하고, 생성 시간도 더 걸린다. + +비정적 멤버 클래스는 어댑터를 정의할 떄 자주쓰임. +-> 인스턴스를 갑싸 마치 다른 클래스의 인스턴스처럼 보이게 하는 뷰로 사용 +ex) Map 인터페이스 구현체 + +**멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.** + +static 생략 => +1. 바깥 인스턴스로의 숨은 외부 참조를 갖게 된다. -> 시간, 공간 +2. 가비지 컬렉션이 바깥 클래스의 인스턴스를 수거하지 못하는 메모리 릭 + +private 정적 멤버 클래스는 흔히 바깥 클래스가 표현하는 객체의 한 부분을 나타낼 때 쓴다. +키와 값을 매핑시키는 Map 인스턴스를 생각해봊자. + +많은 Map 구현체는 각각의 키-쌍 값을 표현하는 엔트리(Entry) 객체들을 가지고 있다. 모든 엔트리가 맵과 연관되어 있지만, 엔트리의 메서드들은 맵을 직접 사용하지는 않는다. +=>private 정적 멤버 클래스가 좋음. + + +멤버 클래스가 공개된 클래스의 Public이나 Protected 멤버 => 정적 여부가 중요햐짐. + + +### 익명 클래스 +- 이름이 없다. +- 익명 클래스는 바깥 클래스의 멤버도 아니다. +- 익명 클래스는 응용시에 제약이 많다. +- 정적 팩토리 메서드를 구현할 때 사용 +- 짧지 않으면 가독성이 떨어짐. + + +### 지역 클래스 +- 지역변수를 선언할 수 있는 곳이면 어디서든 선언할 수 있고, 유효 범위도 지역 변수와 동일 +- 멤버 클래스처럼 이름이 있고 반복 사용 가능 +- 익명 클래스 처럼 비정적 문맥에서 사용될 때만 바깥 인스턴스를 참조할 수 있음. +- 정적 멤버는 가질 수 없고, 가독성을 위해 짧게 작성해야함. + + +### 핵심정리 +메서드 밖에서도 사용해야 하고, 메서드 안에 정의하기 길다면 멤버 클래스 +멤버 클래스의 인스턴스 각각이 바깥 인스턴스를 참조하면 비정적, 아니면 정적 + +중첩 클래스가 한 메소드안에서만 쓰이면서 그 인스턴스를 생성하는 지점이 단 한 곳이고 해당 타입으로 쓰기에 적합한 클래스나 인터페이스가 이미 있다면, 익명 클래스, 아니면 지역 클래스 + + diff --git "a/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23425_\355\206\261\353\240\210\353\262\250_\355\201\264\353\236\230\354\212\244\353\212\224\355\225\234_\355\214\214\354\235\274\354\227\220_\355\225\230\353\202\230\353\247\214_\353\213\264\354\234\274\353\235\274.md" "b/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23425_\355\206\261\353\240\210\353\262\250_\355\201\264\353\236\230\354\212\244\353\212\224\355\225\234_\355\214\214\354\235\274\354\227\220_\355\225\230\353\202\230\353\247\214_\353\213\264\354\234\274\353\235\274.md" new file mode 100644 index 0000000..61f0893 --- /dev/null +++ "b/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23425_\355\206\261\353\240\210\353\262\250_\355\201\264\353\236\230\354\212\244\353\212\224\355\225\234_\355\214\214\354\235\274\354\227\220_\355\225\230\353\202\230\353\247\214_\353\213\264\354\234\274\353\235\274.md" @@ -0,0 +1,19 @@ +# 아이템 25. 톱레벨 클래스는 한 파일에 하나만 담으라. + +소스 파일 하나에 Top-Level class를 여러 개 선언해도 문제는 없다. -> But, 득이 없다 + +```Java +// Utensil.java에 정의된 2개 클래스 + +class Utensil { + static final String NAME = "pan"; +} + +class Dessert { + static final String NAME = "pie"; +} +``` + +이와 같이 정의되면 때에 따라 어떤 소스파일을 컴파일 하냐에 따라서 동작이 달라질 수 있다. + +따라서 분리하자. diff --git "a/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23426_raw_type\354\235\200_\354\202\254\354\232\251\355\225\230\354\247\200_\353\247\220\353\235\274.md" "b/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23426_raw_type\354\235\200_\354\202\254\354\232\251\355\225\230\354\247\200_\353\247\220\353\235\274.md" new file mode 100644 index 0000000..6bd7905 --- /dev/null +++ "b/unan/week7/\354\234\240\353\202\234-7\354\243\274\354\260\250_\354\225\204\354\235\264\355\205\23426_raw_type\354\235\200_\354\202\254\354\232\251\355\225\230\354\247\200_\353\247\220\353\235\274.md" @@ -0,0 +1,96 @@ +# 아이템 26. raw type은 사용하지 말라. + +generic, generic interface : 클래스와 인터페이스 선언에 타입 매개변수(type parameter)까 쓰인 경우 + +제네릭 클래스, 인터페이스를 통틀어 generic type이라고 한다. + +제네릭 타입은 일련의 parameterized type을 정의한다. + +마지막으로 제네릭 타입을 하나 정의 하면 그에 딸린 Raw type도 함께 정의된다. + + Raw type : 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을 때, + Raw Type은 타입 선언에서 제네릭 타입 정보가 전부 지워진 것처럼 동작함. + + +#### 잘못된 예시 + +```Java + +// Stamp 인스턴스만 취급한다. +private final Collection stamps = ...; + + +``` + +stamp 대신 coin을 넣어도 아무 문제 없이 실행된다. + + +#### 잘못된 예시 + +```Java +for (Iterator i = stamps.iterator(); i.hasNext();) { + Stamp stamp = (Stamp) i.next(); // ClassCastException을 던진다. + stamp.cancel(); +} +``` + +매개변수화된 컬렉션 타입 -> 타입 안정성 확보 +```Java +private final Collection stamps = ...; +``` + +Raw Type을 쓰는 것을 언어 레벨에서 막지 않았지만, 절대로 쓰지말자. +Raw type을 사용하면 제네릭이 안겨주는 안전성과 표현력을 모두 잃게 된다. + +그럼 Raw Type이 존재하는 이유는? +-> 제네릭이 없는 동안 작성된 코드들과의 호환성 + +List와 같은 Raw type은 안되지만, List 처럼 임의 객체를 허용하는 매개변수화 타입은 괜찮다. + + +### 원소의 타입을 몰라도 되는 Raw Type을 쓰고 싶은 경우 -> 비한정적 와일드카드 타입(unbounded wildcard type) + +```java +static int numElementsInCommon(Set s1, Set s2) { + ... +} +``` + +차이점 + - raw type 컬렉션은 아무 원소나 넣을 수 있어서 불변식을 훼손하기 쉽다. + - Collection null 외에는 어떤 원소도 넣을 . 수없다. + +### Raw type을 쓰자의 예외 +1. Class 리터럴에는 raw type을 쓰자. + - List.class, String[].class 허용. List.class , List s = (Set) o; // wildcard. 타입 + ... + } +``` +o의 타입이 Set임을 확인하고, 형 변환해야 컴파일러 경고가 뜨지 않는다. + +### 정리 + +Raw type -> 런타임 예외를 유발하니 사용하지 말자. (호환성 때문에 남아있음.) +Set -> 어떤 타입의 객체도 저장 가능 +Set 모종의 타입 객체만 저장 가능 +Raw 타입인 Set은 제네렉 타입 시스템에 속하지 않음. + +| | | | | +|---|---|---|---| +|매개변수화 타입|parameterized type|List|아이템 26| +|실제 타입 매개변수|actual type parameter|String|아이템 26| +|제네릭 타입|generic type|List|아이템 26,29| +|정규 타입 매개변수|formal type parameter||아이템 26| +|비한정적 와일드카드

타입|unbounded wildcard typ|List<?>|아이템 26| +|로 타입|raw type|List|아이템 26| +|한정적 타입 매개변수|bounded type parameter||아이템 29| +|재귀적 타입 한정|recursive type bound|> 아이템 30|| +|한정적 와일드카드

타입||bounded wildcard type List|아이템 31| +|제네릭 메서드|generic method|static <> List

asList(E[] a)|아이템 30| +|타입 토큰|type token|String.class|아이템 3|