자바의정석 12장

서현우·2022년 4월 5일
0

자바의정석

목록 보기
12/22

ch12-1 지네릭스(Generics)란?

  • 컴파일시 타입을 체크해 주는 기능(compile-tile type check)
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10) //OK.
list.add("20") //ERROR
//타입 체크가 강화됨. 지네릭스 덕분에
  • 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌

지네릭스의 장점

1.타입 안정성을 제공
2.타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.
(ClassCastException 형변환에러를 줄일 수 있다)
(어떻게 하면 런타입에러를 컴파일타임에러로 끌어올 수 있을까?)

ch12-2 타입 변수

  • 클래스를 작성할 때, Object타입 대신 타입변수(E)를 선언해서 사용.

ch12-3 타입 변수에 대입하기

  • 객체를 생성시, 타입 변수(E) 대신 실제 타입(Tv)을 대입
ArrayList<Tv> tvList = new ArrayList<Tv>();
  • 타입 변수 대신 실제 타입이 지정되면, 형변환 생략가능

ch12-4 지네릭스 용어

Box : 지네릭 클래스. 'T의 Box' 또는 'T Box'라고 읽는다.
T : 타입 변수 또는 타입 매개변수.(T는 타입 문자)
Box : 원시 타입(raw type)

ch12-5 지네릭 타입과 다형성

  • 참조 변수와 생성자의 대입된 타입은 일치해야 한다.
    (조상 자손 관계도 불가)
ArrayList<Tv> = new ArrayList<Tv>(); //OK. 일치
ArrayList<Product> = new ArrayList<Tv>(); //에러. 불일
  • 지네릭 클래스간의 다형성은 성립.(여전히 대입된 타입은 일치해야 함)
List<Tv> list = new ArrayList<Tv>(); //OK. 다형성
List<Tv> list = new LinkedList<Tv>(); //OK. 다형성
  • 매개변수의 다형성도 성립
ArrayList<Product> = new ArrayList<Product>();
list.add(new Product());
list.add(new Tv()); //자손도 OK
list.add(new Audio()); //자손도 OK

ch12-7 Iterator

  • 클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용

ch12-8 HashMap<K,V>

  • 여러 개의 타입 변수가 필요한 경우, 콤마(,)를 구분자로 선언
HashMap<String, Student> map = new HashMap<String, Student>(); //생성
map.put("자바왕", new Student("자바왕",1,1,100,100,100)); //데이터 저장

ch12-9 제한된 지네릭 클래스

  • extends로 대입할 수 있는 타입을 제한
class FruitBox<T extends Fruit> {
	ArryaList<T> list = new ArrayList<T>();
	...
} //Fruit의 자손만 대입 가능

FruitBox<Apple> appleBox = new FruitBox<Apple>(); //OK.
FruitBox<Toy> toyBox = new FruitBox<Toy>(); //에러. Toy는 Fruit의 자손이 아님
  • 인터페이스인 경우에도 extends를 사용

ch12-11 지네릭스 제약

  • 타입 변수에 대입은 인스턴스 별로 다르게 가능
  • static멤버에 타입 변수 사용 불가
  • 배열 생성할 때 타입 변수 사용불가. 타입 변수로 배열 선언은 가능
    T[] itemArr; //OK
    T[] tmpArr = new T[itemArr.length]; //에러

ch12-12 와일드 카드 <?>

  • 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능

    '<? extends T>' : T와 그 자손들만 가능
    '<? super T>' : T와 그 조상들만 가능
    '<?>' : 제한 없음. <? extends Object>와 동일

ArrayList<? extends Product> list = new ArrayList<Tv>(); //OK
ArrayList<? extends Product> list = new ArrayList<Audio>(); //OK
  • 메서드의 매개변수에 와일드 카드를 사용
static Juice makeJuice(FruitBox<? extends Fruit> box) {
	String tmp="";
	...
	System.out.println(Juicer.makeJuice(new FruitBox<Fruit>()));
	System.out.println(Juicer.makeJuice(new FruitBox<Apple>()));
}

ch12-14 지네릭 메서드

  • 지네릭 타입이 선언된 메서드(타입 변수는 메서드 내에서만 유효)

  • 클래스의 타입 매개변수와 메서드의 타입 매개변수 는 별개

class FruitBox<T> {
	...
	static <T> void sort(List<T> list, Comparator<? super T> c) {
	...
	}
}
  • 메서드를 호출할 때마다 타입을 대입해야(대부분 생략 가능)
  • 메서드를 호출할 때 타입을 생략하지 않을 때는 클래스 이름 생략 불가

ch12-15 지네릭 타입의 형변환

  • 지네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다.(경고발생)
  • 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능

ch12-16 지네릭 타입의 제거

  • 컴파일러는 지네릭타입을 제거하고, 필요한 곳에 형변환을 넣는다.
  1. 지네릭 타입의 경계(bound)를 제거
  2. 지네릭 타입 제거 후에 타입이 불일치하면, 형변환을 추가
  3. 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가

12-17 열거형(enum)

  • 관련된 상수들을 같이 묶어 놓은 것. Java는 타입에 안전한 열거형을 제공
    (값, 타입 둘 다 체크)

12-18 열거형의 정의와 사용

  • 열거형을 정의하는 방법
    enum 열거형이름 { 상수명1, 상수명2, ...}
    //0, 1 ...

  • 열거형 타입의 변수를 선언하고 사용하는 방법

  • 열거형 상수의 비교에 ==와 compareTo() 사용가능
    (비교연산자 사용불가)

12-19 열거형의 조상 - java.lang.Enum

  • 모든 열거형은 Enum의 자손이며, 아래의 메서드를 상속받는다.
Class<E> getDeclaringClass() //열거형의 Class객체를 반환
String name() //열거형 상수의 이름을 문자열로 반환
int ordinal() //열거형 상수가 정의된 순서를 반환(0부터 시작)
T valueOf(Class<T> enumType, String name) 
//지정된 열거형에서 name과 일치하는 열거형 상수를 반환
  • values(), valueOf()는 컴파일러가 자동으로 추가

ch12-21 열거형에 멤버 추가하기

  • 불연속적인 열거형 상수의 경우, 원하는 값을 괄호()안에 적는다.
    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;}
}
  • 열거형의 생성자는 묵시적으로 private이므로, 외부에서 객체생성 불가
Direction d = new Direction(1); //에러. 열거형의 생성자는 외부에서 호출불가

ch12-23 애너테이션이란?

  • 주석처럼 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공
  • 애너테이션의 사용예
@Test //이 메서드가 테스트 대상임을 테스트 프로그램에 알린다.
public void method() {
	...
}

ch12-24 표준 애너테이션

ch12-25 @Override

  • 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.
  • 오버라이딩할 때 메서드이름을 잘못적는 실수를 하는 경우가 많다.
  • 오버라이딩할 때는 메서드 선언부 앞에 @Override를 붙이자.

12-26 @Deprecated

  • 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.
  • @Deprecated의 사용 예, Date클래스의 getDate()
@Deprecated
public int getDate() {
	return normalize().getDayOfMonth();
}
  • @Deprecated가 붙은 대상이 사용된 코드를 컴파일하면 나타나는 메세지
    Note: ... use or overrides a deprecated API.

12-27 @FunctionallInterface

  • 함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크
  • 함수형 인터페이스에는 하나의 추상메서드만 가져야 한다는 제약이 있음

12-28 @SuppressWarnings

  • 컴파일러의 경고메세지가 나타나지 않게 억제한다.

  • 괄호()안에 억제하고자 하는 경고의 종류를 문자열로 지정

  • 둘 이상의 경고를 동시에 억제 가능

  • '-Xlint' 옵션으로 컴파일하면, 경고메세지를 확인할 수 있다.

12-29 메타 애너테이션

  • 애너테이션을 위한 애너테이션
  • 메타 애너테이션은 java.lang.annotation패키지에 포함

12-30 @Target

  • 애너테이션을 정의할 때, 적용대상 지정에 사용

12-31 @Retention

  • 애너테이션이 유지(retention)되는 기간을 지정하는데 사용

SOURCE : 소스 파일에만 존재. 클래스파일에는 존재하지 않음.
CLASS : 클래스 파일에 존재. 실행시 사용불가. 기본값
RUNTIME : 클래스 파일에 존재. 실행시에 사용가능.

12-32 @Documented, @Inherited

  • javadoc으로 작성한 문서에 포함시키려면 @Documented를 붙인다.

  • 애너테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.

12-33 @Repeatable

  • 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용
  • @Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있다.
  • @Repeatable인 @...를 하나로 묶을 컨테이너 애너테이션도 정의해야 함

12-34 애너테이션 타입 정의하기

  • 애너테이션을 직접 만들어 쓸 수 있다.
@interface 애너테이션이름 {
	타입 요소이름(); //애너테이션의 요소를 선언
	...
}
  • 애너테이션의 메서드는 추상메서드이며, 애너테이션을 적용할 때 지정(순서X)

12-35 애너테이션의 요소

  • 적용시 값을 지정하지 않으면, 사용될 수 있는 기본값 지정 가능(null제외)

  • 요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능

  • 요소의 타입이 배열인 경우, 괄호{}를 사용해야 한다.

12-36 모든 애너테이션의 조상

  • Annotation은 모든 애너테이션의 조상이지만 상속은 불가
  • 사실 Annotation은 인터페이스이다.

12-37 마커 애너테이션 - Marker Annotation

  • 요소가 하나도 정의되지 않은 애너테이션

12-38 애너테이션 요소의 규칙

  • 애너테애션의 요소를 선언할 때 아래의 규칙을 반드시 지켜야 한다.
    • 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨
    • 괄호()안에 매개변수를 선언할 수 없다.
    • 예외를 선언할 수 없다.
    • 요소를 타입 매개변수로 정의할 수 없다.
profile
안녕하세요!!

0개의 댓글