Home 지네릭스, 열거형, 애너테이션
Post
Cancel

지네릭스, 열거형, 애너테이션

지네릭스

다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스 컴파일 시의 타입체크를 해주는 기능이다. 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.

선언

1
2
3
4
5
6
7
8
9
10
class Box<T>{
	T item;
	void setItem(T item) {this.item = item;}
	T getItem() {return item}
}

Box<String> b = new Box<String>();
b.setItem(new Object()); // String 타입이 아니기 때문에 에러
b.setItem("ABC");
String item = b.getItem();

** 타입변수는 꼭 T를 사용하지 않아도 되며 타입변수가 여러개인 경우 Map<K, V>와 같이 콤마를 구분자로 나열하면 된다.

  • static 멤버에 타입 변수 T를 사용할 수 없다. ex) Box< Apple >.item 과 Box< Grape >.item이 달라선 안된다.
  • 지네릭타입의 배열을 생성할 수 없다.
  • 지네릭 클래스끼리 상속됐을 경우 사용할 수 있지만 대입된 타입이 상속관계에 있다고 다르게 사용할 수는 없다. ex) Box< Fruit > appleBox = new Box < Apple >(); (X) Box< Apple > appleBox = new FruitBox < Apple >(); (O)
  • class FruitBox< T extends Fruit > 과 같이 선언하게 되면 타입에 Fruit의 자손 타입만 담을 수 있게 된다.
1
2
3
4
5
6
class Juicer {
	static Juice makeJuice(FruitBox<Fruit> box){
		String tmp = "";
		for(Fruit f : box.getList()) tmp += f + " ";
		return new Juice(tmp);
}

** 위와 같이 static에 지네릭스를 적용할 수 없다.

1
2
3
4
5
6
class Juicer {
	static Juice makeJuice(FruitBox<? extends Fruit> box){
		String tmp = "";
		for(Fruit f : box.getList()) tmp += f + " ";
		return new Juice(tmp);
}

** ? extends T = 자손들만 가능 ? super T = 조상들만 가능 ? = 모든 타입 가능

열거형

서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용하다.

1
2
3
4
5
6
7
class Card{
	enum Kind { CLOVER, HEART, DIAMOND, SPADE }
	enum Value { TWO, THREE, FOUR }
	
	final Kind kind;
	final Value value;
}

** 열거형 상수의 값이 불연속적인 경우 CLOVER(2), HEART(4) 이런식으로 ()를 이용해주면 된다. - 현재 CLOVER(1), TWO(1)과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum Direction {
	EAST(1, ">"), SOUTH(2,"V"), WEST(3, "<"), NORTH(4,"^");
	
	private final int value;
	private final String symbol;

	Direction(int value, String symbol) {
		this.value = value;
		this.symbol = symbol;
	}
	
	public int getValue() { return value; }
	public String getSymbol() { return symbol; }
}

** 하나의 열거형 상수에 여러 값을 지정할 수 있다. 하지만 그에 맞게 인스턴스 변수와 생성자 등을 추가해주어야 한다. 외부에서 접근할 수 있도록 메서드도 추가해주었다.

1
2
3
4
5
6
7
public Dirction rotate(int num){
	num = num % 4;
	if(num < 0) num += 4;
	return DIR_ARR[(value-1+num) % 4]; // DIR_ARR[] = Direction.values()
} // Direction enum 내의 함수.

System.out.println(Direction.EAST.rotate(1)); // 이런식으로 사용 가능하며 결과는 SOUTH

** enum 에서의 추상클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
enum Transportation{
	BUS(100) {int fare(int distance) {return distance * BASIC_FARE; } }
	TRAIN(150) {int fare(int distance) {return distance * BASIC_FARE; } }

	protected final int BASIC_FARE;
	
	Transportation(int basicFare) { BASIC_FARE = basicFare; } // Bus(100)에서 100이 BASIC_FARE가 된다.
	
	abstract int fare(int distance);
}

System.out.println(Transportation.BUS.fare(120)); // 100 * 120이 fare가 된다.
System.out.println(Transportation.TRAIN.fare(120)); // 150 * 120

애너테이션(annotation)

프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것. 주석처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있다는 장점이 있다.

  • 표준 애너테이션
애너테이션설명
@Override컴파일러에게 오버라이딩하는 메서드라는 것을 알림
@Deprecated앞으로 사용하지 않을 것을 권장하는 대상에 붙임
@SuppressWarnings컴파일러의 특정 경고메시지가 나타나지 않게 해줌

이 외에 여러 애너테이션들이 있다.

** @Override 를 붙일 경우 오버라이딩 시 함수명 실수 등을 잡아 줄 수 있다.

  • 애너테이션 타입 정의
1
2
3
4
5
6
7
8
9
10
@interface Testinfo{
	int count();
	String testsedBy();
	String[] testTools();
}

@TestInfo(
	count = 3, testedBy = "Kim",
	testTools = { "JUnit", "AutoTester" }
)
This post is licensed under CC BY 4.0 by the author.