Frinee의 코드저장소

[Java] Generics, Enum, Annotation

by Frinee

1. 제네릭스(Generics)

1.1. 제네릭스란?

  • 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입을 체크해 주는 기능
  • 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌.
  • 제네릭스의 장점
    1. 타입의 안정성을 제공함.
    2. 타입체크의 형변환을 생략할 수 있으므로 코드가 간결해짐.

1.2. 제네릭 클래스의 선언

// 여기서 T는 임의의 참조형 타입이다. 
// T에 원하는 타입을 지정하여 사용할 수 있다.
class Box<T> {
	T item;
	
	void setItem(T item) { this.item = item; }
	T getItem() { return item;}
}

Box<String> b = new Box<String>();  // 타입 T 대신 실제 타입 지정
b.setItem(new Object());            // 에러, 지정한 String 외에는 지정불가
b.setItem("ABC");                   // OK
String item = (String)b.getItem(); // 형변환이 필요없음
  • 주의사항
    • 제네릭 타입을 지정하지 않아도 객체 생성이 허용되지만 안전하지 않다는 경고가 발생
    • 타입 변수 T에 Object타입을 지정하면, 경고가 발생하지 않음

  • 제네릭스 용어
    • Box<T> : 제네릭 클래스, ‘T의 Box’ 또는 ‘T Box’라고 읽는다.
    • T : 타입 변수 또는 타입 매개변수. (T는 타입 문자)
    • Box : 원시 타입(raw type)
  • 제네릭스 제한
    • T는 인스턴스변수로 간주되기 때문에 모든 객체에 대해 동일하게 동작해야 하는 static멤버에 타입 변수 T를 사용할 수 없음
    • 제네릭 타입의 배열 선언은 가능하나 배열을 생성하는 것은 허용되지 않음
      • new 연산자는 컴파일 시점에 타입을 정확하게 알고 있어야 함.

1.3. 제네릭 클래스의 객체 생성과 사용

  1. 참조변수와 생성자에 대입된 타입이 일치해야 함.
  2. 두 타입이 상속관계에 있는 경우에도 대입된 타입은 일치해야 함.
  3. JDK1.7부터는 추정이 가능한 경우 타입을 생략할 수 있게 됨.
Box<Apple> appleBox = new Box<>();  // JDK1.7부터 가능
Box<Apple> appleBox = new Box<Apple>();  // OK
Box<Apple> appleBox = new Box<Grape>();  // 에러
Box<Fruit> appleBox = new Box<Apple>();  // 에러

1.4. 제한된 제네릭 클래스

  • 타입 매개변수 T에 지정할 수 있는 타입의 종류를 제한하는 방법이 존재함.
  • 제네릭에 extends 를 사용하면 특정 타입의 자손들만 대입할 수 있게 제한할 수 있음.
  • 인터페이스를 구현하는 제약을 사용할 때에도 extends 를 사용한다.
class FruitBox<T extends Fruit> {    // Fruit의 자손 타입만 지정가능
	ArrayList<T> list = new ArrayList<T>();
	...
}

1.5. 와일드 카드

// 매개변수에 과일박스를 대입하면 주스를 만들어 반환하는 클래스
class Juicer { 
	static Juice makeJuice(FruitBox<Fruit> box) { 
		String tmp = "";
		for(Fruit f : box.getList()) tmp += f + " ";
		return new Juice(tmp);
	}
}
  • 이 경우, 제네릭 타입을 FruitBox<Fruit> 로 고정해버리면 Apple 과 같은 다른 과일의 타입을 활용할 수 없는 문제가 발생
  • 이럴 때 사용하기 위해 고안된 것이 와일드 카드이며 와일드 카드 기호는 “?” 로 표현
  • extends 와 super 로 제한할 수 있음.
    • <? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
    • <? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
    • <?> : 제한 없음. 모든 타입이 가능

1.6. 제네릭 메서드

  • 메서드의 선언부에 제네릭 타입이 선언된 메서드를 제네릭 메서드라 한다.
  • 제네릭 메서드는 제네릭 클래스가 아닌 클래스에서도 정의가 가능하다.
// Collections.sort()
static <T> void sort(List<T> List, Comparator<? super T> c)

class FruitBox<T> {
		...
	static <T> void sort(List<T> list, Comparator<? super T> c){
		...
	}
}

 

2. 열거형(Enum)

2.1. 열거형(Enum)이란?

  • 서로 관련된 상수를 편리하게 선언하기 위한 기능
  • 자바의 열거형은 값뿐만 아니라 타입도 관리하기 때문에 논리적 오류를 줄일 수 있음
class Card {
	enum Kind { CLOVER, HEART, DIAMOND, SPADE }
	enum Value { TWO, THREE, FOUR }
	
	final Kind kind;
	final Value value;
}

2.2. 열거형의 정의와 사용

enum 열거형이름 { 상수명1, 상수명2, ... }

enum Direction { EAST, SOUTH, WEST, NORTH }

class Unit {
	int x, y;
	Direction dir;
	
	void init() {
		dir = Driection.EAST;
	}
}
  • 열거형 상수간의 비교는 == 를 사용할 수 있음.
  • 열거형의 메서드 
메서드 설명
Class<E> getDeclaringClass() 열거형의 Class객체를 반환
String name() 열거형 상수의 이름을 문자열로 반환
int ordinal() 열거형 상수가 정의된 순서를 반환 (0부터 시작)
T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환
static E values() 열거형에 정의된 모든 상수를 출력
  • 열거형의 값 지정하기
enum Direction { 
	EAST(1), SOUTH(5), WEST(-1), NORTH(10);
	
	private final int value;
	Direction(int value) { this.value = value; }
	public int getValue() { return value; } 
 }

 

3. 애너테이션(Annotation)

3.1. 애너테이션(Annotation)이란?

  • 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각하고 개발을 했다고 한다..
  • 소스코드의 주석 /** ~ */ 에 소스코드에 대한 정보를 저장하고, 소스코드 주석으로부터 HTML문서를 생성하는 프로그램(javadoc.exe)을 만들어 사용함.
  • 이 기능을 응용해서 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 애너테이션이다.
  • 애너테이션은 주석처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 줄 수 있음

3.2. 표준 애너테이션

애너테이션 설명
@Override 컴파일러에게 오버라이딩하는 메서드라는 것을 알린다.
@Deprecated 앞으로 사용하지 않을 것을 권장하는 대상에게 붙인다.
@SuppressWarnings 컴파일러의 특정 경고메시지가 나타나지 않게 해준다.
@SafeVarargs 지네릭스 타입의 가변인자에 사용한다. (JDK1.7)
@FunctionalInterface 함수형 인터페이스라는 것을 알린다.(JDK1.8)
@Native native메서드에서 참조되는 상수 앞에 붙인다. (JDK1.8)

메타 애너테이션

  • 애너테이션을 위한 애너테이션, 즉 애너테이션에 붙이는 애너테이션
  • 애너테이션을 정의할 때 애너테이션의 적용대상이나 유지기간 등을 지정하는데 사용
애너테이션 설명
@Target 애너테이션이 적용가능한 대상을 지정하는데 사용
@Documented 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다.
@Inherited 애너테이션이 자손 클래스에 상속되도록 한다.
@Retention 애너테이션이 유지되는 범위를 지정하는데 사용
@Repeatable 애너테이션을 반복해서 적용할 수 있게 한다.(JDK1.8)

애너테이션 요소 규칙

  • 요소의 타입은 기본형, String, Enum, Annotation, Class만 허용
  • ( )안에 매개변수를 선언할 수 없다.
  • 예외를 선언할 수 없음
  • 요소를 타입 매개변수로 정의할 수 없음.

 

블로그의 정보

프리니의 코드저장소

Frinee

활동하기