자바 4

Mango·2022년 3월 9일
0

Java

목록 보기
6/8
  • 지네릭스(Generics)란?
    - 컴파일시 타입을 체크해 주는 기능 - JDK 1.5
//Tv객체만 저장할 수 있는 ArrayList를 생성
ArrayList<Tv> tvList = new ArrayList<Tv>();

tvList.add(new Tv());    //OK
tvList.add(new Audio()); //컴파일 에러. Tv 외에 다른 타입은 저장 불가

지네릭스의 장점
1. 타입 안정성을 제공한다.
2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.

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

  • 타입 변수에 대입하기
    - 객체를 생성시, 타입변수(E) 대신 실제 타입(Tv)을 지정(대입)
    - 타입 변수 대신 실제 타입이 지정되면, 형변환 생략 가능

// 타입 변수 E 대신에 실제 타입 Tv를 대입
ArrayList<Tv> tvList = new ArrayList<Tv>();
  • 지네릭스 용어

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

  • 지네릭 타입과 다형성

    - 참조 변수와 생성자의 대입된 타입은 일치해야 한다.

    ArrayList<Tv> list = new ArrayList<Tv>(); //OK
    ArrayList<Product> list = new ArrayList<Tv>(); //error

    - 지네릭 클래스간의 다형성은 성립.(여전히 대입된 타입은 일치해야)

    List<Tv> list = new ArrayList<Tv>(); //OK. ArrayList가 List를 구현
    List<tv> list = new LinkedList<Tv>(); //OK. LinkedList가 List를 구현

    - 매개변수의 다형성도 성립

    ArrayList<Product> list = newArrayList<Product>();
    list.add(new Product());
    list.add(new Tv()); //OK
    list.add(new Audio()); //OK
  • Iterator< E>
    - 클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용

  • HashMap<K,V>
    - 여러 개의 타입 변수가 필요한 경우, 콤마(,)를 구분자로 선언

HashMap<String, Student> map = new HashMap<String, Student>(); //생성
map.put("자바왕", new Student("자바왕",1,1,100,100,100)); //데이터 저장
  • 제한된 지네릭 클래스
    - extends로 대입할 수 있는 타입을 제한
class FruitBox<T, extends Fruit> { //Fruit의 자손만 타입으로 지정가능
	ArrayList<T> list = new ArrayList<T>();
		...
}
FruitBox<Apple> appleBox = new FruitBox<Apple>(); //OK
FruitBox<Toy> toyBox = new FruitBox<Toy>(); //error

- 인터페이스인 경우에도 extends를 사용

interface Eatable {}
class FruitBox<T extends Eatable> {...}
  • 지네릭스의 제약

    - 타입 변수에 대입은 인스턴스 별로 다르게 가능

    Box<Apple> appleBoc = new Box<Apple>(); //OK. Apple객체만 저장가능
    Box<Grape> grapeBox = new Box<Grape>(); //OK. Grape객체만 저장가능

    - static멤버에 타입 변수 사용 불가

    class Box<T> {
    	static T item; //error
       static int compare(T t1, T t2) {...} //error
    }

    - 배열 생성할 때 타입 변수 사용불가. 타입 변수로 배열 선언은 가능

    class Box<T> {
    	T[] itemArr; //OK. T타입의 배열을 위한 참조변수
       	...
        T[] toArray() {
        	T[] tmpArr = new T[itemArr.length]; //error. 지네릭 배열 생성불가 
           -> new 연산자는 뒤에 타입이 확정되어 있어야 하는데T는 어떤 타입이 올 지 모르기 때문에
        }
    }
  • 와일드 카드<?>
    - 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능

    ArrayList<? extends Product> list = new ArrayList<Tv>(); //OK
    ArrayList<? extends Product> list = new ArrayList<Audio>(); //OK
    ArrayList<Product> list = new ArrayList<Tv>(); //error. 대입된 타입 불일치

    < ? extends T> 와일드 카드의 상한 제한. T와 그 자손들만 가능
    < ? super T> 와일드 카드의 하한 제한. T와 그 조상들만 가능
    < ?> 제한 없음. 모든 타입이 가능. <? extends Object>와 동일

    - 메서드의 매개변수에 와일드 카드를 사용

    static Juice makeJuice(FrutBox<? extends Fruit> box) {
    	String tmp = "";
    	for(Fruit f : box.getList()) tmp += f + " ";
    	return new Juice(tmp);
    }
    
  • 지네릭 메서드
    - 지네릭 타입이 선언된 메서드(타입 변수는 메서드 내에서만 유효)

    static <T> void sori(List<T> list, Comparator<? super T> c)

    - 클래스 타입 매개변수 < T>와 메서드 타입 매개변수 < T>는 별개

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

    - 메서드를 호출할 때마다 타입을 대입해야(대부분 생략 가능)

    FruitBox<Fruit> fruitBox = new FruitBox<FuitBox>();
    FruitBox<Apple> appleBox = new FruitBox<Apple>();
    	...
    System.out.println(Juicer.<Fruit>makeJuice(fruitBox));
    System.out.println(Juicer.<Apple>makeJuicer(appleBox));

    - 메서드를 호출할 때 타입을 생략하지 않을 때는 클래스 이름 생략 불가

    System.out.println(<Fruit>makeJuice(fruitBox)); //error. 클래스 이름 생략 불가
    System.out.println(this.<Fruit>makeJuice(fruitBox)); //OK
    System.out.printkb(Juicer.<Fruit>makeJuice(fruitBox)); //OK
  • 지네릭 타입의 형변환
    - 지네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다.(경고 발생)

    Box<Object> objBox = null;
    Box box = (Box)objBox; //OK. 지네릭 타입 -> 원시 타입. 경고 발생
    objBox = (Box<Object>)box; //OK. 원시 타입 -> 지네릭 타입. 경고 발생
    
    objBox = (Box<Object>)strBox; //error. Box<String> -> Box<Object>
    strBox = (Box<String>)objBox; //error. Box<Object> -> Box<String>

    - 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능

    Box<Object> objBox = (Box<Objeck>)new Box<String>(); //error
    Box<? extends Object>wBox = (Box<? extends Object>)new Box<String>(); //OK
    Box<? extends Object> wBox = new Box<String>(); //위 문장과 동일
  • 지네릭 타입의 제거
    - 컴파일러는 지네릭 타입을 제거하고, 필요한 곳에 형변환을 넣는다.
    ① 지네릭 타입의 경계(bound)를 제거
    ② 지네릭 타입 제거 후에 타입이 불일치하면, 형변환을 추가
    ③ 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가

  • 열거형(enum)
    - 관련된 상수들을 같이 묶어 놓은 것. Java는 타입에 안전한 열거형을 제공
    - 열거형을 정의하는 방법

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

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

    class Unit {
    	int x, y; //유닛의 위치
    	Direction dir; //열거형 인스턴스 변수를 선언
    
    	void init() {
    		dir = Direction.EAST; //유닛의 방향을 EAST로 초기화
    	}
    }

    - 열겨형 상수의 비교에 ==와 compareTo()사용가능

    if(dir == Direction.EAST) {
    	x++;
    } else if (dir > Direction.WEST) {//error. 열겨형 상수에 비교연산자 사용 불가
    	...
    } else if(dir.compareTo(Direction.WEST) > 0 ) { ... //compareTo는 가능
  • 열겨형의 조상 - java.lang.Enum
    - 모든 열겨형은 Enum의 자손이며, 메소드를 상속받는다.
    - values(), valueOf()는 컴파일러가 자동으로 추가

  • 열거형에 멤버 추가하기
    - 불연속적인 열거형 상수의 경우, 원하는 값을 괄호()안에 적는다.

    enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) }

    - 괄호()를 사용하려면, 인스턴스 변수와 생성자를 새로 추가해 줘야 한다.
    - 열거형의 생성자는 묵시적으로 private이므로, 외부에서 객체생성 불가

    Direction d = new Direction(1); //error. 열거형의 생성자는 외부에서 호출 불가
  • 애너테이션이란?
    - 주석처럼 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공

  • 표준 애너테이션
    - Java에서 제공하는 애너테이션

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

    🔸 @Deprecated
    - 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.
    - @Deprecated의 사용 예, Date클래스의 getDate()
    - @Deprecated가 붙은 대상이 사용된 코드를 컴파일 하면 나타나는 메시지

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

    🔸 @SuppressWarnings
    - 컴파일러의 경고메시지가 나타나지 않게 억제한다.
    - 괄호()안에 억제하고자 하는 경고의 종류를 문자열로 지정
    - 둘 이상의 경구를 동시에 억제하려면 다음과 같이 한다.

    @SuppressWarnings({"deprecation", "unchecked", "varargs"})

    - '-Xlint'옵션으로 컴파일하면, 경고메시지를 확인할 수 있다. 괄호[]안이 경고의 종류.

  • 메타 애너테이션
    - 메타 애너테이션은 '애너테이션을 위한 애너테이션'

    🔸 @Target
    - 애너테이션을 정의할 때, 적용대상 지정에 사용

    🔸 @Retention
    - 애너테이션이 유지(retention)되는 기간을 지정하는데 사용
    - 컴파일러에 의해 사용되는 애너테이션의 유지 정택은 SOURCE이다.
    - 실행시에 사용 가능한 애너테이션의 정책은 RUNTIME이다.

    🔸 @Documented, @Inherited
    - javadoc으로 작성한 문서에 포함시키려면 @Documented를 붙인다.
    - 애너테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.

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

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

  • 애너테이션의 요소

  • 모든 애너테이션의 조상 -> interface Annotation

  • 마커 애너테이션 - Marker Annotation
    - 요소가 하나도 정의되지 않은 애너테이션

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

profile
How u do that

0개의 댓글

Powered by GraphCDN, the GraphQL CDN