29일차
중요한 점은 다형성이다.

8. 인터페이스

8.4 디폴트메소드

인터페이스만들때 메소드가 모두 추상메소드엿엇다.
그런데 불편함을 느끼기 시작햇다.
실제 기능이 구현객체에서 구현되엇어야햇다.
구현객체들이 점점늘어나서 구현되고잇엇다.
추상메소드만 넣는다면 굉장히 많은 구현객체에서 재정의해야하는데 이게 불편했다.
그래서 인터페이스에 몸통이 있는것을 넣는게 어떤가라는 논의가잇엇고 추상클래스랑 뭐가다른가 논란이 잇엇지만 추가되엇다.

default method는 interface이 구현된 메소드이다.
접근제한자 생략하면 public이다.
구현객체들에도 상속처럼 안보이지만 있게 된다.

public interface MyInterface01 {
    void method1();

    default void method2() {
        System.out.println("interface의 default method");
        System.out.println("body가 있는 메소드");
    }
}

public class C01DefaultMethod {
    public static void main(String[] args) {
        MyInterface01 o1 = new MyClass011();
        MyInterface01 o2 = new MyClass012();

        o1.method1();
        o2.method1();

        o1.method2();
        o2.method2();
    }
}

접근제한자의 defult = 패키지 private
인터페이스이 dfault= 인터페이스의 구현된 메소드
default메소드도 구현클래스에서 재정의 가능하다.

8.5 private 메소드

default메소드들이 많아지고 공통된 코드들이 늘어나서 이 코드들을 모아놓을 필요가잇엇다.
그래서 공통된 코드로 메소드를 만들고 다른 메소드에서 호출하는 방식으로 만들었는데
기본이 public이라 이 공통코드를 가져다 사용할 수 있게되는것이 불편하다.
그래서 private 메소드가 생겨낫다.

public interface MyInterface02 {
    private void common() {
        System.out.println("공통된 코드들");
    }

    default void method1() {
        common();
        System.out.println("메소드1 코드들");
    }

    default void method2() {
        common();
        System.out.println("메소드2 코드들");
    }
}

8.6 static 필드

인터페이스의 값 인터페이스의 기능을 추가할 수 있게 되었다.
static필드와 static메소드가 있다.
인터페이스는 인스턴스 필드를 가질 수 없다.
인터페이스의 필드는 모두 public static final필드이다.
생략해도 추가된다.

public interface MyInterface03 {
    //static field
    public static final int I = 3;

    //public static final 생략
    int J = 5;
}

8.7 static method

public interface MyInterface04 {
    // public static method
    static void method1() {
        System.out.println("스태틱 메소드");
    }
}
********

public class C04StaicMethod {
    public static void main(String[] args) {
        MyInterface04.method1();
    }
}

8.8 private static method

private instance method와 마찬가지로 static메소드들의 공통부분을 처리하기 위해 private static 메소드도 생겨낫다.

private static void common() {
    System.out.println("공통된 코드");
}

static void method1() {
    common();
    System.out.println("method1 코드");
}

static void method2() {
    common();
    System.out.println("method2 코드");
}

8.9 강제 형변환

구현객체만 가지고 있는 메소드를 사용하고 싶을 경우
강제형변환해서 사용할 수 있다.

public class C01Cast {
    public static void main(String[] args) {
        MyInterface01 o1 = new MyClass011();
        // o1.method1(); 불가능

        MyClass011 o2 = (MyClass011) o1;
        o2.method1();
    }
}

8.10 instaceof

강제형변환이 불가능하면 오류가 발생한다.
강제형변환이 가능한지 아닌지를 확인해보고 강제형변환을 할 수있다.

public class C03Instanceof {
    public static void main(String[] args) {
        MyInterface02 o1 = new MyClass021();
        MyInterface02 o2 = new MyClass022();

        boolean a = o1 instanceof MyClass021; // true
        boolean b = o1 instanceof MyInterface02; // true

        System.out.println(a);
        System.out.println(b);

        System.out.println(o2 instanceof MyClass022); // true
        System.out.println(o2 instanceof MyInterface02); // true

        System.out.println();

        System.out.println(o1 instanceof MyClass022); // false
        System.out.println(o2 instanceof MyClass021); // false
    }
}

public class C02Instanceof {
    public static void main(String[] args) {
        MyInterface02 o1 = new MyClass021();
        MyInterface02 o2 = new MyClass022();

        if (o1 instanceof MyClass021) {
            MyClass021 o3 = (MyClass021) o1;
        }

        if (o2 instanceof MyClass022) {
            MyClass022 o4 = (MyClass022) o2;
        }

        if (o1 instanceof MyClass022) {
            MyClass022 o5 = (MyClass022) o1;
        }
        System.out.println("실행 흐름 이어감");
    }
}

8.11 확인문제 8번

C일때만 method2()가 호출되게하기

public class Example {
    public static void action(A a) {
        a.method1();

        if (a instanceof C) {
            C c = (C) a;
            c.method2();
        }
    }
    public static void main(String[] args) {
        action(new B());
        action(new C());
    }
}

8.12 String instanceof

api를 보고 구현하고 있는 것은 true가 나옴을 알 수 있다.

public class C05Instanceof {
    public static void main(String[] args) {
        method("java"); //모두 true
        method(new StringBuilder("java")); //구현한거는 다 true
        method(new StringBuffer("")); //구현하고 있는 것은 true
    }
    `
    public static void method(CharSequence c) {
        System.out.println(c instanceof String);
        System.out.println(c instanceof Object);
        System.out.println(c instanceof Serializable);
        System.out.println(c instanceof CharSequence);
        System.out.println(c instanceof Comparable);
        System.out.println(c instanceof Constable);
        System.out.println(c instanceof ConstantDesc);
    }
}

Part3

표준라이브러리 활용
라이브러리란 누군가 만들어놓은 클래스들의 모음이다.
직접만들수도잇지만 그것을 가져다 사용할 수도 있다.
자바를 만들어 놓은 사람이 모아 둔 것이 자바 표준 라이브러리이다.
API문서에 있는 것이 바로 이 자바 표준 라이브러리이다.

12장 java base모듈

OBJECT 포장 수학 리플렉션 어노테이션 정도 할듯하다.
항상 공식 문서를 보자.

12.1 Object 클래스

java.lang.Object
얘보다 상위클래스는 없다.
Class Object is the root of the class hierarchy.
어떤 클래스가 있던 Object는 트리형구조에서 가장 위에 있다.

즉 Object는 모든 클래스의 상위클래스이다. 심지어 우리가 만든 클래스도 Object를 상속한다.
extends Object가 생략되어 있는 상태이다.

public class C01Object {
    public static void main(String[] args) {
        //Object
        //모든 클래스의 상위클래스

        String s1 = "java";
        Object o1 = s1; 

        Scanner sc = new Scanner("");
        Object o2 = sc;

        ArrayList list = new ArrayList();
        Object o3 = list;

        C01Object o4 = new C01Object();
        Object o5 = o4;

        Object o6 = new MyClass01();
    }
}

참조타입과 기본타입은 저장되는 방식이 다르다.
그래도 담을 수가 있다. 나중에 배움(아마 박싱언박싱인듯)
int i = 3;
Object o7 = i;
결국엔 초기엔 별개엿는데 이제는 기본타입도 참조타입처럼 사용할 수 있다는 것이다.

12.1.1 Object의 메소드

따라서 Object에 있는 메소드는 모든 클래스가 가지고 있다.
자주사용하는 toString(); hashCode(); equals(); 등을 배울것이다.

재정의 하지 않으면 Object의 것이 실행된다. 필요하다면 재정의할 수 있다.

12.1.2 toString()

기본은 다음과 같다.
getClass().getName() + '@' + Intger.toHexString(hashString());
클래스이름@16진법해쉬코드

해쉬코드란 참조값이라고 생각하면된다.
예전에 System.identityHashCode(o2)로 비교한적이 있음.
이것이 해쉬코드이다. 이건 10진법 그냥 해쉬코드는 16진법

12.1.3 toString()-2

public class C04ToString {
    public static void main(String[] args) {
        Object o1 = "java";
        Object o2 = new String("java");

        System.out.println(System.identityHashCode(o1)); //다름
        System.out.println(System.identityHashCode(o2)); 

        System.out.println(o1.toString());
        System.out.println(o2.toString()); //같음
    }
}
public class C04ToString {
    public static void main(String[] args) {
        Object o1 = "java";
        Object o2 = new String("java");

        System.out.println(System.identityHashCode(o1)); //다름
        System.out.println(System.identityHashCode(o2)); 

        System.out.println(o1.toString());
        System.out.println(o2.toString()); //같음
    }
}

서로 다른 객체라 해쉬코드 즉 참조 값은 다르지만
String은 toString을 재정의 했기 때문에 비교를 하면 같게 나온다.
자기자신을 뽑아내게 재정의 되어있다. 그래서 같은 문자열이면 같은 문자열이 나온다.

12.1.3 toString()-3

toString은 결국 객체를 문자열로 표현하는 것이다.
그래서 toString을 마음대로 재정의해서 내 객체를 표현할 수 있다.

class MyClass05 {
    @Override
    public String toString() {
        return "내가 만든 설명";
    }
}

public class C05ToString {
    public static void main(String[] args) {
        Object o1 = new MyClass05();
        Object o2 = new MyClass05();

        System.out.println(o1.toString()); //내가 만든 설명
        System.out.println(o2.toString()); //내가 만든 설명
    }
}

12.1.3 toString()-4

필드의 설명을 보고싶을때 toString을 자주 재정의한다.

class MyClass06 {
    private String name;
    private int age;

    public MyClass06(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "나이는 " + age + "살 이고 이름은: " + name + "입니다.";
    }
}

public class C06ToString {
    public static void main(String[] args) {
        Object o1 = new MyClass06("son", 77);
        Object o2 = new MyClass06("park", 55);

        System.out.println(o1.toString());
        //나이는 77살 이고 이름은: son입니다.
        System.out.println(o2.toString());
        //나이는 55살 이고 이름은: park입니다.
    }
}

12.1.4 toString()-5

자주 사용하기 때문에 genertate source에서 기본적으로 제공하고 있다.

public class C07ToString {
    public static void main(String[] args) {
        Object o1 = new MyClass07("son", 30, "london", false);
        Object o2 = new MyClass07("park", 33, "seoul", true);

        System.out.println(o1.toString());
        System.out.println(o2.toString());
    }
}

class MyClass07 {
    private String name;
    private int age;
    private String address;
    private boolean married;

    public MyClass07(String name, int age, String address, boolean married) {
        this.name = name;
        this.age = age;
        this.address = address;
        this.married = married;
    }

    @Override
    public String toString() {
        return "MyClass07 [name=" + name + ", age=" + age + ", address=" + address + ", married=" + married + "]";
    }
}

12.1.5 확인문제 6번

toString을 오버라이딩해서 Member크래스 실행결과처럼 나오게 해보기

public class Member {
    private String id;
    private String name;

    public Member(String id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return id + ": " + name;
    }
}

public class MemberExample {
    public static void main(String[] args) {
        Member member = new Member("blue", "이파란");
        System.out.println(member);
    }
}

메소드를 실행시키지 않아도 객체를 출력한다면 그 객체의 toString이 출력된다.

12.1.6 레코드 선언

클래스 만들때 읽기전용으로 만드는 경우가 가끔 있다.
final필드로만들고 생성자만들고 getterseter만들고 toString하는일이 많았다.
안보이지만 다 자동으로 정의된다.
get메소드대신 그냥 필드이름을 사용하면된다.

record MyClass09(String name, int age) {
}

public class C09Record {
    public static void main(String[] args) {
        MyClass09 o1 = new MyClass09("son", 33);
        System.out.println(o1); //MyClass09[name=son, age=33]
        System.out.println(o1.name());
        System.out.println(o1.age());
    }
}

5 참조타입

참조타입하면서 넘어왔던 열거타입에 대해서 알아보고자 한다.

5.12 열거타입

어떤 클래스를 만들때 특별히 하는 일은 없고 상수값들만 가지고 있는 경우가 있다.
예를 들어 계절과 같은 경우가 있다.

public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int FALL = 3;
public static final int WINTER = 4;

이게 너무 길어서 사용하기 불편하다.
이런 정해진 값만 넣는게 종종 존재하니 새로운것이 생겻는데 이것이 Enum열거이다.
enum 키워드로 클래스를 만들고 값이름들만 나열하면된다

enum Season{
    //값이름 나열
    SPRING, SUMMER, FALL, WINTER
}

public class C11Enum {
    public static void main(String[] args) {
        System.out.println(Season.SPRING);
        System.out.println(Season.SUMMER);
        System.out.println(Season.FALL);
        System.out.println(Season.WINTER);

        Season s1 = Season.SPRING;
        Season s2 = Season.SUMMER;
        Season s3 = Season.FALL;
        Season s4 = Season.WINTER;

        System.out.println(s1.ordinal()); //0
        System.out.println(s2.ordinal()); //1
        System.out.println(s3.ordinal()); //2
        System.out.println(s4.ordinal()); //3

        Season s5 = Season.valueOf("SPRING");
        Season s6 = Season.valueOf("SUMMER");
        Season s7 = Season.valueOf("FALL");
        Season s8 = Season.valueOf("WINTER");

        System.out.println(System.identityHashCode(s1));
        System.out.println(System.identityHashCode(s5)); 
        //이미 객체가만들어진거라 같은 참조값을 가진다.
    }
}

2023.03.08 후기

내가 헤맸던 부분을 쭉쭉 매우 빠르게 나가고 있는데 다른 사람들은 어떻게 이해하고 있는지 정말 궁금하다.

'국비 > Java' 카테고리의 다른 글

2023.03.10 31일차 Java  (0) 2023.03.10
2023.03.09 30일차 Java  (0) 2023.03.09
2023.03.06 27일차 Java  (0) 2023.03.06
2023.03.03 26일차 Java  (0) 2023.03.06
2023.03.02 25일차 Java  (0) 2023.03.02

+ Recent posts