티스토리 뷰

반응형

[Java의 정석 - http://www.yes24.com/Product/Goods/24259565]

 

1. 지네릭스(Generics)

1.1 지네릭스란?

  • 지네릭스
    : 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크(compile-time type check)를 해주는 기능
  • 지네릭스의 장점
    • 타입 안정성을 제공
      • 의도하지 않은 타입의 객체가 저장되는 것을 막고, 저장된 객체를 꺼내올 때 원래의 타입과 다른 타입으로 잘못 형변환되어 발생할 수 있는 오류를 줄여줌
    • 타입 체크와 형변환을 생략할 수 있으므로 코드가 간결해진다

1.2 지네릭 클래스의 선언

  • 타입 변수(type variable) : 임의의 참조형 타입을 의미
  • 지네릭스의 용어
    • class Box<T> {}
      • Box<T> : 지네릭 클래스
      • T : 타입 변수 또는 타입 매개변수(T는 타입 문자)
      • Box : 원시 타입(raw type)
    • Box<String> b = new Box<String>();
      • Box<String> : 지네릭 타입 호출. 타입 매개변수에 타입을 지정하는 것
        • 컴파일하면 원시 타입인 Box로 바뀜(지네릭 타입이 제거됨)
      • String : 매개변수화된 타입(parameterized type)
  • 지네릭스의 제한
    • static 멤버에 타입 변수 T를 사용할 수 없다
    • instanceof, new 연산자에 T를 피연산자로 사용할 수 없다
      • 지네릭 배열을 생성해야할 필요가 있으면 Reflection API의 newInstance()나 Object 배열 생성해서 복사한 다음에 T[]로 형변환하는 방법 등을 사용한다

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

  • 객체를 생성할 때 참조변수와 생성자에 매개변수화된 타입이 일치해야 한다
    • 상속관계에 있는 것도 안 된다
  • 객체를 생성할 때 두 지네릭 클래스의 타입이 상속관계에 있고 매개변수화된 타입이 같은 것은 괜찮다
  • void add(T item)으로 객체를 추가할 때 매개변수화된 타입과 다른 타입의 객체는 추가할 수 없다
    • 매개변수화된 타입의 자손들은 가능하다

1.4 제한된 지네릭 클래스

  • 지네릭 타입에 'extends'를 사용하면 특정 타입의 자손들만 대입할 수 있게 제한할 수 있다
    • 인터페이스 제한할 때도 'implements'가 아닌 'extends' 사용

1.5 와일드 카드

  • 다른 곳에 지네릭 클래스를 사용할 때 어려움이 있음
    • 지네릭 타입이 다른 것만으로는 오버로딩이 성립하지 않음
  • 와일드 카드
    • 기호 '?'로 표현
    • 어떠한 타입도 될 수 있음
    • 'extends'와 'super'로 상한(upper bound)와 하한(lower bound)를 제한
      • <? extends ?> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
      • <? super ?> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
      • <?> : 제한 없음. 모든 타입이 가능. <? extends Object>와 동일

1.6 지네릭 메서드

  • static 멤버에는 타입 매개변수를 사용할 수 없지만 메서드에 지네릭 타입을 선언하고 사용하는 것은 가능하다
    ex) static <T> void sort(List<T> list, Coparator<? super T> c){}
    • 메서드에 선언된 지네릭 타입은 지역변수를 선언한 것과 유사. 메서드 내에서 지역적으로만 사용됨
  • 지네릭 메서드를 호출할 때 대입된 타입을 생략할 수 없는 경우에는 참조변수나 클래스 이름을 생략할 수 없다

1.7 지네릭 타입의 형변환

  • 지네릭 타입과 넌지네릭(non-generic) 타입간의 형변환은 항상 가능(경고 발생)
  • 대입된 타입이 다른 지네릭 타입 간에는 형변환 불가
    • Box<> extends Object> wBox = new Box<String>(); 은 가능
  • 매개변수화된 타입에 Object 대신 와일드 카드를 쓰면 형변환이 용이

1.8 지네릭 타입의 제거

  • 컴파일러는 지네릭 타입을 이용해서 소스파일을 체크하고 필요한 곳에 형변환을 넣어준다
  • 컴파일된 파일(*.class)에는 지네릭 타입에 대한 정보가 없다
    • 지네릭이 도입되기 이전의 소스 코드와의 호환성을 유지하기 위해
  • 지네릭 제거 과정
    • 1. 지네릭 타입의 경계(bound)를 제거
      • 지네릭 타입이 <T extends Fruit>라면 T는 Fruit, <T>라면 Object로 치환되고 클래스 옆의 선언은 제거된다
    • 2. 지네릭 타입을 제거한 후에 타입이 일치하지 않으면 형변환을 추가한다

 

2. 열거형(enums)

2.1 열거형이란?

  • 서로 관련된 상수를 편리하게 선언하기 위한 것
  • 타입에 안전한 열거형(typesafe enum)
    • 실제 값이 같아도 타입이 다르면 컴파일 에러가 발생
  • 열거형 상수를 사용하면 상수의 값이 바껴도 기존의 소스를 다시 컴파일하지 않아도 된다

2.2 열거형의 정의와 사용

  • 정의 - 괄호 {} 안에 상수의 이름을 나열
  • 사용 - 열거형이름.상수명
    • 비교
      • == 사용 가능
      • <, > 같은 비교연산자는 사용 불가
      • compareTo() 사용 가능
    • switch 문의 조건식에도 사용가능
      • case 문에 열거형의 이름 말고 상수의 이름만 적어야됨
  • 모든 열거형의 조상 - java.lang.Enum
    • Enum 클래스에 정의된 메서드
      • Class<E> getDeclaringClass() : 열거형의 Class 객체를 반환한다
      • String name() : 열거형 상수의 이름을 문자열로 반환한다
      • int ordinal() : 열거형 상수가 정의된 순서를 반환한다(0부터 시작)
        • 이 값을 열거형 상수의 값으로 사용하지 않는 것이 좋음(내부적으로 사용하는 값이므로)
      • T valueOf(Class<T> enumType, String name) : 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다

2.3 열거형에 멤버 추가하기

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
  • 열거형에 추상 메서드 추가하기
    • 추상 메서드를 이용해 열거형의 상수 마다 다르게 동작하는 것을 구현할 수 있게 함
enum Transportation {
	BUS(100) {
    	int fare(int distance) { return distance*BASIC_FARE; }
    },
    TRAIN(150)) {
    	int fare(int distance) { return distance*BASIC_FARE; }
    },
    SHIP(100) {
    	int fare(int distance) { return distance*BASIC_FARE; }
    },
    AIRPLANE(300) {
    	int fare(int distance) { return distance*BASIC_FARE; }
    };
    
    abstract int fare(int distance);	// 거리에 따라 요금을 계산하는 추상 메서드
    
    protected final int BASIC_FARE;	// protected로 해야 각 상수에서 접근 가능
    
    Transportation(int basicFare) {
    	BASIC_FARE = basicFare;
    }
    
    public int getBasicFare() { return BASIC_FARE; }
}

 

2.4 열거형의 이해

  • 열거형은 class에 static final로 상수들이 선언되어 있고 생성자가 private으로 되어있는거랑 유사

 

3. 애너테이션(annotation)

3.1 애너테이션이란?

  • 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것
  • 주석처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있음
    • 해당 프로그램에 미리 정의된 종류와 형식으로 작성해야만 의미가 있음
  • 메타 애너테이션(meta annotaion) : 애너테이션을 정의하는데 사용되는 애너테이션의 애너테이션

3.2 표준 애너테이션

  • @Override : 컴파일러에게 오버라이딩하는 메서드라는 것을 알린다
    • 메서드 앞에만 붙일 수 있는 애너테이션
    • 컴파일러가 같은 이름의 메서드가 조상에 있는지 확인하고 없으면 에러 메시지를 출력한다
  • @Deprecated : 앞으로 사용하지 않을 것을 권장하는 대상에 붙인다
  • @SuppressWarnings : 컴파일러의 특정 경고메시지가 나타나지 않게 해준다
    • 종류
      • "deprecation" : @Deprecated가 붙은 대상을 사용해서 발생하는 경고
      • "unchecked" : 지네릭스 타입을 지정하지 않았을 때 발생하는 경고
      • "rawtypes" : 지네릭스를 사용하지 않아서 발생하는 경고
      • "varargs" : 가변인자 타입이 지네릭 타입일 때 발생하는 경고 억제
    • main 함수에 붙일 수도 있지만 경고가 발생하는 대상에만 애너테이션을 붙여서 경고의 억제 범위를 최소화하는 것이 좋다
  • @SafeVarargs : 지네릭스 타입의 가변인자에 사용한다(JDK1.7)
    • 메서드에 선언된 가벼인자의 타입이 non-reifiable 타입일 경우 해당 메서드를 선언하는 부분과 호출하는 부분에서 "unchecked" 경고가 발생하는데 이 경고를 억제하기 위해 사용한다
      • refiable : 컴파일 후에도 제거되지 않는 타입
      • non-refiable : 컴파일 후에 제거되는 타입(지네릭은 대부분 여기에 해당)
    • static이나 final이 붙은 메서드와 생성자에만 붙일 수 있음
      • 오버라이드 될 수 있는 메서드에는 사용될 수 없음
    • @SafeVarargs를 붙이면 해당 메서드를 호출하는 곳에서 발생하는 "unchecked" 경고가 억제된다
      • @SuppressWarnings("unchecked")를 사용해도 되지만 메서드 선언부, 호출되는 곳에 다 붙여야 동일한 효과
    • 'varargs' 경고는 억제할 수 없음
  • @FunctionalInterface : 함수형 인터페이스라는 것을 알린다(JDK1.8)
    • 컴파일러가 '함수형 인터페이스'를 올바르게 선언했는지 확인하고 잘못된 경우 에러를 발생시킨다
  • @Native : native 메서드에서 참조되는 상수 앞에 붙인다(JDK1.8)

3.3 메타 애너테이션

  • 애너테이션에 붙이는 애너테이션으로 애너테이션을 정의할 때 애너테이션의 적용대상(target)이나 유지기간(retention)등을 지정하는데 사용
  • @Target : 애너테이션이 적용가능한 대상을 지정하는데 사용한다(메타)
    • 애너테이션 적용대상의 종류
      • ANNOTATION_TYPE : 애너테이션
      • CONSTRUCTOR : 생성자
      • FIELD : 필드(멤버변수, enum상수), 기본형에 사용
      • LOCAL_VARIABLE : 지역변수
      • METHOD : 메서드
      • PACKAGE : 패키지
      • PARAMETER : 매개변수
      • TYPE : 타입(클래스, 인터페이스, enum), 타입을 선언할 때 애너테이션을 붙일 수 있음
      • TYPE_PARAMETER : 타입 매개변수(JDK1.8)
      • TYPE_USE : 타입이 사용되는 모든 곳(JDK1.8), 해당 타입의 변수를 선언할 때 붙일 수 있음, 참조형에 사용
  • @Documented : 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다(메타)
    • 자바에서 제공하는 기본 애너테이션 중에 @Override와 @SuppressWarnings를 제외하고 모두 이게 붙어있음
  • @Inherited : 애너테이션이 자손 클래스에 상속되도록 한다(메타)
  • @Retention : 애너테이션이 유지되는 범위를 지정하는데 사용한다(메타)
    • 애너테이션 유지정책(retention policy)의 종류
      • SOURCE : 소스 파일에만 존재. 클래스 파일에는 존재하지 않음.
        • @Override나 @SuppressWarnings처럼 컴파일러가 사용하는 애너테이션
      • CLASS : 클래스 파일에 존재. 실행시에 사용불가. 기본값.
      • RUNTIME : 클래스 파일에 존재. 실행시에 사용 가능.
        • 리플렉션(reflection)을 통해 클래스 파일에 저장된 애너테이션의 정보를 읽어서 처리할 수 있음
        • @FunctionalInterface
  • @Repeatable : 애너테이션을 반복해서 적용할 수 있게 한다(메타)
    • 같은 이름의 애너테이션이 여러 개가 하나의 대상에 적용될 수 있기 때문에 이 애너테이션들을 하나로 묶어서 다룰 수 있는 애너테이션도 추가로 정의해야 한다
  • @Native
    • 네이티브 메서드(native method)에 의해 참조되는 상수 필드(constant field)에 붙이는 애너테이션
      • 네이티브 메서드 : JVM이 설치된 OS의 메서드
      • 메서드 선언부만 정의하고 구현은 하지 않음
      • 자바의 일반 메서드와 호출방법은 다르지 않지만 실제로 호출되는 것은 OS의 메서드
    • JNI(Java Native Interface)로 자바에 정의된 네이티브 메서드와 OS의 메서드를 연결해주는 작업이 필요함

3.4 애너테이션 타입 정의하기

@interface 애너테이션 이름 {
	타입 요소이름();	// 애너테이션의 요소를 선언한다
    ...
}
  • 애너테이션의 요소
    • 반환값이 있고 매개변수는 없는 추상 메서드의 형태를 가짐
    • 상속을 통해 구현하지 않아도 됨
    • 애너테이션을 적용할 때 이 요소들의 값을 빠짐없이 지정해줘야 함
      • 요소의 이름을 같이 적어주므로 순서는 상관 없음
    • 기본값을 가질 수 있음
    • 요소가 오직 하나 뿐이고 이름이 value인 경우 애너테이션을 적용할 때 요소의 이름을 생략하고 값만 적어도 됨
  • java.lang.annotation.Annotation
    • 모든 애너테이션의 조상
    • 애너테이션은 상속이 허용되지 않으므로 명시적으로 지정할 수는 없음
  • 마커 애너테이션(Marker Annotation)
    • 요소가 하나도 정의되지 않은 애너테이션
    • @Serializable, @Cloneable 등
  • 애너테이션 요소의 규칙
    • 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된다
    • ()안에 매개변수를 선언할 수 없다
    • 예외를 선언할 수 없다
    • 요소를 타입 매개 변수로 선언할 수 없다
  • 클래스 객체의 getAnnotation(), getAnnotations()를 사용해 애너테이션 정보를 가져올 수 있음
반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함