1. μ§€λ„€λ¦­μŠ€(Generics)λž€?


μ§€λ„€λ¦­μŠ€(Generics)λž€?

  • 컴파일 μ‹œ νƒ€μž…μ„ 체크해 μ£ΌλŠ” κΈ°λŠ₯(compile-time type check) - JDK1.5
  • 객체의 νƒ€μž… μ•ˆμ •μ„±μ„ 높이고 ν˜•λ³€ν™˜μ˜ λ²ˆκ±°λ‘œμ›€μ„ μ€„μ—¬μ€Œ
ArrayList<Tv> tvList = new ArrayList<Tv>();
tvList.add(new Tv());    // OK.
tvList.add(new Audio()); // 컴파일 μ—λŸ¬.
// Tv t = (Tv)tvList.get(0);
Tv t = tvList.get(0); // ν˜•λ³€ν™˜ λΆˆν•„μš”
  • RuntimException인 ClassCastException을 Compiletimeμ—μ„œ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄
  • e.g. String str = null;보닀 String str = β€œβ€;둜 μ΄ˆκΈ°ν™”ν•˜μ—¬ NullPointerException νšŒν”Ό

2~3. νƒ€μž… λ³€μˆ˜


νƒ€μž… λ³€μˆ˜

  • 클래슀λ₯Ό μž‘μ„±ν•  λ•Œ, Object νƒ€μž… λŒ€μ‹  νƒ€μž… λ³€μˆ˜(E)λ₯Ό μ„ μ–Έν•΄μ„œ μ‚¬μš©

νƒ€μž… λ³€μˆ˜μ— λŒ€μž…ν•˜κΈ°

  • 객체 생성 μ‹œ, νƒ€μž… λ³€μˆ˜(E) λŒ€μ‹  μ‹€μ œ νƒ€μž…(Tv)을 지정(λŒ€μž…)
// νƒ€μž… λ³€μˆ˜ E λŒ€μ‹ μ— μ‹€μ œ νƒ€μž… Tvλ₯Ό λŒ€μž…
ArrayList<Tv> tvList = new ArrayList<Tv>();
  • νƒ€μž… λ³€μˆ˜ λŒ€μ‹  μ‹€μ œ νƒ€μž…μ΄ μ§€μ •λ˜λ©΄, ν˜•λ³€ν™˜ μƒλž΅κ°€λŠ₯

4~5. μ§€λ„€λ¦­μŠ€ μš©μ–΄, νƒ€μž…κ³Ό λ‹€ν˜•μ„±


μ§€λ„€λ¦­μŠ€ μš©μ–΄

  • Box<T> 지넀릭 클래슀. β€˜T의 Box’ λ˜λŠ” β€˜T Box’라고 읽음
  • T νƒ€μž… λ³€μˆ˜ λ˜λŠ” νƒ€μž… λ§€κ°œλ³€μˆ˜. (TλŠ” νƒ€μž… 문자)
  • Box μ›μ‹œ νƒ€μž… (raw type). 일반 클래슀

μ§€λ„€λ¦­μŠ€ νƒ€μž…κ³Ό λ‹€ν˜•μ„±

ArrayList<Tv>      list = new ArrayList<Tv>(); // OK.
ArrayList<Product> list = new ArrayList<Tv>(); // μ—λŸ¬.
  • μ°Έμ‘° λ³€μˆ˜μ™€ μƒμ„±μžμ˜ λŒ€μž…λœ νƒ€μž…μ€ μΌμΉ˜ν•΄μ•Ό 함
List<Tv> list = new ArrayList<Tv>();  // OK. λ‹€ν˜•μ„±. ArrayListκ°€ Listλ₯Ό κ΅¬ν˜„
List<Tv> list = new LinkedList<Tv>(); // OK. λ‹€ν˜•μ„±. LinkedListκ°€ Listλ₯Ό κ΅¬ν˜„
  • 지넀릭 ν΄λž˜μŠ€κ°„μ˜ λ‹€ν˜•μ„±μ€ 성립. (μ—¬μ „νžˆ λŒ€μž…λœ νƒ€μž…μ€ μΌμΉ˜ν•΄μ•Ό 함)
ArrayList<Product> list = new ArrayList<Product>();
list.add(new Product());
list.add(new Tv());
list.add(new Audio());
  • λ§€κ°œλ³€μˆ˜μ˜ λ‹€ν˜•μ„±λ„ 성립

7~8. Iterator, HashMapκ³Ό μ§€λ„€λ¦­μŠ€


Iterator<E>

Iterator<Student> it = list.iterator();
while (it.hasNext()) {
	Student s = it.next(); // ν˜•λ³€ν™˜ μƒλž΅ κ°€λŠ₯
}
  • 클래슀λ₯Ό μž‘μ„±ν•  λ•Œ, Object νƒ€μž… λŒ€μ‹  T 와 같은 νƒ€μž… λ³€μˆ˜λ₯Ό μ‚¬μš©

HashMap<K, V>

HashMap<String, Student> map = new HashMap<String, Student>();
map.put("μžλ°”μ™•", new Student("μžλ°”μ™•", 1, 1, 100, 100, 100));
  • μ—¬λŸ¬ 개의 νƒ€μž… λ³€μˆ˜κ°€ ν•„μš”ν•œ 경우, 콀마λ₯Ό κ΅¬λΆ„μžλ‘œ μ„ μ–Έ

9~11. μ œν•œλœ 지넀릭 클래슀, μ œμ•½


μ œν•œλœ 지넀릭 클래슀

class FruitBox<T extends Fruit> { // Fruit의 μžμ†λ§Œ νƒ€μž…μœΌλ‘œ 지정가λŠ₯
	ArrayList<T> list = new ArrayList<T>();
}
  • extends둜 λŒ€μž…ν•  수 μžˆλŠ” νƒ€μž…μ„ μ œν•œ
interface Eatable {}
class FruitBox<T extends Eatable> { ... }
  • μΈν„°νŽ˜μ΄μŠ€μΈ κ²½μš°μ—λ„ extendsλ₯Ό μ‚¬μš©

μ§€λ„€λ¦­μŠ€μ˜ μ œμ•½

Box<Apple> appleBox = new Box<Apple>();
Box<Grape> grapeBox = new Box<Grape>();
  • νƒ€μž… λ³€μˆ˜μ— λŒ€μž…μ€ μΈμŠ€ν„΄μŠ€ λ³„λ‘œ λ‹€λ₯΄κ²Œ κ°€λŠ₯
  1. static 멀버에 νƒ€μž… λ³€μˆ˜ μ‚¬μš© λΆˆκ°€ (μΈμŠ€ν„΄μŠ€ 곡톡이기 λ•Œλ¬Έμ—)
class Box<T> {
	static T item; // μ—λŸ¬.
	static int compare(T, t1, T t2) { ... } // μ—λŸ¬.
}
  1. λ°°μ—΄ 생성 μ‹œ νƒ€μž… λ³€μˆ˜ μ‚¬μš©λΆˆκ°€. νƒ€μž… λ³€μˆ˜λ‘œ λ°°μ—΄ 선언은 κ°€λŠ₯
class Box<T> {
	T[] itemArr; // OK. Tνƒ€μž…μ˜ 배열을 μœ„ν•œ μ°Έμ‘°λ³€μˆ˜
		...
	T[] toArray() {
		T[] tmpArr = new T[itemArr.length]; // μ—λŸ¬. 지넀릭 λ°°μ—΄ μƒμ„±λΆˆκ°€
		...
	}
}

12~14. μ™€μΌλ“œ μΉ΄λ“œ, 지넀릭 λ©”μ„œλ“œ


μ™€μΌλ“œ μΉ΄λ“œ <?>

  • ν•˜λ‚˜μ˜ μ°Έμ‘° λ³€μˆ˜λ‘œ λŒ€μž…λœ νƒ€μž…μ΄ λ‹€λ₯Έ 객체λ₯Ό μ°Έμ‘° κ°€λŠ₯
ArrayList<? extends Product> list = new ArrayList<Tv>();    // OK.
ArrayList<? extends Product> list = new ArrayList<Audio>(); // OK.
ArrayList<Product> list = new ArrayList<Tv>(); // μ—λŸ¬. λŒ€μž…λœ νƒ€μž… 뢈일치
  • <? extends T> μ™€μΌλ“œ μΉ΄λ“œμ˜ μƒν•œ μ œν•œ. T와 κ·Έ μžμ†λ“€λ§Œ κ°€λŠ₯
  • <? super T> μ™€μΌλ“œ μΉ΄λ“œμ˜ μƒν•œ μ œν•œ. T와 κ·Έ μ‘°μƒλ“€λ§Œ κ°€λŠ₯
  • <?> μ œν•œ μ—†μŒ. λͺ¨λ“  νƒ€μž…μ΄ κ°€λŠ₯. <? extends Object> 와 동일
static Juice makeJuice(FruitBox<? extends Fruit> box) {
		String tmp = "";
		for (Fruit f : box.getList()) {
				tmp += f + " ";
		}
		return new Juice(tmp);
}
  • λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜μ— μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ‚¬μš©

지넀릭 λ©”μ„œλ“œ

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) {
		...
	}
}
  • 클래슀의 νƒ€μž… λ§€κ°œλ³€μˆ˜<T>와 λ©”μ„œλ“œμ˜ νƒ€μž… λ§€κ°œλ³€μˆ˜ <T>λŠ” λ³„κ°œ
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));
System.out.println(Juicer.<Apple>makeJuice(appleBox));
  • λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ νƒ€μž…μ„ λŒ€μž…ν•΄μ•Ό(λŒ€λΆ€λΆ„ μƒλž΅ κ°€λŠ₯)
System.out.println(<Fruit>makeJuice(fruitBox));        // μ—λŸ¬. 클래슀 이름 μƒλž΅λΆˆκ°€
System.out.println(this.<Fruit>makeJuice(appleBox));   // OK.
System.out.println(Juicer.<Fruit>makeJuice(fruitBox)); // OK.
  • λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ νƒ€μž…μ„ μƒλž΅ν•˜μ§€ μ•Šμ„ λ•ŒλŠ” 클래슀 이름 μƒλž΅ λΆˆκ°€

15~16. 지넀릭 ν˜•λ³€ν™˜


지넀릭 νƒ€μž…μ˜ ν˜•λ³€ν™˜

Box<Object> objBox = null;
Box box = (Box)objBox;     // OK. 지넀릭 νƒ€μž… -> μ›μ‹œ νƒ€μž…. κ²½κ³  λ°œμƒ
objBox = (Box<Object>)box; // OK. μ›μ‹œ νƒ€μž… -> 지넀릭 νƒ€μž…. κ²½κ³  λ°œμƒ
objBox = (Box<Object>)strBox; // μ—λŸ¬. Box<String> -> Box<Object>
strBox = (Box<String>)objBox; // μ—λŸ¬. Box<Object> -> Box<String>
  • 지넀릭 νƒ€μž…κ³Ό μ›μ‹œ νƒ€μž… κ°„μ˜ ν˜•λ³€ν™˜μ€ λ°”λžŒμ§ ν•˜μ§€ μ•ŠμŒ
Box<Object>         objBox = (Box<Object>)new Box<String>(); // μ—λŸ¬. ν˜•λ³€ν™˜ λΆˆκ°€λŠ₯
Box<? extends Object> wBox = (Box<? extends Object>)new Box<String>(); // OK.
Box<? extends Object> wBox = new Box<String>(); // μœ„ λ¬Έμž₯κ³Ό 동일
// λ§€κ°œλ³€μˆ˜λ‘œ FruitBox<Fruit>, FruitBox<Apple>, FruitBox<Grape> 등이 κ°€λŠ₯
static Juice makeJuice<FruitBox<? extends Fruit> box) { ... }
FruitBox<? extends Fruit> box = new FruitBox<Fruit>(); // OK.
FruitBox<? extends Fruit> box = new FruitBox<Apple>(); // OK.
  • μ™€μΌλ“œ μΉ΄λ“œκ°€ μ‚¬μš©λœ 지넀릭 νƒ€μž…μœΌλ‘œλŠ” ν˜•λ³€ν™˜ κ°€λŠ₯

지넀릭 νƒ€μž…μ˜ 제거

  • μ»΄νŒŒμΌλŸ¬λŠ” 지넀릭 νƒ€μž…μ„ μ œκ±°ν•˜κ³ , ν•„μš”ν•œ 곳에 ν˜•λ³€ν™˜μ„ λ„£μŒ
  1. 지넀릭 νƒ€μž…μ˜ 경계(bound)λ₯Ό 제거
  2. 지넀릭 νƒ€μž… 제거 ν›„ νƒ€μž…μ΄ λΆˆμΌμΉ˜ν•˜λ©΄, ν˜•λ³€ν™˜ μΆ”κ°€
  3. μ™€μΌλ“œ μΉ΄λ“œκ°€ ν¬ν•¨λœ 경우, μ μ ˆν•œ νƒ€μž…μœΌλ‘œ ν˜•λ³€ν™˜ μΆ”κ°€

17~20. μ—΄κ±°ν˜•


μ—΄κ±°ν˜•(enum)

  • κ΄€λ ¨λœ μƒμˆ˜λ“€μ„ 같이 λ¬Άμ–΄ 놓은 것
class Card {
	enum Kind { CLOVER, HEART, DIAMOND, SPADE }
	enum Value { TWO, THREE, FOUR }
	final Kind kind; // νƒ€μž…μ΄ intκ°€ μ•„λ‹Œ Kind
	final Value value;
}

μž₯점

  • JavaλŠ” νƒ€μž…μ— μ•ˆμ „ν•œ μ—΄κ±°ν˜•μ„ 제곡
if(Card.Kind.CLOVER==Card.Value.TWO) { // 컴파일 μ—λŸ¬. νƒ€μž…μ΄ λ‹¬λΌμ„œ λΉ„κ΅λΆˆκ°€

μ—΄κ±°ν˜•μ˜ μ •μ˜μ™€ μ‚¬μš©

enum Direction { EAST, SOUTH, WEST, NORTH }
  • μ—΄κ±°ν˜•μ„ μ •μ˜ν•˜λŠ” 방법
class Unit {
	int x, y;      // μœ λ‹›μ˜ μœ„μΉ˜
	Direction dir; // μ—΄κ±°ν˜• μΈμŠ€ν„΄μŠ€ λ³€μˆ˜ μ„ μ–Έ
	void init() {
		dir = Direction.EAST; // μœ λ‹›μ˜ λ°©ν–₯을 EAST둜 μ΄ˆκΈ°ν™”
	}
}
  • μ—΄κ±°ν˜• νƒ€μž…μ˜ λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  μ‚¬μš©ν•˜λŠ” 방법
if (dir == Direction.EAST) {
	x++;
} else if (dir > Direction.WEST) { // μ—λŸ¬. μ—΄κ±°ν˜• μƒμˆ˜μ— λΉ„κ΅μ—°μ‚°μž μ‚¬μš© λΆˆκ°€
	...
} else if (dir.compareTo(Direction.WEST) > 0) {
	...
}
  • μ—΄κ±°ν˜• μƒμˆ˜μ˜ 비ꡐ에 == 와 compareTo() μ‚¬μš© κ°€λŠ₯

μ—΄κ±°ν˜•μ˜ 쑰상 - java.lang.Enum

  • λͺ¨λ“  μ—΄κ±°ν˜•μ€ Enum의 μžμ†μ΄λ©°, μ•„λž˜μ˜ λ©”μ„œλ“œλ₯Ό μƒμ†λ°›μŒ
// μ—΄κ±°ν˜• μƒμˆ˜μ˜ 이름을 λ¬Έμžμ—΄λ‘œ λ°˜ν™˜
String name()
// μ—΄κ±°ν˜• μƒμˆ˜κ°€ μ •μ˜λœ μˆœμ„œλ₯Ό λ°˜ν™˜
int ordinal()
// μ§€μ •λœ μ—΄κ±°ν˜•μ—μ„œ nameκ³Ό μΌμΉ˜ν•˜λŠ” μ—΄κ±°ν˜• μƒμˆ˜λ₯Ό λ°˜ν™˜
T valueOf(Class<T> enumType, String name)
// λͺ¨λ“  μ—΄κ±°ν˜• μƒμˆ˜λ₯Ό λ°°μ—΄λ‘œ λ°˜ν™˜
static E[] values()
// μ—΄κ±°ν˜• μƒμˆ˜ μ΄λ¦„μœΌλ‘œ κ°’ λ°˜ν™˜
static E valueOf(String name)

21~22. μ—΄κ±°ν˜• 멀버 μΆ”κ°€ν•˜κΈ°


μ—΄κ±°ν˜• 멀버 μΆ”κ°€ν•˜κΈ°

enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) }
  • λΆˆμ—°μ†μ μΈ μ—΄κ±°ν˜• μƒμˆ˜μ˜ 경우, μ›ν•˜λŠ” 값을 κ΄„ν˜Έ μ•ˆμ— 적음
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;
	}
}
  • κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•˜λ €λ©΄, μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ™€ μƒμ„±μžλ₯Ό μƒˆλ‘œ μΆ”κ°€ν•΄ μ€˜μ•Ό 함
Direction d = new Direction(1); // μ—λŸ¬. μ—΄κ±°ν˜•μ˜ μƒμ„±μžλŠ” μ™ΈλΆ€μ—μ„œ ν˜ΈμΆœλΆˆκ°€
  • μ—΄κ±°ν˜•μ˜ μƒμ„±μžλŠ” λ¬΅μ‹œμ μœΌλ‘œ private 이기 λ•Œλ¬Έμ—, μ™ΈλΆ€μ—μ„œ 객체 생성 λΆˆκ°€

23~26. ν‘œμ€€ μ• λ„ˆν…Œμ΄μ…˜


μ• λ„ˆν…Œμ΄μ…˜μ΄λž€?

  • μ£Όμ„μ²˜λŸΌ ν”„λ‘œκ·Έλž˜λ° 언어에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμœΌλ©°, μœ μš©ν•œ 정보λ₯Ό 제곡

@Override

  • μ˜€λ²„λΌμ΄λ”©μ„ μ˜¬λ°”λ₯΄κ²Œ ν–ˆλŠ”μ§€ μ»΄νŒŒμΌλŸ¬κ°€ μ²΄ν¬ν•˜κ²Œ 함
  • μ˜€λ²„λΌμ΄λ”©ν•  λ•Œ λ©”μ„œλ“œ 이름을 잘λͺ» μ λŠ” μ‹€μˆ˜λ₯Ό ν•˜λŠ” κ²½μš°κ°€ 많음

@Deprecated

  • μ•žμœΌλ‘œ μ‚¬μš©ν•˜μ§€ μ•Šμ„ 것을 ꢌμž₯ν•˜λŠ” ν•„λ“œλ‚˜ λ©”μ„œλ“œμ— λΆ™νž˜
  • @Deprecated의 μ‚¬μš© 예, Date 클래슀의 getDate()

@FunctionalInterface

  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ— 뢙이면, μ»΄νŒŒμΌλŸ¬κ°€ μ˜¬λ°”λ₯΄κ²Œ μž‘μ„±ν–ˆλŠ”μ§€ 체크
    • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ—λŠ” ν•˜λ‚˜μ˜ μΆ”μƒλ©”μ„œλ“œλ§Œ κ°€μ Έμ•Ό ν•œλ‹€λŠ” μ œμ•½μ΄ 있음
  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ™€ μ „λž΅ νŒ¨ν„΄

@SuppressWarning

  • 컴파일러의 κ²½κ³  λ©”μ‹œμ§€κ°€ λ‚˜νƒ€λ‚˜μ§€ μ•Šκ²Œ μ–΅μ œ
  • κ΄„ν˜Έ μ•ˆμ— μ–΅μ œν•˜κ³ μž ν•˜λŠ” 경고의 μ’…λ₯˜λ₯Ό λ¬Έμžμ—΄λ‘œ 지정

29~33. 메타 μ• λ„ˆν…Œμ΄μ…˜


메타 μ• λ„ˆν…Œμ΄μ…˜μ΄λž€?

  • μ• λ„ˆν…Œμ΄μ…˜μ„ μœ„ν•œ μ• λ„ˆν…Œμ΄μ…˜

@Target

  • μ• λ„ˆν…Œμ΄μ…˜μ„ μ •μ˜ν•  λ•Œ, μ μš©λŒ€μƒ 지정에 μ‚¬μš©

@Retention

  • μ• λ„ˆν…Œμ΄μ…˜μ΄ μœ μ§€λ˜λŠ” 기간을 μ§€μ •ν•˜λŠ”λ° μ‚¬μš©

@Documented, @Inherited

  • javadoc으둜 μž‘μ„±ν•œ λ¬Έμ„œμ— ν¬ν•¨μ‹œν‚€λ €λ©΄ @Documented
  • μ• λ„ˆν…Œμ΄μ…˜μ„ μžμ† ν΄λž˜μŠ€μ— μƒμ†ν•˜κ³ μžν•  λ•Œ, @Inherited

@Repeatable

  • λ°˜λ³΅ν•΄μ„œ 뢙일 수 μžˆλŠ” μ• λ„ˆν…Œμ΄μ…˜μ„ μ •μ˜ν•  λ•Œ μ‚¬μš©

34~37. μ• λ„ˆν…Œμ΄μ…˜ νƒ€μž… μ •μ˜, μš”μ†Œ


μ• λ„ˆν…Œμ΄μ…˜ νƒ€μž… μ •μ˜ν•˜κΈ°

@interface DateTime {
	String yymmdd();
	String hhmmss();
}
  • μ• λ„ˆν…Œμ΄μ…˜μ„ 직접 λ§Œλ“€μ–΄ μ“Έ 수 있음
// μ •μ˜
@interface TestInfo {
	int count();
	String testedBy();
	String[] testTools();
	TestType testType();
	DateTime testDate();
}
// μ‚¬μš©
@TestInfo(
	count = 3, testedBy = "Kim",
	testTools = {"JUnit", "AutoTester"},
	testType = TestType.FIRST,
	testDate = @DateTime(yymmdd = "160101", hhmmss = 235959")
)
public class NewClass { ... }
  • μ• λ„ˆν…Œμ΄μ…˜μ˜ λ©”μ„œλ“œλŠ” 좔상 λ©”μ„œλ“œμ΄λ©°, μ• λ„ˆν…Œμ΄μ…˜μ„ μ μš©ν•  λ•Œ 지정 (μˆœμ„œ X)

μ• λ„ˆν…Œμ΄μ…˜μ˜ μš”μ†Œ

@interface TestInfo {
	int count() default 1;  // 기본값을 1둜 지정
}
@TestInfo // @TestInfo(count=1)κ³Ό 동일
public class NewClass { ... }
  • 적용 μ‹œ 값을 μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄, μ‚¬μš©λ  수 μžˆλŠ” κΈ°λ³Έκ°’ 지정 κ°€λŠ₯ (null μ œμ™Έ)
@interface TestInfo {
	String value();
}
@TestInfo("passed") // @TestInfo(value="passed")와 동일
public class NewClass { ... }
  • μš”μ†Œκ°€ ν•˜λ‚˜μ΄κ³  이름이 value일 λ•Œ, μš”μ†Œμ˜ 이름 μƒλž΅ κ°€λŠ₯
@interface TestInfo {
	String[] testTools();
}
@TestInfo(testTools = {"JUnit", "AutoTester"})
@TestInfo(testTools = "JUnit")
@TestInfo(testTools = {}) // 값이 없을 경우 λΉˆκ΄„ν˜Έ ν•„μš”
  • μš”μ†Œμ˜ νƒ€μž…μ΄ 배열인 경우, μ€‘κ΄„ν˜Έ μ‚¬μš©

λͺ¨λ“  μ• λ„ˆν…Œμ΄μ…˜μ˜ 쑰상

  • Annotation은 λͺ¨λ“  μ• λ„ˆν…Œμ΄μ…˜μ˜ μ‘°μƒμ΄μ§€λ§Œ 상속 λΆˆκ°€
  • 사싀 Annotation은 μΈν„°νŽ˜μ΄μŠ€

마컀 μ• λ„ˆν…Œμ΄μ…˜

  • μš”μ†Œκ°€ ν•˜λ‚˜λ„ μ •μ˜λ˜μ§€ μ•Šμ€ μ• λ„ˆν…Œμ΄μ…˜
public @interface Override{}
public @interface Test{}

μ• λ„ˆν…Œμ΄μ…˜ μš”μ†Œμ˜ κ·œμΉ™

  • μ• λ„ˆν…Œμ΄μ…˜μ˜ μš”μ†Œλ₯Ό μ„ μ–Έν•  λ•Œ κ·œμΉ™
    • μš”μ†Œμ˜ νƒ€μž…μ€ κΈ°λ³Έν˜•, String, enum, μ• λ„ˆν…Œμ΄μ…˜, Class 만 ν—ˆμš©
    • κ΄„ν˜Έ μ•ˆμ— λ§€κ°œλ³€μˆ˜ μ„ μ–Έ X
    • μ˜ˆμ™Έ μ„ μ–Έ X
    • μš”μ†Œλ₯Ό νƒ€μž… λ§€κ°œλ³€μˆ˜λ‘œ μ •μ˜ X