볞묞 바로가Ʞ

Java/Java의 정석

Chapter 12 - 제넀늭슀, 엎거형, 애너테읎션

Chapter 12 - 제넀늭슀, 엎거형, 애너테읎션

1. 지넀늭슀(Generics)

  • JDK 1.5에서 처음 도입

1.1 지넀늭슀란?

  • 닀양한 타입의 객첎듀을 닀룚는 메서드나 컬렉션 큎래슀에 컎파음 시의 타입 첎크륌 핎죌는 Ʞ능
    • 타입 안정성을 높읎고 형변환의 번거로움 감소

1.2 지넀늭 큎래슀의 ì„ ì–ž

  • 큎래슀 옆에 <T>륌 붙읎고 Object 큎래슀륌 몚두 T로 변겜
    • T는 타입 변수띌고 부늄 (T가 아닌 닀륞 것 사용핎도 묎ꎀ)
  • 지넀늭 큎래슀로 객첎륌 ì„ ì–ž 시 찞조변수와 생성자에 타입 T 대신 싀제 타입을 지정
  • 하위 혞환을 위핎 예전의 방식윌로 객첎륌 생성하는 것도 허용하지만 안전하지 않닀는 겜고 발생
    • Object륌 지정하멎 겜고 발생 X

지넀늭슀의 ìš©ì–Ž

  • Example : 지넀늭 큎래슀
  • T : 타입 변수 또는 타입 맀개변수
  • Example : 원시타입
  • 지정된 타입을 맀개변수화된 타입읎띌고 부늄
  • 컎파음 후에는 원시타입윌로 바뀜 (지넀늭 타입읎 제거됚)

지넀늭슀의 제한

  • 객첎 생성 시 객첎별로 닀륞 타입을 지정하는 것을 허용
  • 몚든 객첎에 동음하게 동작핎알 하는 static 멀버에 타입 변수 T륌 사용할 수 없음
  • new T[10]곌 같읎 new 연산자와 핚께 사용할 수 없음
    • 컎파음 시점에 타입 T가 묎엇읞지 정확히 알아알 하므로
    • 지넀늭 배엎을 ꌭ 생성핎알 하멎 new 연산자 대신 newInstance()와 같은 동적윌로 객첎륌 생성하는 메서드 or Object 배엎을 생성핎서 복사한 후 형변환

1.3 지넀늭 큎래슀의 객첎 생성곌 사용

  • 찞조변수와 생성자에 대입된 타입읎 음치핎알 됚
    • 음치하지 않윌멎 에러 발생
    • 두 타입읎 상속ꎀ계여도 에러 발생
    • 두 지넀늭 큎래슀의 타입읎 상속ꎀ계읎며 대입된 타입읎 같은 것은 허용
    • JDK 1.7부터는 추정읎 가능한 겜우 타입 생략 가능
  • 생성된 객첎의 메소드가 맀개변수로 타입 변수 객첎륌 받을 때 타입 변수의 자손듀도 맀서드의 맀개변수가 될 수 있음

1.4 제한된 지넀늭 큎래슀

  • T만 선얞하멎 몚든 종류의 타입을 지정할 수 있음
  • 제넀늭 타입에 extends륌 사용하멎 특정 타입의 자손듀만 대입할 수 있게 제한 가능
  • 읞터페읎슀륌 구현핎알 하는 제앜 역시 extends로 표현
    • implements륌 사용하지 않음에 죌의
    • 자손 제앜곌 구현 읞터페읎슀가 졎재한닀멎 & Ʞ혞로 연결 (<T extends ExampleClass & ExampleInterface>)

1.5 와음드 칎드

  • 하나의 찞조변수로 서로 닀륞 타입에 대입된 여러 지넀늭 객첎륌 닀룚Ʞ 위핎 사용
    • 메서드륌 혞출할 때마닀 닀륞 타입을 대입핎알 할 때 사용
  • <T extends Example> vs <? extends Example>
    • <T extends Example>는 메서드륌 혞출할 때마닀 닀륞 지넀늭 타입을 대입할 수 있게 한 것
    • <? extends Example>는 하나의 찞조변수로 서로 닀륞 타입에 대입된 여러 지넀늭 객첎륌 닀룚Ʞ 위한 것
  • <? extends T> : 와음드 칎드의 상한 제한. T와 ê·ž 자손듀만 가능
  • <? super T> : 와음드 칎드의 하한 제한. T와 ê·ž 조상듀만 가능
  • <?> : 제한 없음. 몚든 타입읎 가능. (<? extends Object>와 동음)
  TestList<Parent> testList = new TestList<Parent>(); // 허용
  TestList<Parent> childTestList = new TestList<Child1>(); // 에러

  TestList<? extends Parent> wildCardChildTestList = new TestList<Child1>(); // 허용
  wildCardChildTestList = new TestList<Child2>(); // 허용
  wildCardChildTestList = new TestList<Child3>(); // 허용

1.6 지넀늭 메서드

  • 메서드의 선얞부에 지넀늭 타입읎 선얞된 메서드 (큎래슀의 타입 변수가 선얞되는 것읎 아님!)
  • 지넀늭 큎래슀에 정의된 타입 맀개변수와 지넀늭 메서드에 정의된 타입 맀개변수는 전혀 별개의 것
    • 같은 묞자 T 음지띌도
  • 메서드에 선얞된 지넀늭 타입은 지역 변수륌 ì„ ì–ží•œ 것곌 같음
    • 메서드 낎에서만 사용될 것
  • 메서드 혞출 시 타입 변수에 타입을 대입핎알 하지만 대부분의 겜우 컎파음러가 추정 가능하므로 생략
    • 메서드륌 혞출할 때 타입을 생략할 수 없는 겜우에는 찞조변수나 큎래슀 읎늄 생략 불가
  • public static <T extends Comparable<? super T>> void sort(List<T> list)
    • 타입 T륌 요소로 하는 List륌 맀개변수로 허용
    • T는 Comparable을 구현한 큎래슀읎얎알 핹
    • Comparable<? super T>읎므로 Comparable의 맀개변수는 T와 T의 조상 타입읎 몚두 가능

1.7 지넀늭 타입의 형변환

  • 지넀늭 타입곌 원시 타입 간의 형변환은 가능
    • 겜고가 발생할 뿐
  • 대입된 타입곌 닀륞 지넀늭 타입 간에는 형변환 불가능
    • Object여도 불가능
  • 특정 타입을 ? extends Object윌로의 형변환도 가능
    • 반대로도 가능하지만 확읞되지 않은 형변환읎띌는 겜고 발생
  • Optional<Object>륌 Optional<String>윌로 직접 형변환 하는 것은 불가능하지만 와음드 칎드가 포핚된 지넀늭 타입윌로 형변환하멎 가능
    • Optional<Object> -> Optional<?> -> Optional<T>

1.8 지넀늭 타입의 제거

  • 컎파음러는 지넀늭 타입을 읎용핎서 소슀파음을 첎크 후 필요한 곳에 형변환을 넣얎쀀 ë’€ 지넀늭 타입 제거
    • *.class 파음에는 지넀늭 타입에 대한 정볎가 없음
  • 하휘 혞환성을 유지하Ʞ 위핚
    • 원시 타입윌로 작성할 수 있도록 한 것도 마찬가지
  • Ʞ볞적읞 제거 곌정
    1. 지넀늭 타입의 겜계륌 제거 (~ extends XXX는 XXX로 변겜, T만 있을 시 Object로 변겜)
    2. 지넀늭 타입을 제거한 후 타입읎 음치하지 않윌멎 형변환 추가

2. 엎거형(enums)

2.1 엎거형읎란?

  • 서로 ꎀ렚된 상수륌 펞늬하게 선얞하Ʞ 위한 것
  • JDK 1.5부터 새로 추가
  • 값뿐만 아니띌 타입도 ꎀ늬핚 (C얞얎의 엎거형볎닀 향상된 것)
    • 타입에 안전한 엎거형(싀제 값뿐만 아니띌 타입도 첎크)
  • 상수와 닀륎게 엎거형 상수는 Ʞ졎의 소슀륌 닀시 컎파음하지 않아도 됚

2.2 엎거형의 정의와 사용

  • enum 엎거형읎늄 {상수명1, 상수명2, ...}
  • static 변수륌 찞조하듯 엎거형읎늄.상수명윌로 ì°žì¡°
  • ==로 비교가 가능하나 <,> 같은 비교연산자는 사용 불가능
    • compareTo()는 사용 가능
  • switch 묞의 case 묞에도 사용가 능한데 엎거형의 읎늄은 적지 말고 상수만 적얎알 핹

몚든 엎거형의 조상 - java.lang.Enum

  • getDeclaringClass(), name(), ordinal(), valueOf()륌 Enum에서 갖고 있음
    • ordinal()은 0부터 시작하는 엎거형의 순서 반환
    • name()은 엎거형의 읎늄을 묞자엎로 반환
  • values(), valueOf(String name)은 컎파음러가 자동적윌로 추가핎 죌는 메서드
    • values()는 엎거형의 몚든 상수륌 배엎에 ë‹Žì•„ 반환
    • valueof()는 상수에 대한 찞조륌 얻게 핎쀌

2.3 엎거형에 멀버 추가하Ʞ

  • 엎거형의 읎늄 옆에 원하는 값을 ꎄ혞와 핚께 적얎죌멎 가능
    • ê·ž 후 지정된 값을 저장할 수 있는 읞슀턎슀 변수와 생성자륌 새로 추가 핎알핚
      • 엎거형 상수륌 몚두 정의한 닀음 닀륞 멀버듀을 추가 핎알핚
      • 엎거형 상수의 마지막에 ';'도 잊지 말 것
  • 엎거형 생성자는 제얎자가 묵시적윌로 private
  • 여러 값에 맞는 읞슀턎슀 변수와 생성자륌 새로 추가한닀멎 엎거형 상수에 여러 값을 저장할 수 있음

엎거형에 추상 메서드 추가하Ʞ

  • 엎거형에 추상메서드륌 선얞하멎 각 엎거형 상수가 추상 메서드륌 반드시 구현핎알 핹

2.4 엎거형의 읎핎

  • 엎거형 상수 하나하나가 객첎
  • Enum 큎래슀의 static 상수읞 엎거형 상수듀의 값은 객첎의 죌소읎며 바뀌지 않윌므로 ==로 비교가 가능한 것
    • 서로의 ordinal을 빌죌는 방식윌로 구현

3. 애너테읎션(annotation)

3.1 애너테읎션읎란?

  • javadoc을 만듀얎낎는 죌석의 @읎 붙은 태귞 Ʞ능을 응용하여 만든 Ʞ능
  • 프로귞랚의 소슀윔드 안에 닀륞 프로귞랚을 위한 정볎륌 믞늬 앜속된 형식윌로 포핚시킚 것
  • 죌석처럌 프로귞래밍 얞얎에 영향을 믞치지 않윌멎서도 닀륞 프로귞랚에게 유용한 정볎륌 제공
    • ꎀ렚 있는 프로귞랚에만 영향
  • JDK에서 제공하는 표쀀 에너테읎션은 죌로 컎파음러에게 유용한 정볎 제공
    • 새로욎 애너테읎션을 정의할 때 사용하는 메타 애너테읎션도 제공

3.2 표쀀 애너테읎션

  • 표쀀 애너테읎션
    • @Override, @Deprecated, @SuppressWarnings, @SafeVarags, @FunctionalInterface, @Native
  • 표쀀 애너테읎션 쀑 메타 애너테읎션
    • @Target, @Documented, @Inherited, @Retention, @Repeatable

@Override

  • 메서드 앞에만 붙음 수 있음
  • 조상의 메서드륌 였버띌읎딩 하는 것읎띌는 걞 컎파음러에게 알렀쀌
  • 메서드 읎늄을 잘 못 ì“°ë©Ž 컎파음러가 에러 출력
  • 필수는 아니지만 싀수륌 방지 핎죌는 애너테읎션

@Deprecated

  • 더 읎상 사용되지 않는 필드나 메서드에 붙읎는 애너테읎션
  • 닀륞 것윌로 대첎되었윌니 더 읎상 사용하지 않을 것을 권하는 의믞

@FunctionalInterface

  • 핚수형 읞터페읎슀륌 ì„ ì–ží•  때 읎 애너테읎션을 붙읎멎 컎파음러가 올바륞 핚수형 읞터페읎슀읞지 확읞
  • 잘못된 겜우 컎파음러가 에러 출력
  • 필수는 아니지만 싀수륌 방지핎 죌는 애너테읎션

@SuppressWarnings

  • 묵읞핎알 하는 겜고가 발생하는 대상에 붙여서 컎파음 후에 ì–Žë–€ 겜고 메시지도 나타나지 않게 핹
  • -Xlint 옵션윌로 나였는 겜고의 종류 쀑 대ꎄ혞[]안에 있는 겜고륌 억제할 수 있음
  • 억제하는 겜고로 죌로 사용되는 것은 "deprecation", "uncheked", "rawtypes", "varargs"
  • 배엎처럌 ꎄ혞{}륌 사용핎 둘 읎상의 겜고륌 동시에 억제할 수도 있음
  • main() 메소드에 붙여서 핎당 겜고와 ꎀ렚된 몚든 메섞지륌 억제할 수 있지만 억제 범위륌 최소화하는 것읎 좋닀.

@SafeVarargs

  • 컎파음 후에도 제거되지 않는 타입은 reifiable, 제거되는 타입은 non-reifiable 타입
    • 지넀늭 타입듀은 대부분 컎파음 시에 제거되므로 non-reifiable 타입
  • 메서드에 선얞된 가변읞자의 타입읎 non-reifiable 타입음 겜우 핎당 메서드륌 선얞하눈 부분곌 혞출하는 부분의 "uncheked" 겜고륌 억제하Ʞ 위핎선 @SafeVarargs 사용
    • 맀개변수가 가변읞자읎멎서 제넀늭 타입읞 겜우 (ex- Arrays.asList(T... a))
    • 메서드에 선얞된 타입 T는 컎파음 곌정에서 Object로 바뀜
    • 컎파음러가 몚든 객첎가 듀얎올 수 있음을 겜고
    • 하지만 지넀늭슀륌 사용했Ʞ 때묞에 컎파음러가 혞출 부분을 첎크핎서 T 왞에 닀륞 타입읎 듀얎갈 수 없게 할 것읎므로 위 윔드는 안정
    • 읎때 @SafeVarargs륌 붙임
  • @SuppressWarnings("unchecked")는 메서드 ì„ ì–ž 부분곌 혞출되는 곳에서 애너테읎션을 붙여알 하지만 @SafeVarargs는 메서드륌 혞출하는 곳에서 발생하는 겜고도 억제
  • 'varargs' 겜고는 억제할 수 없윌므로 @SuppressWarnings("varargs")와 핚께 얎녞테읎션을 붙임

3.3 메타 애너테읎션

  • 메타 애너테읎션은 애너테읎션을 정의할 때 사용

@Target

  • 애너테읎션읎 적용 가능한 대상을 지정하는 데 사용
  • 여러 개의 값은 ꎄ혞{}륌 사용핎알 핹

@Retention

  • 애너테읎션읎 유지(retention)되는 Ʞ간을 지정하는 데 사용
  • 컎파음러가 사용하는 애너테읎션의 유지 정책은 'SOURCE'
  • 유지 정책읎 'RUNTIME'음 시 싀행 시에 늬플렉션을 통핎 큎래슀 파음에 저장된 애너테읎션을 정볎륌 읜은 ë’€ 처늬
  • 유지 정책 'CLASS'는 컎파음러가 애너테읎션의 정볎륌 큎래슀 파음에 저장할 수 있게 핎쀌
    • 큎래슀 파음읎 JVM에 로딩될 시 애너테읎션의 정볎가 묎시되므로 싀행 시에는 정볎륌 얻을 수 없윌므로 잘 사용 X

@Documented

  • 애너테읎션에 대한 정볎가 javadoc윌로 작성한 묞서에 포핚되도록 핹

@Inherited

  • 애너테읎션읎 자손 큎래슀에 상속되도록 핹
    • 조상 큎래슀에 붙읎멎 자손 큎래슀도 읎 애너테읎션읎 붙은 것곌 같읎 읞식

@Repeatable

  • @Repeatable읎 붙은 애너테읎션은 여러 번 붙음 수 있음
  • 읎 애너테읎션듀을 하나로 묶얎서 닀룰 수 있는 애너테읎션도 추가로 정의핎알 핹

@Native

  • 넀읎티람 메서드에 의핎 찞조되는 상수 필드에 붙읎는 애너테읎션
    • 넀읎티람 메서드는 JVM읎 섀치된 OS의 메서드륌 의믞
    • 볎통 Cì–žì–Žë¡œ 작성
    • 자바에서는 메서드의 선얞부만 정의하고 구현은 X
    • 추상메서드 처럌 선얞부만 있고 몞통읎 없음

3.4 애너테읎션 타입 정의하Ʞ

  • @ Ʞ혞륌 붙읎고 읞터페읎슀륌 정의하는 것곌 동음

애너테읎션의 요소

  • 애너테읎션 낎에 선얞된 메서드륌 애너테읎션 요소띌고 부늄
    • 반환값읎 있고 맀개변수는 없는 추상 메서드의 형태
    • 상속을 통핎 구현하지 않아도 됚
    • 애너테읎션을 적용할 때 읎 요소듀의 값을 빠짐없읎 지정핎 쀘알 핹
    • 지정할 때 순서는 상ꎀ X
    • 각 요소는 Ʞ볞값을 가질 수 있고 값을 지정하지 않을 시 사용됚
    • 에너테읎션의 요소가 하나뿐읎고 읎늄읎 value 음 땐 요소의 읎늄을 생략 후 값만 적얎도 적용 가능
    • 요소의 타입읎 배엎읞 겜우 ꎄ혞{}륌 사용핎서 여러 개의 값을 지정
    • Ʞ볞값 또한 ꎄ혞{}로 지정 가능

java.lang.annotation.Annotation

  • 몚든 애너테읎션의 조상
  • 애너테읎션은 상속읎 허용되지 않윌므로 명시적윌로 extends 지정 불가능
  • Annotaion은 음반적읞 읞터페읎슀로 정의되얎 있음
    • equals(), hashCode(), toString()곌 같은 메서드듀읎 정의되얎 있윌므로 애너테읎션 객첎에서 혞출 가능
  • TestClass.class.getAnnotations()로 TestClass에 적용된 몚든 애너테읎션 혞출 가능 및 읞터페읎슀에 정의된 메서드 혞출 가능

마컀 애너테읎션 Marker Annotation

  • 요소가 하나도 정의되지 않은 애너테읎션을 마컀 애너테읎션읎띌고 부늄
    • 값을 지정할 필요가 없는 애너테읎션듀

애너테읎션 요소의 규칙

  • 반드시 지쌜알 하는 규칙듀
    • 요소의 타입은 Ʞ볞형, String, enum, 애너테읎션, class만 허용
    • () 안에 맀개변수륌 ì„ ì–ží•  수 없닀.
    • 예왞륌 ì„ ì–ží•  수 없닀.
    • 요소륌 타입 맀개변수로 정의할 수 없닀.
  • 큎래슀 객첎에는 핎당 큎래슀에 대한 몚든 정볎륌 갖고 있고 애너테읎션의 정볎도 포핚되얎 있음