From cd2384c93660f1d3429c43919db05eebef202a54 Mon Sep 17 00:00:00 2001 From: Lee yun bok <44944031+leeyunbo@users.noreply.github.com> Date: Sun, 12 Mar 2023 19:22:47 +0900 Subject: [PATCH] [yunbok] 2023-03-12 item22 ~ item24 --- src/docs/{wekk7 => week7}/item19.md | 0 src/docs/{wekk7 => week7}/item20.md | 0 src/docs/{wekk7 => week7}/item21.md | 0 src/docs/week8/item22.md | 16 +++++ src/docs/week8/item23.md | 58 +++++++++++++++++++ src/docs/week8/item24.md | 44 ++++++++++++++ .../item22/constantinterface/MyClass.java | 9 +++ .../constantinterface/PhysicalConstants.java | 13 +++++ .../PhysicalConstants.java | 18 ++++++ .../week8/item23/hierarchy/Circle.java | 10 ++++ .../week8/item23/hierarchy/Figure.java | 6 ++ .../week8/item23/hierarchy/Rectangle.java | 13 +++++ .../week8/item23/hierarchy/Square.java | 8 +++ .../week8/item23/taggedclass/Figure.java | 45 ++++++++++++++ .../week8/item24/adapter/AdapterInJava.java | 19 ++++++ .../item24/anonymousclass/IntArrays.java | 41 +++++++++++++ .../week8/item24/localclass/MyClass.java | 22 +++++++ .../week8/item24/memberclass/MySet.java | 30 ++++++++++ .../week8/item24/memberclass/OutterClass.java | 23 ++++++++ .../item24/staticmemberclass/OutterClass.java | 18 ++++++ 20 files changed, 393 insertions(+) rename src/docs/{wekk7 => week7}/item19.md (100%) rename src/docs/{wekk7 => week7}/item20.md (100%) rename src/docs/{wekk7 => week7}/item21.md (100%) create mode 100644 src/docs/week8/item22.md create mode 100644 src/docs/week8/item23.md create mode 100644 src/docs/week8/item24.md create mode 100644 src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/MyClass.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/PhysicalConstants.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item22/constantutilityclass/PhysicalConstants.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Circle.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Figure.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Rectangle.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Square.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item23/taggedclass/Figure.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item24/adapter/AdapterInJava.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item24/anonymousclass/IntArrays.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item24/localclass/MyClass.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item24/memberclass/MySet.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item24/memberclass/OutterClass.java create mode 100644 src/main/java/com/example/effectivejava3e/week8/item24/staticmemberclass/OutterClass.java diff --git a/src/docs/wekk7/item19.md b/src/docs/week7/item19.md similarity index 100% rename from src/docs/wekk7/item19.md rename to src/docs/week7/item19.md diff --git a/src/docs/wekk7/item20.md b/src/docs/week7/item20.md similarity index 100% rename from src/docs/wekk7/item20.md rename to src/docs/week7/item20.md diff --git a/src/docs/wekk7/item21.md b/src/docs/week7/item21.md similarity index 100% rename from src/docs/wekk7/item21.md rename to src/docs/week7/item21.md diff --git a/src/docs/week8/item22.md b/src/docs/week8/item22.md new file mode 100644 index 0000000..a31ac81 --- /dev/null +++ b/src/docs/week8/item22.md @@ -0,0 +1,16 @@ +# item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라. + +1. 상수를 정의하는 용도로 인터페이스를 사용하지 말 것! (안티패턴) +- 인터페이스의 원래 의도인 "타입을 정의하는 것"을 오염시키기 때문에 안티패턴이다. + - 클래스 내부에서 사용할 상수는 내부 구현(클래스 내부 정보)에 해당한다. + - 내부 구현을 클래스의 API로 노출하는 행위가 된다. + - 인터페이스를 통해 외부에 노출됨 + - 클라이언트에 혼란을 준다. + - 이 클래스가 인터페이스를 구현하고 있으면, "이 클래스가 이 인터페이스 타입이라는건가?", "`PysicalConstants myClass = new MyClass()` 이렇게 사용하라는건가?" 라며 혼란을 준다. + +2. 상수를 정의하는 방법 +- 특정 클래스나 인터페이스 + - 인터페이스는 최대한 자제하자, 인터페이스는 클래스와 다르게 implements를 막을 방법이 없음 +- 열거형 +- 인스턴스화 할 수 없는 유틸리티 클래스 + diff --git a/src/docs/week8/item23.md b/src/docs/week8/item23.md new file mode 100644 index 0000000..67a2400 --- /dev/null +++ b/src/docs/week8/item23.md @@ -0,0 +1,58 @@ +# item 23. 태그 달린 클래스보다는 클래스 계층 구조를 활용하라 + + +1. 태그 달린 클래스의 단점 +- 쓸데없는 코드가 많다. +- 가독성이 나쁘다. +- 메모리도 많이 사용한다. +- 필드를 final로 선언하려면 불필요한 필드까지 초기화해야 한다. +- 인스턴스 타입만으로는 현재 나타내는 의미를 알 길이 없다. + +2. 클래스 계층 구조로 바꾸면 모든 단점을 해결할 수 있다. (상속) + + +```java +class Figure { + enum Shape { RECTANGLE, CIRCLE, SQUARE }; + + // 태그 필드 - 현재 모양을 나타낸다. + final Shape shape; + + // 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다. + double length; + double width; + + // 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다. + double radius; + + // 원용 생성자 + Figure(double radius) { + shape = Shape.CIRCLE; + this.radius = radius; + } + + // 사각형용 생성자 + Figure(double length, double width) { + if (this.length == this.width) { + shape = Shape.SQUARE; + } else { + shape = Shape.RECTANGLE; + } + + this.length = length; + this.width = width; + } + + double area() { + switch(shape) { + case RECTANGLE, SQUARE: + return length * width; + case CIRCLE: + return Math.PI * (radius * radius); + default: + throw new AssertionError(shape); + } + } +} +``` +- Shape가 Circle이지만, Rectangle과 관련된 필드, 메서드들을 가지고 있음 \ No newline at end of file diff --git a/src/docs/week8/item24.md b/src/docs/week8/item24.md new file mode 100644 index 0000000..e8f2b43 --- /dev/null +++ b/src/docs/week8/item24.md @@ -0,0 +1,44 @@ +# item 24. 멤버 클래스는 되도록 static으로 만들라 + +1. 정적 멤버 클래스 +- 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스. 예) Calculator.Operation.PLUS (Enum) +- Outter 클래스와 독립적이다. +- Outter 클래스를 참조하지 않는 경우에 사용한다. + - 참조하는 곳이 있다면, 비정적 멤버 클래스로 만들 수 밖에 없다. + - 비정적 멤버 클래스는 암뭄적으로 바깥 인스턴스에 대한 참조가 생긴다. + - 이 말은 즉슨, Outter class 인스턴스 없이는 자기 자신을 생성할 수 없다. + - `InnerClass innerClass = new OutterClass().new InnerClass();` + +2. 비정적 멤버 클래스 +- 바깥 클래스의 인스턴스와 암묵적으로 연결된다. +- 어댑터를 정의할 때 자주 쓰인다. +- 멤버 클래스에서 바깥 인스턴스를 참조할 필요가 없다면 무조건 정적 멤버 클래스로 만들자. + +3. 익명 클래스 +- 바깥 클래스의 멤버가 아니며, 쓰이는 시점과 동시에 인스턴스가 만들어진다. +- 비정적인 문맥에서 사용될 때만 바깥 클래스의 인스턴스를 참조할 수 있다. +- 자바에서 람다를 지원하기 전에 즉석에서 작은 함수 객체나 처리 객체를 만들 때 사용했다. +- 정적 팩터리 메서드를 만들 때 사용할 수도 있다. + +4. 지역 클래스 +- 가장 드물게 사용된다. +- 지역 변수를 선언하는 곳이면 어디든 지역 클래스를 정의해 사용할 수 있다. +- 가독성을 위해 짧게 작성해야 한다. + + +#### 어댑터 패턴 +기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴 + - 클라이언트가 사용하는 인터페이스를 따르지 않는 기존 코드를 재사용할 수 있게 해준다. + +```java +try(InputStream is = new FileInputStream("number.txt"); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader reader = new BufferedReader(isr)) { + while(reader.ready()) { + System.out.println(reader.readLine()); + } +} catch (IOException e) { + throw new RuntimeException(e); +} +``` +- InputStream을 InputStreamReader로 사용할 수 있게끔 \ No newline at end of file diff --git a/src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/MyClass.java b/src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/MyClass.java new file mode 100644 index 0000000..c2fff1b --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/MyClass.java @@ -0,0 +1,9 @@ +package com.example.effectivejava3e.week8.item22.constantinterface; + +public class MyClass implements PhysicalConstants { + + public static void main(String[] args) { + System.out.println(BOLTZMANN_CONSTANT); + } + +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/PhysicalConstants.java b/src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/PhysicalConstants.java new file mode 100644 index 0000000..391fa92 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item22/constantinterface/PhysicalConstants.java @@ -0,0 +1,13 @@ +package com.example.effectivejava3e.week8.item22.constantinterface; + +// 코드 22-1 상수 인터페이스 안티패턴 - 사용금지! (139쪽) +public interface PhysicalConstants { + // 아보가드로 수 (1/몰) + static final double AVOGADROS_NUMBER = 6.022_140_857e23; + + // 볼츠만 상수 (J/K) + static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23; + + // 전자 질량 (kg) + static final double ELECTRON_MASS = 9.109_383_56e-31; +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item22/constantutilityclass/PhysicalConstants.java b/src/main/java/com/example/effectivejava3e/week8/item22/constantutilityclass/PhysicalConstants.java new file mode 100644 index 0000000..c0d84ed --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item22/constantutilityclass/PhysicalConstants.java @@ -0,0 +1,18 @@ +package com.example.effectivejava3e.week8.item22.constantutilityclass; + +// 코드 22-2 상수 유틸리티 클래스 (140쪽) +public class PhysicalConstants { + private PhysicalConstants() { } // 인스턴스화 방지 + + // 아보가드로 수 (1/몰) + public static final double AVOGADROS_NUMBER = 6.022_140_857e23; + + // 볼츠만 상수 (J/K) + public static final double BOLTZMANN_CONST = 1.380_648_52e-23; + + // 전자 질량 (kg) + public static final double ELECTRON_MASS = 9.109_383_56e-31; +} + + + diff --git a/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Circle.java b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Circle.java new file mode 100644 index 0000000..4b82758 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Circle.java @@ -0,0 +1,10 @@ +package com.example.effectivejava3e.week8.item23.hierarchy; + +// 코드 23-2 태그 달린 클래스를 클래스 계층구조로 변환 (144쪽) +class Circle extends Figure { + final double radius; + + Circle(double radius) { this.radius = radius; } + + @Override double area() { return Math.PI * (radius * radius); } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Figure.java b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Figure.java new file mode 100644 index 0000000..440c886 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Figure.java @@ -0,0 +1,6 @@ +package com.example.effectivejava3e.week8.item23.hierarchy; + +// 코드 23-2 태그 달린 클래스를 클래스 계층구조로 변환 (144쪽) +abstract class Figure { + abstract double area(); +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Rectangle.java b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Rectangle.java new file mode 100644 index 0000000..5ad7086 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Rectangle.java @@ -0,0 +1,13 @@ +package com.example.effectivejava3e.week8.item23.hierarchy; + +// 코드 23-2 태그 달린 클래스를 클래스 계층구조로 변환 (144쪽) +class Rectangle extends Figure { + final double length; + final double width; + + Rectangle(double length, double width) { + this.length = length; + this.width = width; + } + @Override double area() { return length * width; } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Square.java b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Square.java new file mode 100644 index 0000000..aaf16a4 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item23/hierarchy/Square.java @@ -0,0 +1,8 @@ +package com.example.effectivejava3e.week8.item23.hierarchy; + +// 태그 달린 클래스를 클래스 계층구조로 변환 (145쪽) +class Square extends Rectangle { + Square(double side) { + super(side, side); + } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item23/taggedclass/Figure.java b/src/main/java/com/example/effectivejava3e/week8/item23/taggedclass/Figure.java new file mode 100644 index 0000000..8351a52 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item23/taggedclass/Figure.java @@ -0,0 +1,45 @@ +package com.example.effectivejava3e.week8.item23.taggedclass; + +// 코드 23-1 태그 달린 클래스 - 클래스 계층구조보다 훨씬 나쁘다! (142-143쪽) +class Figure { + enum Shape { RECTANGLE, CIRCLE, SQUARE }; + + // 태그 필드 - 현재 모양을 나타낸다. + final Shape shape; + + // 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다. + double length; + double width; + + // 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다. + double radius; + + // 원용 생성자 + Figure(double radius) { + shape = Shape.CIRCLE; + this.radius = radius; + } + + // 사각형용 생성자 + Figure(double length, double width) { + if (this.length == this.width) { + shape = Shape.SQUARE; + } else { + shape = Shape.RECTANGLE; + } + + this.length = length; + this.width = width; + } + + double area() { + switch(shape) { + case RECTANGLE, SQUARE: + return length * width; + case CIRCLE: + return Math.PI * (radius * radius); + default: + throw new AssertionError(shape); + } + } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item24/adapter/AdapterInJava.java b/src/main/java/com/example/effectivejava3e/week8/item24/adapter/AdapterInJava.java new file mode 100644 index 0000000..369a85d --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item24/adapter/AdapterInJava.java @@ -0,0 +1,19 @@ +package com.example.effectivejava3e.week8.item24.adapter; + +import java.io.*; +import java.util.*; + +public class AdapterInJava { + + public static void main(String[] args) { + try(InputStream is = new FileInputStream("number.txt"); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader reader = new BufferedReader(isr)) { + while(reader.ready()) { + System.out.println(reader.readLine()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item24/anonymousclass/IntArrays.java b/src/main/java/com/example/effectivejava3e/week8/item24/anonymousclass/IntArrays.java new file mode 100644 index 0000000..555f475 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item24/anonymousclass/IntArrays.java @@ -0,0 +1,41 @@ +package me.whiteship.chapter04.item24.anonymousclass; + +import java.util.AbstractList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +// 코드 20-1 골격 구현을 사용해 완성한 구체 클래스 (133쪽) +public class IntArrays { + static List intArrayAsList(int[] a) { + Objects.requireNonNull(a); + + // 다이아몬드 연산자를 이렇게 사용하는 건 자바 9부터 가능하다. + // 더 낮은 버전을 사용한다면 로 수정하자. + return new AbstractList<>() { + @Override public Integer get(int i) { + return a[i]; // 오토박싱(아이템 6) + } + + @Override public Integer set(int i, Integer val) { + int oldVal = a[i]; + a[i] = val; // 오토언박싱 + return oldVal; // 오토박싱 + } + + @Override public int size() { + return a.length; + } + }; + } + + public static void main(String[] args) { + int[] a = new int[10]; + for (int i = 0; i < a.length; i++) + a[i] = i; + + List list = intArrayAsList(a); + Collections.shuffle(list); + System.out.println(list); + } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item24/localclass/MyClass.java b/src/main/java/com/example/effectivejava3e/week8/item24/localclass/MyClass.java new file mode 100644 index 0000000..92b43b8 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item24/localclass/MyClass.java @@ -0,0 +1,22 @@ +package me.whiteship.chapter04.item24.localclass; + +public class MyClass { + + private int number = 10; + + void doSomething() { + class LocalClass { + private void printNumber() { + System.out.println(number); + } + } + + LocalClass localClass = new LocalClass(); + localClass.printNumber(); + } + + public static void main(String[] args) { + MyClass myClass = new MyClass(); + myClass.doSomething(); + } +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item24/memberclass/MySet.java b/src/main/java/com/example/effectivejava3e/week8/item24/memberclass/MySet.java new file mode 100644 index 0000000..b9f63ae --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item24/memberclass/MySet.java @@ -0,0 +1,30 @@ +package com.example.effectivejava3e.week8.item24.memberclass; + +import java.util.AbstractSet; +import java.util.Iterator; + +public class MySet extends AbstractSet { + @Override + public Iterator iterator() { + return new MyIterator(); + } + + @Override + public int size() { + return 0; + } + + private class MyIterator implements Iterator { + + @Override + public boolean hasNext() { + return false; + } + + @Override + public E next() { + return null; + } + } + +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item24/memberclass/OutterClass.java b/src/main/java/com/example/effectivejava3e/week8/item24/memberclass/OutterClass.java new file mode 100644 index 0000000..4dc0dcc --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item24/memberclass/OutterClass.java @@ -0,0 +1,23 @@ +package com.example.effectivejava3e.week8.item24.memberclass; + +public class OutterClass { + + private int number = 10; + + void printNumber() { + InnerClass innerClass = new InnerClass(); + } + + private class InnerClass { + void doSomething() { + System.out.println(number); + OutterClass.this.printNumber(); + } + } + + public static void main(String[] args) { + InnerClass innerClass = new OutterClass().new InnerClass(); + innerClass.doSomething(); + } + +} diff --git a/src/main/java/com/example/effectivejava3e/week8/item24/staticmemberclass/OutterClass.java b/src/main/java/com/example/effectivejava3e/week8/item24/staticmemberclass/OutterClass.java new file mode 100644 index 0000000..9e82bb2 --- /dev/null +++ b/src/main/java/com/example/effectivejava3e/week8/item24/staticmemberclass/OutterClass.java @@ -0,0 +1,18 @@ +package me.whiteship.chapter04.item24.staticmemberclass; + +public class OutterClass { + + private static int number = 10; + + static private class InnerClass { + void doSomething() { + System.out.println(number); + } + } + + public static void main(String[] args) { + InnerClass innerClass = new InnerClass(); + innerClass.doSomething(); + + } +}