제네릭스(Generics)
•
컴파일 시 타입을 체크(강화)해주는 기능(complie-time type check) (jdk 1.5부터)
•
객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여준다
•
장점
◦
타입 안정성을 제공한다 (ClassCastException 방지)
◦
타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다
타입 변수(=타입 매개변수)
•
제네릭 클래스를 작성할 때 Object타입(일반 클래스) 대신 타입 변수(E)를 선언해서 사용
•
객체를 생성 시 타입 변수(E) 대신 실제 타입(Tv)를 지정(대입)
•
참조 변수와 생성자의 대입된 타입은 일치해야 한다
(jdk 1.7부터 생성자에 타입 지정은 일치하다는 가정 하에 생략 가능하다)
•
제네릭 클래스 간의 다형성은 성립 (여전히 대입된 타입은 일치해야 한다)
•
매개변수의 다형성도 성립
Iterator<E>
•
클래스를 작성할 때 Object 타입 대신 T와 같은 타입 변수를 사용
HashMap<K,V>
•
여러 개의 타입 변수가 필요한 경우 콤마(,)를 구분자로 선언
제한된 제네릭 클래스
•
extends로 대입할 수 있는 타입을 제한
•
인터페이스인 경우에도 extends를 사용
제네릭스의 제약
•
타입 변수에 대입은 인스턴스 별로 다르게 가능
•
static 멤버에 타입 변수 사용 불가 (static 멤버는 모든 인스턴스에 공통이기 때문에)
•
배열 생성할 때 타입 변수 사용 불가. 타입 변수로 배열 선언은 가능
와일드카드 <?>
•
하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능
◦
<? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
◦
<? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
◦
<?> : 제한 없음. 모든 타입이 가능. <? extends Object>와 동일
•
메서드의 매개변수에 와일드 카드를 사용
제네릭 메서드
•
제네릭 타입이 선언된 메서드(타입 변수는 메서드 내에서만 유효)
•
클래스의 타입 매개변수<T>와 메서드의 타입 매개변수 <T>는 별개
•
메서드를 호출할 때마다 타입을 대입해야함(대부분 생략 가능)
•
메서드를 호출할 때 타입을 생략하지 않을 때는 클래스 이름 생략 불가
와일드 카드 vs 제네릭 메서드
•
와일드 카드 : 하나의 참조변수로 서로 다른 타입이 대입된 여러 제네릭 객체를 다루기 위한 것
•
제네릭 메서드 : 메서드를 호출할 때마다 다른 제네릭 타입을 대입할 수 있게 한 것
제네릭 타입의 형변환
•
제네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다 (경고 발생)
•
와일드 카드가 사용된 제네릭 타입으로는 형변환 가능
제네릭 타입의 제거
•
컴파일러는 제네릭 타입을 제거하고 필요한 곳에 형변환을 넣는다
1.
제네릭 타입의 경계(bound)를 제거 (<T> → Object)
2.
제네릭 타입 제거 후에 타입이 불일치하면 형변환을 추가
3.
와일드 카드가 포함된 경우 적절한 타입으로 형변환 추가
열거형(enum)
•
관련된 상수들을 같이 묶어 놓은 것. Java는 타입에 안전한 열거형을 제공한다
열거형 정의와 사용
•
정의 : enum 열거형이름 { 상수명1, 상수명2, ... }
•
열거형 타입의 변수를 선언하고 사용하는 방법
•
열거형 상수의 비교에 ==와 compareTo() 사용가능
열거형의 조상 - java.lang.Enum 클래스
•
모든 열거형은 Enum의 자손이며, 아래의 메서드를 상속 받는다
•
values(), valueOf()는 컴파일러가 자동으로 추가해준다
◦
values() : Direction[] dArr = Direction.values();
◦
valueOf() : Direction d = Direction.valueOf(”WEST”);
열거형에 멤버 추가하기
•
불연속적인 열거형 상수의 경우 원하는 값을 괄호()안에 적는다 (여러개 가능)
•
괄호()를 사용하려면 인스턴스 변수와 생성자를 새로 추가해줘야 한다
•
열거형의 생성자는 묵시적으로 private이므로 외부에서 객체생성 불가
애너테이션
•
주석처럼 프로그래밍 언어에 영향을 미치지 않으며 유용한 정보를 제공
•
애너테이션의 사용 예시
표준 애너테이션
•
Java에서 제공하는 애너테이션
@Override
•
오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다
•
오버라이딩을 할 때 메서드 이름을 잘못 적는 실수를 하는 경우가 많다
•
오버라이딩 할 때는 메서드 선언부 앞에 @Override를 붙이자
@Deprecated
•
앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다
ex. Date 클래스의 getDate()
•
@Deprecated가 붙은 대상이 사용된 코드를 컴파일하면 나타나는 메시지
@FunctionalInterface
•
함수형 인터페이스에 붙이면 컴파일러가 올바르게 작성했는지 체크
•
함수형 인터페이스에는 하나의 추상메서드만 가져야 한다는 제약이 있음
@SuppressWarnings
•
컴파일러의 경고메시지가 나타나지 않게 억제한다
•
괄호()안에 억제하고자하는 경고의 종류를 문자열로 지정
•
둘 이상의 경고를 동시에 억제하려면 다음과 같이 한다
•
‘-Xlint’ 옵션으로 컴파일하면 경고메시지를 확인할 수 있다. 괄호[]안이 경고의 종류
메타 애너테이션
•
‘애너테이션을 위한 애너테이션'으로 애너테이션을 만들 때 사용한다
•
메타 애너테이션은 java.lang.annotation 패키지에 포함된다
@Target
•
애너테이션을 정의할 때 적용대상 지정에 사용한다
@Retention
•
애너테이션이 유지되는 기간을 지정하는데 사용
•
컴파일러에 의해 사용되는 애너테이션의 유지 정책은 SOURCE이다
•
실행 시에 사용 가능한 애너테이션의 정책은 RUNTIME이다
@Documented, @Inherited
•
javadoc으로 작성한 문서에 포함시키려면 @Documented를 붙인다
•
애너테이션을 자손 클래스에 상속하고자 할 때 @Inherited를 붙인다
@Repeatable
•
반복해서 붙일 수 있는 애너테이션을 정의할 때 사용
•
@Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있다
•
@Repeatable인 @ToDo를 하나로 묶을 컨테이너 애너테이션도 정의해야한다
애너테이션 타입 정의하기
•
애너테이션을 직접 만들어 쓸 수 있다
•
애너테이션의 메서드는 추상 메서드이며 애너테이션을 적용할 때 지정 (순서 상관X)
애너테이션의 요소
•
적용 시 값을 지정하지 않으면 사용될 수 있는 기본값 지정 가능 (null 제외)
•
요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능
•
요소의 타입이 배열인 경우 괄호{}를 사용해야 한다
모든 애너테이션의 조상 - java.lang.annotation.Annotation
•
Annotation은 모든 애너테이션의 조상이지만 상속은 불가
•
사실 Annotation은 인터페이스이다
마커 애너테이션 - Marker Annotation
•
요소가 하나도 정의되지 않은 애너테이션
애너테이션 요소의 규칙
•
애너테이션의 요소를 선언할 때 아래의 규칙을 반드시 지켜야 한다
◦
요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨
◦
괄호()안에 매개변수를 선언할 수 없다
◦
예외를 선언할 수 없다
◦
요소를 타입 매개변수로 정의할 수 없다