본문 바로가기

TIL(Today I Learned)

TIL-231021(자바의정석 Chapter12 '지네릭스, 열거형, 애너테이션')

📝오늘 공부한 것

  • 자바 스터디

 

📌 자바의 정석 스터디

[ 지네릭스 ]

다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능

 

지네릭스의 장점

  1. 타입 안정성을 제공한다.
  2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.

지네릭 클래스의 선언

지네릭스의 제한

  • 지네릭 클래스의 객체를 생성할 때 객체별로 다른 타입을 지정하는 것은 적절하다.
  • 그러나 static멤버에 타입 변수 T를 사용할 수 없다. T는 인스턴스변수로 간주되기 때문이다. → static멤버는 타입 변수에 지정된 타입, 즉 대입된 타입의 종류에 관계없이 동일한 것이어햐 하기 때문이다.
  • 지네릭 타입의 배열을 생성하는 것도 허용되지 않는다. 지네릭 배열 타입의 참조변수를 선언하는 것은 가능하지만, ‘new T[10]’ 과 같이 배열을 생성하는 것은 안된다는 뜻이다. → 지네릭 배열을 생성할 수 없는 것은 new 연산자 때문인데, 이 연산자는 컴파일 시점에 타입 T가 뭔지 정확히 알아야 한다.
  • 꼭 지네릭 배열을 생성해야할 필요가 있을 때는, new연산자 대신 ‘Reflection API’의 newInstance()와 같이 동적으로 객체를 생성하는 메서드로 배열을 생성하거나, Object배열을 생성해서 복사한 다음에 ‘T[ ]’로 형변환하는 방법 등을 사용한다.

지네릭 클래스의 객체 생성과 사용

  • 지네릭 클래스의 객체를 생성할 때는 참조변수와 생성자에 대입된 타입(매개변수화된 타입)이 일치해야 한다.
  • 단, 두 지네릭 클래스의 타입이 상속관계에 있고, 대입된 타입이 같은 것은 괜찮다.
  • 추정이 가능한 경우 타입을 생략할 수 있다.
  • 생성된 지네릭 클래스의 객체에 ‘void add(T item)’으로 객체를 추가할 때, 대입된 타입과 다른 타입의 객체는 추가할 수 없다.

제한된 지네릭 클래스

  • ‘extends’를 사용하면, 특정 타입의 자손들만 대입할 수 있게 제한할 수 있다.
  • 클래스가 아니라 인터페이스를 구현해야 한다는 제약이 필요하다면, 이때도 ‘extend’를 사용한다. ‘implements’를 사용하지 않는다.
  • 클래스 A의 자손이면서 B인터페이스도 구현해야 한다면 ‘&’기호로 연결한다.

와일드 카드

지네릭 타입이 다른 것만으로는 오버로딩이 성립하지 않는다.

지네릭 타입은 컴파일러가 컴파일할 때만 사용하고 제거한다. 그래서 오버로딩이 아니라 ‘메서드 중복 정의’가 된다.

<? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능

<? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능

<?> : 제한 없음. 모든 타입이 가능. <? extend Object>와 동일

* 지네릭 클래스와 달리 와일드 카드에는 ‘&’를 사용할 수 없다.

* Comparator에는 항상 <? super T>가 습관적으로 따라 붙는다.

지네릭 메서드

  • 메서드의 선언부에 지네릭 타입이 선언된 메서드를 지네릭 메서드라 한다.
  • Collections.sort()가 지네릭 메서드이며, 지네릭 타입의 선언 위치는 반환 타입 바로 앞이다.
  • static 멤버에는 타입 매개변수를 사용할 수 없지만, 이처럼 메서드에 지네릭 타입을 선언하고 사용하는 것은 가능한다.
  • 지네릭 베서드를 호출할 때, 대입된 타입을 생략할 수 없는 경우에는 참조변수나 클래스 이름을 생략할 수 없다는 것이다.
  • 같은 클래스 내에 있는 멤버들끼리는 참조변수나 클래스이름, 즉 ‘this’나 ‘클래스이름.’을 생략하고 메서드 이름만으로 호출이 가능하지만, 대입된 타입이 있을 때는 반드시 써줘야 한다.

 

[ 열거형 ]

열거형에 멤버 추가하기

  • 열거형의 인스턴스 변수는 반드시 final이어야 한다는 제한은 없지만, value는 열거형 상수의 값을 저장하기 위한 것이므로 final을 붙였다. 그리고 외부에서 이 값을 얻을 수 있게 getValue()도 추가하였다.
  • 열거형 Direction에 새로운 생성자가 추가되었지만, 위와 같이 열거형의 객체를 생석할 수 없다. 열거형의 생성자는 제어자가 묵시적으로 private이기 때문이다.
  • 하나의 열거형 상수에 여러 값을 지정할 수도 있다.

 

[ 애너테이션 ]

표준 애너테이션

@Override : 조상의 메서드를 오버라이딩하는 것이라는 걸 컴파일러에게 알려주는 역할

@Deprecated : 더 이상 사용되지 않는 필드나 메서드에 붙이는 것.

@FuntionalInterface : 함수형 인터페이스를 선언할 때, 컴파일러가 함수형 인터페이스를 올바르게 선언했는지 확인하고, 잘못된 경우 에러를 발생

@SuppressWarnings : 컴파일러가 보여주는 경고메시지가 나타나지 않게 억제

@SafeVarargs :

  • 가변인자의 매개변수를 사용할 때 경고를 억제
  • static이나 final이 붙은 메서드와 생성자에만 붙일 수 있다. 즉, 오버라이드될 수 있는 메서드에슨 사용할 수 없다. @SafeVarargs로 ‘unchecked’경고는 억제할 수 있지만, ‘varargs’경고는 억제할 수 없기 때문에 습관적으로 @SafeVarargs와 @SuppressWarnings(”varargs”)를 같이 붙인다.

메타 애너테이션

@Target : 애너테이션이 적용가능한 대상을 지정하는데 사용

@Retention : 애너테이션이 유지되는 기간을 지정하는데 사용

@Documented : 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다.

@Inherited : 애너테이션이 자손 클래스에 상속되도록 한다.

@Repeatable : 보통은 하나의 대상에 한 종류의 애너테이션을 붙이는데, ‘@Repeatable’이 붙은 애너테이션은 여러 번 붙일 수 있다.

@Native : 네이티브 메서드에 의해 참조되는 ‘상수 필드’에 붙이는 애너테이션

 

애너테이션 타입 정의하기

마커 애너테이션 Marker Annotation

Serializable이나 Cloneable인터페이스처럼, 요소가 하나도 정의되지 않은 애너테이션을 마커 애너테이션이라고 한다.

 

애너테이션 요소의 규칙

  • 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된다.
  • ( )안에 매개변수를 선언할 수 없다.
  • 예외를 선언할 수 없다.
  • 요소를 타입 매개변수로 정의할 수 없다.