ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (김영한의 실전 자바 - 중급 1편) 5 - 내용 정리
    카테고리 없음 2024. 5. 28. 16:49

    [1. Object 클래스] 

    * 정적 의존관계 vs 동적 의존관계
    - 정적 의존관계 : 컴파일 시간에 결정, 주로 클래스 간의 관계 의미
    프로그램 실행하지 않고 클래스 내에서 사용하는 타입만 보면 의존관계 알 수 있음

    - 동적 의존관계 : 프로그램 실행하는 런타임에 확인할 수 있다. 
    어떤 인자로 어떤 객체가 전달될 지는 프로그램 실행해야 알 수 있다. 

    ex) ObjectPrinter.print(Object obj) 에서 어떤인자로 어떤 객체가 전달 될 지 프로그램 실행해야 알 수 있음

    Car 인스턴스가 넘어오거나 Dog 인스턴스가 넘어오는지 실행해야만 알 수 있다.  


    ■ equals()
    * 동일성(Identity) vs 동등성(Equality)
    - 동일성(완전히 같음) : == 연산자를 사용해서 두 객체의 참조가 동일한 객체를 가리키는지 확인
    - 동등성(같은 가치나 수준이나 형태 외관이 같지 않을 수 있다.) : equals() 메서드를 사용해
    두 객체가 논리적으로 동등한지 확인

     

    동일성은 물리적으로 같은 메모리에 있는 객체 익스턴스인지 참조값 확인
    동등성 논리적으로 같은지 확인 

     

     

     

    Object.equals() 메서드도 기본적으로 == 동일성 비교를 한다. 

    동등성은 각각 클래스마다 다르게 사용자가 정의할 수 있다. 

    따라서 동등성 비교를 하고 싶다면 equals 를 오버라이딩 해서 재정의 해야한다. 

     

    [2. 불변 객체]
    ■ 불변 객체
    : 객체의 상태(객체 내부 값, 필드, 멤버 변수)가 변하지 않는 객체를 불변 객체

     

     


    불변이라는 단순한 제약을 사용해서 사이드 이펙트라는 큰 문제를 막을 수 있다. 
    사이드 이펙트는 값을 변경할 때 발생하기 때문에 값 변경을 원천적으로 막으면 된다. 

     

    따라서 다음과 같이 value 값을 final 로 불변으로 만들어 버리면 애초에 값이 바뀌는 현상을 막을 수 있다. 

     

    개발을 하면서 값이 바뀌면 안되는 값은 미리 final 불변 객체로 만들어 주는 것이 좋다.

    만약 개발을 하다 사이드 이펙트 현상이 터지면 그것은 값을 변경한 사람이 아닌,

    불변 객체로 설계하지 않은 선임자의 실수나 다름 없다. 

     

    ※ 사이드 이펙트

    : 프로그래밍에서 어떤 계산이 주된 작업 외에 추가적인 부수 효과를 일으키는 것이다. (부정적 의미)

    *가변객체 vs 불변객체
    - 가변 : 상태가 변할 수 있다. // 하나를 바꿨을 때 다 같이 바뀌어야 할 때 
    - 불변 : 상태가 변하지 않는다. //하나 바꿨을 때 다른 것이 변경되면 안되는 상황

    기존값을 유지한 상태로 뭔가 새로 하나 넣어서 새로 반환할 때 with 라는 표현 씀


    불변 객체의 메서드가 with로 이름이 지어진 경우, 

    그 메서드가 지정된 수정사항을 포함하는 객체의 새 인스턴스를 반환한다.

    즉, 원본 객체의 상태가 그대로 유지됨을 강조하면서 변경사항을 새 복사본에 포함하는 과정을 간결하게 표현한다. 

     

    [3. String 클래스]

    ■ String(불변)

     

    * String 메서드
    length() : 문자열 길이 반환
    charAt(int index) : 특정 인덱스의 문자 반환
    substring(int beginIndex, int endIndex) : 문자열의 부분 문자열을 반환
    indexOf(String str) : 특정 문자열이 시작되는 인덱스를 반환
    toLowerCase(), toUpperCase() : 문자열을 소문자 또는 대문자로 변환
    trim() : 문자열 양 긑 공백 제거
    concat(String str) : 문자열 더한다.

    String은 클래스, 즉 참조형이다. 

     

    참조형은 변수에 계산할 수 있는 값이 있는 것이 아니라 x001 과 같이 참조값이 들어있어,

    원칙적으로는 + 연산이 불가능하다.

    따라서 원래는 concat()과 같은 메서드로 문자열을 더해야 하지만,

    자바에서는 너무 많이 다뤄 예외적으로 + 로 문자열을 더할 수 있다. 

     

     

     

     

    String str3 = "hello" 와 같이 문자열 리터럴을 사용하는 경우 

    자바는 메모리 효율성과 성능 최적화를 위해 문자열 풀을 사용한다. 

    자바가 실행되는 시점에 클래스에 문자열 리터럴이 있으면 

    문자열 풀에 String 인스턴스를 미리 만들어둔다. 이때 같은 문자열이 있으면 만들지 않는다. 

    문자열 풀 덕분에 같은 문자를 사용하는 경우 메모리 사용을 줄이고 

    문자를 만드는 시간도 줄어들기 때문에 성능도 최적화 할 수 있다. 

     

    여기서 String 이 불변인 이유가 있다.

    이렇게 문자열 풀에서 같은 참조값을 참고하는 값이 마음대로 변하지 않게 막아주는 역할을 한다. 

    ※ 풀 : 자원이 모여있는 곳
    공용 자원을 모아둔 곳
    문자열 풀은 힙 영역을 사용한다. 

     

    * StringBuilder vs String

     


    StringBuilder는 가변적 / String은 불변

    StringBuilder는 보통 문자열 변경이 많은 경우 사용하고,
    후에 toString으로 불변 객체로 만든다. 

    * StringBuffer vs StringBuilder (거의 Builder를 사용한다)
    StringBuffer  는 내부에 동기화 되어 있어 멀티 스레드 상황에 안전하지만 동기화 오버헤드로 인해 성능이 느리다.

    반대로 StringBuilder 는 멀티 쓰레드에 상황에 안전하지 않지만 동기화 오버헤드가 없으므로 속도가 빠르다.

    ※ CharSequence는 String, StringBuilder의 상위 타입이다.
    StringBuilder는 가변 String 이다. 

    반복문에서는 StringBuilder 사용이 좋다. 최적화가 안되기 때문이다. 

     

    * methodchaining 
    메서드가 체인처럼 연결돼 있다. = methodchaining = 메서드 체이닝
    자기 자신의 참조값을 반환하기 때문에 .을 찍고 사용 가능하다.
    StringBuilder도 자기 자신을 반환해서 메서드 체이닝 사용한다. 

     

    [4. 래퍼, Class 클래스]

    자바의 기본형 타입은 객체가 아니기 때문에 유용한 메서드 사용이 불가능하다.

    더불어 null 값을 가질 수 없다는 단점이 있다.

    이를 해결하기 위해 래퍼 클래스가 나오게 되었다. 

     

    ■ 래퍼 클래스
    특정 기본형을 감싸서(Wrap) 만드는 클래스를 래퍼 클래스라고 한다. 

     

    ※ String.valueOf() : 다양한 타입을 문자열로 변환한다. 

    * 자바 제공하는 래퍼 클래스 

     


    1. 불변
    2. 객체이기 때문에 equals 로 비교해야 한다. 

     



    * 박싱
    : 기본형을 래퍼 클래스로 변경하는 것을 마치 박스에 물건을 넣은 것 같다고 해서 박싱(Boxing)이라고 한다. 

     

     


    * intValue() - 언박싱
    : 래퍼 클래스에 들어있는 기본형 값을 다시 꺼내는 메서드

     



    * 오토박싱
    컴파일러가 개발자 대신에 valueOf, xxxValue() 코드를 추가해주는 기능이다. 

     

    * parseInt vs valueOf
    래퍼 객체로 변환 : valueOf
    (문자) 기본형 변환 : parseInt
    ※ 파싱 : 문자를 무언가로 바꾼다.

    valueOf : 래퍼 타입을 반환
    parseInt : 기본형 반환

    기본형은 메모리에 단순히 그 크기만큼 공간 차지한다. 
    래퍼 클래스는 객체 자체를 다루는데 필요한 객체 메타데이터를 포함하여 더 많은 메모리 사용한다. 

    ■ Class 클래스
    클래스의 정보(메타데이터)를 다루는 데 사용한다.
    실행중인 자바 애플리케이션 내 필요한 클래스의 속성과 메소드에 대한 정보를 조회 및 조작할 수 있다. 

    * 리플렉션(reflection)
    Class를 사용하면 클래스의 메타 정보를 기반으로 클래스에 정의된 메소드, 필드, 생성자 등을 조회하고 이들을 통해 

    객체 인스턴스를 생성하거나 메소드를 호출하는 작업을 할 수 있다. 
    이를 리플렉션이라 한다. 

     

    [5. 열거형 - ENUM]
    ■ 문자열과 타입 안정성
    String 사용 시 타입 안정성 부족 문제
    문자 실수
    컴파일 시 오류 감지 불가

    ■ 타입 안전 열거형 패턴 (Type-Safe Enum Pattern)
    enum(enumeration) 열거 : 어떤 항목을 나열하는 것
    나열한 항목만 사용할 수 있다. 

    * 타입 안전 열거형 패턴 장점
    1. 타입 안정성 향상 : 정해진 객체만 사용해서 잘못된 값 입력 방지
    2. 데이터 일관성 : 데이터 일관성 보장

    컴파일 시점에 방지

    ■ 열거형(Enum Type)
    열거형 정의 시 class 대신 enum 표시

    타입 안정성 향상 : 정해진 타입만 넣을 수 있다. 오타 방지
    간결성 및 일관성 : 열거형을 사용하면 코드가 더 간결하고 명확해지며, 데이터의 일관성이 보장된다
    확장성 : 타입 편하게 넣을 수 있다. 

    alt + enter 치면 static import 로 깔끔하게 코드 볼 수 있다. 
    상수의 경우에는 static import 사용 가능하다. 

    String -> ENUM 변환, 잘못된 문자면 IllegalArgumentException 발생

     

    * ENUM 메서드

     


    ordinal은 가급적 사용하지 않는게 좋다. 

     

    ※ Arrays.toString() : 배열 참조값이 아닌 내부의 값 출력할 때 사용

     

    [6. 날짜와 시간]
    ■ 날짜와 시간 라이브러리
    London / UTC / GMT 00:00
     
    처음 세계 시간을 만들 때 영국 런던에 있는 그리니치 천문대 기준으로 만듦.

    UTC : 원자 시계 사용하여 측정 (좀 더 정확)
    일광 절약 시간(DST)

    Joda-Time 오픈소스 라이브러리 도입 -> java.time 패키지를 표준 API 로 도입했다. 

     

    * LocalDate  / LocalTime  / LocalDateTime 
    - LocalDate : 날짜만 표현
    - LocalTime : 시간만 표현할 때
    - LocalDateTime : 둘 다 사용

     

    * 시간의 개념
    1. 특정 시점의 시간(시각) : 생일은 6월 14일
    2. 시간의 간격(기간) : 4년은 더 공부해야 해
    ex) Period, Duration

    Period : 두 날짜 사이 간격 년, 월, 일
    Duration : 두 날짜 사이 시 분 초

    OffsetDateTime : ZoneId 가 없다. 

    포매팅 : 날짜와 시간 데이터를 원하는 포맷의 문자열로 변경하는 것 Date -> String
    파싱 : 문자열을 날짜와 시간으로  String -> Date

     

    [7. 중첩 클래스, 내부 클래스1]
    ■ 중첩 클래스
    1. 정적 중첩 클래스
    2. 내부 클래스
    - 내부 클래스
    - 지역 클래스
    - 익명 클래스

    * 중첩 vs 내부
    - 중첩 : 어떤 다른 것이 내부에 위치하거나 포함되는 구조적인 관계
    나의 안에 있지만 내 것이 아닌 것
    ex) 큰 나무 상자 안에 다른 나무 상자 넣은 것
    - 내부 : 나의 내에 있는 나를 구성하는 요소
    나의 내부
    ex) 나의 심장은 나의 내부에서 나를 구성하는 요소

    바깥 클래스 입장에서 볼 때 안에 있는 클래스가 나의 인스턴스에 소속되어 있는가 아닌가

    * 정적 중첩 클래스 
    1. static이 붙는다.
    2. 바깥 클래스의 인스턴스에 소속되지 않는다.

    * 내부 클래스
    - 내부 클래스 : 바깥 클래스 인스턴스 멤버에 접근
    - 지역 클래스 : 내부 클래스 특징 + 지역 변수에 접근
    - 익명 클래스 : 지역 클래스 특징 + 클래스 이름이 없는 특별한 클래스

    중첩 클래스는 해당 클래스와 긴밀한 연결이 있거나 클래스 안에서만 사용될 때만 사용해야 한다. 

    정적 중첩 클래스
    바깥 클래스 클래스 멤버에는 접근할 수 있으나 인스턴스 멤버에는 접근할 수 없다. 
    클래스 멤버는 사실상 누구나 접근 가능한데 차이점은 private 일 때도 접근할 수 있다는 점이다.

    내부 클래스는 바깥 클래스의 인스턴스에 소속된다. 

    중첩 클래스 사용 이유
    1. 논리적 그룹화 
    다른 곳에 사용될 필요가 없는 중첩 클래스 외부 노출을 안시킨다.
    2. 캡슐화
    중첩 클래스는 바깥 클래스의 private 멤버에 접근할 수 있다. 

    다른 변수를 가려서 보이지 않게 하는 것을 섀도잉이라 한다. 
    this.value 내부 클래스 인스턴스에 접근
    바깥클래스 이름.this 는 바깥 클래스의 인스턴스에 접근할 수 있다. 

     

    [8. 중첩 클래스, 내부 클래스2]
    ■ 지역 클래스
    지역 클래스도 바깥 클래스의 인스턴스 멤버 접근이 가능하다. 

    ■ 변수 생명주기 (3가지)
    - 클래스 변수 : 프로그램 종료 까지, 가장 길다(메서드 영역)

    - 지역 변수 : 메서드 호출이 끝나면 사라짐(스택 영역)
    - 인스턴스 변수 : 인스턴스 생존 기간(힙 영역)
    소속 인스턴스가 GC 되기 전까지 존재

    * 지역 변수 캡처
    : 인스턴스를 생성하는 시점에 필요한 지역 변수를 복사해 생성한 인스턴스에 함께 넣어준다.

     


    익명 클래스는 클래스의 본문을 정의하면서 동시에 생성한다.
    new 다음에 바로 상속 받으면서 구현할 부모 타입을 입력하면 된다. 
    인터페이스를 생성하는 것이 아니라 Printer라는 이름의 인터페이스를 구현한 익명 클래스를 생성하는 것이다. 

    익명 클래스
    선언하면서 동시에 생성한다. 
    부모 클래스를 상속 받거나, 또는 인터페이스를 구현해야 한다.
    이름을 가지지 않아 생성자 가질 수 없다.

     

     

    ※ 정적 중첩 클래스 사용 이유

    정적 중첩 클래스는 외부 클래스 인스턴스 멤버에 접근할 수 없다.

    따라서 외부 클래스 인스턴스 멤버에 접근이 필요 없다면 정적 중첩 클래스로 만드는 게 바람직하다.

     

    더불어 정적 중첩 클래스는 외부 클래스 인스턴스를 참조하지 않아 메모리 효율성에도 좋다. 

     



    코드 조각을 메서드에 전달할 때는 인스턴스를 전달하고 해당 인스턴스에 있는 메서드를 호출

    람다

     


    메서드를 인수로 전달 가능하게 됨

     

    [9. 예외 처리1 - 이론]
    ■ 자바 예외 처리 키워드
    try, catch, finally, throw, throws

     

     


    Object : 예외도 객체, 모든 객체의 최상위 부모는 Object 이므로 예외 최상위도 Object
    Throwable : 최상위 예외, 하위에 Exception과 Error
    Error : 메모리 부족, 심각한 시스템 오류와 같이 복구 불가능한 시스템 예외
    Exception : 체크 예외
    - 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외
    - Exception과 그 하위 예외는 모두 컴파일러가 체크하는 체크 예외
    ※ RuntimeException 체크예외가 아니다.  
    RuntimeException : 언체크 예외, 런타임 예외
    - 컴파일러가 체크 하지 않는 언체크 예외이다. 
    - RuntimeException과 그 자식 예외는 모두 언체크 예외
    - RuntimeException의 이름을 따라서 RuntimeException과 그 하위 언체크 예외를 
    런타임 예외라 많이 부른다.  

    * 체크 예외 vs 언체크 예외
    체크 예외는 개발자가 명시적으로 처리해야 함
    언체크 예외는 개발자가 발생한 예외를 명시적으로 처리하지 않아도 된다. 

    Throwable 예외를 잡으면 안된다.
    왜냐면 Error 예외를 같이 잡게 되기 때문이다. 

    * 예외 기본 규칙
    예외 2가지 규칙
    1. 예외는 잡아서 처리하거나 밖으로 던져야 함
    2. 예외를 잡거나 던질 때 지정 예외 뿐 아니라 예외 자식들도 함께 처리할 수 있다.
    - Exception을 catch 로 잡으면 모두 잡는다.
    - Exception을 throws 로 던지면 모두 던진다.

    * 체크 예외
    super(message) Throwable 에 메시지 저장된다.

    체크 예외의 장단점
    - 장점: 실수로 예외 누락하지 않도록 컴파일러 통해 문제 잡아준다.
    - 단점: 개발자가 모든 체크 예외를 잡거나 던지도록 체크해야 해서 번거롭다.

    * 언체크 예외
    컴파일러가 예외를 체크하지 않는다.
    현대에는 체크 예외를 거의 쓰지 않는다.

    예외 흐름 커맨드 창에 나타내줌 = 스택 트레이스

    * finally
    finally는 반드시 호출된다. 

    * 예외 객체 계층화

    * 예외 스택 트레이스 출력
    e.printStackTrace(System.out); 

    * try with resources
    - close : AutoCloseable 인터페이스로 close() 메서드 이용
    - try 끝나면 자동 호출
    종료 시점에 자원을 반납하는 방법을 여기 정의하면 된다.
    이 메서드에서 예외를 던지지 않으므로 인터페이스 메서드에 있는 throws Exception은 제거한다.

Designed by Tistory.