diff --git "a/\352\271\200\354\210\230\353\271\210/4\354\236\245/item19.md" "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item19.md"
new file mode 100644
index 0000000..c56443f
--- /dev/null
+++ "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item19.md"
@@ -0,0 +1,104 @@
+## 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
+
+### 상속용 클래스가 지켜야 할 것들
+- 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야 한다.
+ - 어떤 순서로 호출하는지, 호출 결과가 이어지는 처리에 어떤 영향을 주는지도 담아야 한다.
+ - 재정의 가능 메서드란 public, protected 중 final이 아닌 모든 메서드를 말한다.
+ - 재정의 가능한 메서드를 호출할 수 있는 모든 상황을 문서로 남기는 것이 좋다.
+ - 백그라운드 스레드나 정적 초기화 과정에서 호출될 수도 있으므로 유의하자.
+
+### Implentation Requirements와 @implSpec 태그 - remove() 의 예
+API 문서 메서드 설명 끝에서 발견할 수 있는 문구 중 Implementation Requirements가 있다.
이 절은 메서드 주석에 @implSpec 태그를 붙이면 자바독 도구가 생성해준다.
+
+```java
+/**
+* {@inheritDoc}
+*
+* @implSpec
+* This implementation iterates over the collection looking for the
+* specified element. If it finds the element, it removes the element
+* from the collection using the iterator's remove method.
+*
+*
Note that this implementation throws an
+* {@code UnsupportedOperationException} if the iterator returned by this
+* collection's iterator method does not implement the {@code remove}
+* method and this collection contains the specified object.
+*
+* @throws UnsupportedOperationException {@inheritDoc}
+* @throws ClassCastException {@inheritDoc}
+* @throws NullPointerException {@inheritDoc}
+*/
+public boolean remove(Object o) {
+ Iterator This method is called by the {@code clear} operation on this list
+ * and its subLists. Overriding this method to take advantage of
+ * the internals of the list implementation can substantially
+ * improve the performance of the {@code clear} operation on this list
+ * and its subLists.
+ *
+ * @implSpec
+ * This implementation gets a list iterator positioned before
+ * {@code fromIndex}, and repeatedly calls {@code ListIterator.next}
+ * followed by {@code ListIterator.remove} until the entire range has
+ * been removed. Note: if {@code ListIterator.remove} requires linear
+ * time, this implementation requires quadratic time.
+ *
+ * @param fromIndex index of first element to be removed
+ * @param toIndex index after last element to be removed
+ */
+protected void removeRange(int fromIndex, int toIndex) {
+ ListIterator@implSpec은 이 클래스를 상속하여 메서드를 재정의했을 때 나타날 효과를 상세히 설명하고 있다.
+ - 이 주의점을 통해 우리는 어떤 메서드를 어떤 방식으로 상속해야 할지 알 수 있다.
+ - 상속용 클래스가 지켜야 할 좋은 문서화의 예이다.
+
+### 훅(hook) 메서드 공개하기 - removeRange() 의 예
+```java
+/**
+ * Removes from this list all of the elements whose index is between
+ * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
+ * Shifts any succeeding elements to the left (reduces their index).
+ * This call shortens the list by {@code (toIndex - fromIndex)} elements.
+ * (If {@code toIndex==fromIndex}, this operation has no effect.)
+ *
+ * final로 만들어 상속을 금지한다.
+ - 모든 생성자를 private 혹은 package-private으로 선언하고 public 정적 팩터리를 만든다.
+- 혹여나 일반 클래스에서 상속을 허용하고 싶다면, 재정의 가능 메서드는 절대 사용하지 않도록 문서에 표기하자.
+
+### 정리
+- 상속용 메서드를 만들 때는 클래스 내부에서 스스로를 어떻게 사용하는지 문서로 남기자.
+- 문서화한 것은 그 클래스가 쓰이는 한 반드시 지키자.
+ - 그렇지 않을 경우 하위 클래스의 오동작을 만들 수 있다.
+- 클래스를 확장해야 할 명확한 이유가 떠오르지 않으면 상속을 금지하자.
+ - 클래스를 final로 만들거나 생성자를 모두 외부에서 접근 불가능하게 바꾸면 된다.
\ No newline at end of file
diff --git "a/\352\271\200\354\210\230\353\271\210/4\354\236\245/item20.md" "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item20.md"
new file mode 100644
index 0000000..4fc3ab5
--- /dev/null
+++ "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item20.md"
@@ -0,0 +1,74 @@
+## 추상 클래스보다는 인터페이스를 우선하라
+
+### 추상 클래스와 인터페이스
+- 공통점
+ - 메서드의 시그니쳐만 만들고 구현을 구현 클래스에게 맡긴다.
+- 차이점
+ - 추상클래스: 단일 상속만 가능하다. 구현체는 추상클래스의 하위 클래스가 된다.
+ - 인터페이스: 다중 상속이 가능하다. 인터페이스를 구현했다면, 같은 타입으로 취급된다.
+
+### 인터페이스의 장점 활용하기
+1. 믹스인 (mixin)
+- 믹스인: 구현 클래스에 '선택적 행위'를 제공한다고 선언하는 효과를 준다.
+- ex) Comparable, Iterable, AutoCloseable, Serializable
+추상 클래스는 이미 다른 클래스를 상속하는 클래스의 경우, 해당 클래스가 두 부모 클래스를 가질 수는 없으므로 믹스인으로 사용될 수 없다.
+
+2. 계층이 없는 타입 프레임워크
+```java
+public class Item20Test {
+ interface Singer {
+ void Sing();
+ }
+
+ interface Songwriter {
+ void compose(int chartPosition);
+ }
+
+ interface SingerSongWriter extends Singer, Songwriter {
+ void strum();
+ }
+}
+```
+- SingerSongWriter 인터페이스처럼 인터페이스는 다른 인터페이스를 상속할 수 있다.
+- 인터페이스의 상속은 상속이라는 단어는 사용하지만, 클래스의 상속처럼 부모, 자식 계층이 존재하지 않는다.
+ - 부모 클래스의 생성자를 호출할 필요 없다.
+ - 부모 클래스의 구현 내용도 이어받지 않는다.
+ - 정의된 메서드들만 구현하면 된다.
+- 클래스로 이와 같은 구조를 구현하려면, 상하 관계를 따져보며 차례로 단일 상속을 받아야 한다.
+ - 만든 이후에도 클래스 상속이 갖는 여러가지 제약을 갖게 된다.
+
+3. 골격 구현(템플릿 메서드 패턴) 활용
+- 인터페이스로는 타입 정의 및 몇가지 디폴트 클래스를 구현한다.
+- 골격 구현 추상 클래스로 나머지 메서드들까지 구현한다.
+```java
+static List
인터페이스 디폴트 메서드가 갖는 한계를 추상클래스를 이용해서 벗어난다.
+
+
+인터페이스를 구현한 클래스에서 골격 구현을 확장한 private 내부 클래스를 정의하고, 각 메서드 호출을 내부 클래스의 인스턴스에 전달하여 활용할 수도 있다.
이는 래퍼 클래스에서의 활용법과 비슷하다.
이 방식을 시뮬레이트한 다중 상속이라 하고, 다중 상속의 많은 장점을 제공하며 동시에 단점은 피하게 해준다.
\ No newline at end of file
diff --git "a/\352\271\200\354\210\230\353\271\210/4\354\236\245/item21.md" "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item21.md"
new file mode 100644
index 0000000..657e41b
--- /dev/null
+++ "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item21.md"
@@ -0,0 +1,118 @@
+## 인터페이스는 구현하는 쪽을 생각해 설계하라
+
+
+### 기존 인터페이스에 디폴트 메서드 구현을 추가하는 것은 위험한 일이다.
+
+1. 디폴트 메서드는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 '삽입' 될 뿐이다.
+
+
+
+- 디폴트 메서드 : 인터페이스에 있는 구현 메서드 (메서드 앞에 default 예약어. 구현부 {} 가 있다.)
+
+ - 기본 메서드는 이미 구현되어 있기 때문에 호출하여 사용할 수 있다.
+```java
+public interface MyInterface {
+ // 추상 메서드
+ void abstractMethod();
+
+ // 기본 메서드
+ default void defaultMethod() {
+ // 기본 구현 코드
+ System.out.println("This is a default method.");
+ }
+}
+```
+```java
+public class MyClass implements MyInterface {
+ @Override
+ public void abstractMethod() {
+ // 추상 메서드 구현 코드
+ System.out.println("Abstract method implementation.");
+ }
+
+ public static void main(String[] args) {
+ MyClass obj = new MyClass();
+ obj.abstractMethod(); // 출력 : Abstract method implementation.
+ obj.defaultMethod(); // 출력 : This is a default method.
+ }
+}
+```
+
+
+
+
+예시 ) Collection에 있는 removeIf 메서드
+
+```java
+// Collection.java
+default boolean removeIf(Predicate super E> filter) {
+ Objects.requireNonNull(filter);
+ boolean removed = false;
+ final Iterator중첩 클래스 : 다른 클래스 안에 정의된 클래스
+- 중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야한다. 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야한다.
+- 종류
+ - 정적 멤버 클래스
+ - (비정적) 멤버 클래스
+ - 익명 클래스
+ - 지역 클래스
+1. 정적 멤버 클래스
+
+- 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버 에도 접근할 수 있음 (일반 클래스와의 차이점)
+
+- 일반 클래스처럼 독립적으로 동작할 수 있으며, 바깥 클래스의 인스턴스 없이도 생성 가능.
+
+- 멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들자.
+```java
+public class OuterClass {
+
+ // private 멤버
+ private final String secret2 = "This is a secret!";
+
+ // 정적 멤버 클래스
+ public static class NestedStaticClass {
+
+ public void printSecret() {
+
+ // 바깥 클래스의 private 멤버에 접근
+ OuterClass outerClass = new OuterClass();
+ System.out.println("Accessing private member: " + outerClass.secret2);
+
+ }
+ }
+
+ public static void main(String[] args) {
+ // 정적 멤버 클래스의 인스턴스 생성
+ OuterClass.NestedStaticClass nested = new OuterClass.NestedStaticClass();
+ nested.printSecret(); // 출력: Accessing private member: This is a secret!
+ }
+
+}
+```
+
+
+
+
+2. 비정적 멤버 클래스
+
+- static이 없는 내부 클래스.비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결
+
+- 비정적 멤버 클래스는 바깥 인스턴스 없이는 생성 불가능.
+
+- 내부 클래스가 외부의 멤버를 사용하지 않아도, 숨겨진 외부 참조가 생성됨.
+```java
+OuterClass$NestedStaticClass.class
+
+class OuterClass$NestedStaticClass {
+ int innerClass;
+
+ OuterClass$NestedStaticClass(final OuterClass this$0) {
+ this.this$0 = this$0;
+ this.innerClass = 20;
+ }
+}
+ ```
+
+
+
+클래스명.this 형태로 바깥 클래스의 이름을 명시하는 용법을 사용하여 바깥 인스턴스의 참조를 가져올 수 있음.
+
+- 정규화 this : 일반적으로는 내부 클래스에서 바깥 클래스의 멤버를 자연스럽게 접근할 수 있으므로 필요한 경우에만 사용
+
+
+
+
+```java
+public class OuterClass {
+ private final String instanceSecret = "Instance secret!";
+
+ // 정적 멤버 클래스
+ class NestedStaticClass {
+
+ public void printInstanceSecret() {
+ // 바깥 클래스의 인스턴스를 통해 private 멤버에 접근
+ System.out.println("Accessing instance private member: " + OuterClass.this.instanceSecret);
+ System.out.println("Accessing private member: " + instanceSecret);
+ }
+ }
+
+ public static void main(String[] args) {
+ OuterClass outer = new OuterClass(); // 바깥 클래스 인스턴스 생성
+ outer.new NestedStaticClass().printInstanceSecret();
+ }
+}
+ ```
+
+### static을 생략하면 바깥 인스턴스로의 숨은 외부 참조를 갖게 됨. 참조 관리에 신경쓰지 않으면 메모리 누수 발생 가능.
+
+비정적 멤버 클래스의 인스턴스가 바깥 클래스의 인스턴스를 암묵적으로 참조하므로, 바깥 클래스 인스턴스는 비정적 멤버 클래스의 참조가 살아 있는 한 수거되지 않음
+3. 익명 클래스
+
+- 쓰이는 시점에 선언과 동시에 인스턴스가 만들어짐. 코드의 어디서든 생성 가능
+
+- 자바8부터 람다가 대체함 (함수형 인터페이스-추상메서드 하나 인 경우)
+```java
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class Main {
+ public static void main(String[] args) {
+ String[] names = {"Alice", "Bob", "Charlie"};
+
+ Arrays.sort(names, new Comparator비정적으로, 그렇지 않으면 정적
+
+- 중첩 클래스가 한 메서드 안에서만 쓰이면서 그 인스턴스를 생성하는 지점이 단 한 곳이고 해당 타입으로 쓰기에 적합한 클래스나 인터페이스가 이미 있다면 익명 클래스로 만들고, 그렇지 않으면 지역 클래스
\ No newline at end of file
diff --git "a/\352\271\200\354\210\230\353\271\210/4\354\236\245/item25.md" "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item25.md"
new file mode 100644
index 0000000..d44fdca
--- /dev/null
+++ "b/\352\271\200\354\210\230\353\271\210/4\354\236\245/item25.md"
@@ -0,0 +1,59 @@
+## 톱 레벨 클래스는 한 파일에 하나만 담으라
+
+### 두 클래스가 한 파일에 정의되어 있을 때
+
+Utensil.java
+```java
+class Utensil {
+ static final String NAME = "pan";
+}
+
+class Dessert {
+ static final String NAME = "cake";
+}
+```
+Dessert.java
+```java
+class Utensil {
+ static final String NAME = "pot";
+}
+
+class Dessert {
+ static final String NAME = "pie";
+}
+```
+Main.java
+```java
+public class Main {
+ public static void main(String[] args) {
+ System.out.println(Utensil.NAME + Desert.NAME);
+ }
+}
+```
+- 위는 Utensil.java와 Dessert.java라는 두 개의 파일에 중복으로 정의된 2개의 클래스의 예이다.
+- 위와 같은 경우 javac 명령어에 들어가는 인수에 따라 실행결과가 달라진다.
+ - javac Main.java Dessert.java: 에러, Utensil과 Dessert 클래스가 중복 정의되었습니다.
+ - javac Main.java, javac Main.java Utensil.java: "pancake" 출력
+ - javac Dessert.java Main.java: "potpie" 출력
+
+- 파일을 나누면 위와 같은 복잡한 동작원리도 알 필요 없고, 잠재적 에러도 없으므로 Utensil.java와 Dessert.java 각 파일별로 클래스는 1개씩만 선언하는 것이 좋다.
+### 굳이 한 파일에 여러 클래스를 정의하고 싶다면?
+```java
+public class Test {
+ public static void main(String[] args) {
+ System.out.println(Utensil.NAME + Dessert.NAME);
+ }
+
+ private static class Utensil {
+ final String NAME = "pan";
+ }
+
+ private static class Dessert {
+ final String NAME = "cake";
+ }
+}
+```
+### 정리
+
+- 소스파일 하나에는 반드시 톱레벨 클래스(혹은 톱레벨 인터페이스)를 하나만 담자.
+- 한 파일 내부에 클래스를 여러 개를 정의하면 아무런 이득 없이 괜히 에러만 발생한다.
\ No newline at end of file
diff --git "a/\352\271\200\354\210\230\353\271\210/5\354\236\245/item26.md" "b/\352\271\200\354\210\230\353\271\210/5\354\236\245/item26.md"
new file mode 100644
index 0000000..2947b3b
--- /dev/null
+++ "b/\352\271\200\354\210\230\353\271\210/5\354\236\245/item26.md"
@@ -0,0 +1,79 @@
+## 로 타입은 사용하지 말라
+
+
+
+### 로 타입 : 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않은 것
+
+ex) List