제네릭 플러스 알파

cutiepazzipozzi·2023년 3월 17일
2

지식스택

목록 보기
7/35
post-thumbnail

이펙티브 자바에서 제네릭을 다룬 내용을 나름 정리해보고자 한다.
내용은 아마도.. 계속.. 추가될..ㅇ ㅖ ㅈ ㅓ ㅇ ..

알아두면 매우 좋은 제네릭 공식 F4

1. raw 형태로 사용하지 말자

List 이렇게만 선언하는 것이 raw 타입

얘는 타입도 선언 안해주는데 왜 씀? 이라고 물으신다면..
-> (제너릭이 등장하기 전의 코드와의) 호환성 때문!
(이 호환성이라는 것에 대한 정확한 예시는 이해하고 추가해야할 거 같다)
-> 클래스 리터럴와 instanceOf 연산자는 로 형태가 필요,,

(로) List => 제네릭 타입과 무관 => 따라서 List<String>이 하위
(Object) List<Object> => 모든 타입 허용 => but 하위는 X
//따라서 로 타입이라면 타입 안전성을 잃게 됨
클래스 리터럴

literal이라는 단어의 의미가 '문자 그대로'라는 뜻인데, 이는 변수 or 상수에 저장되는 값 그 자체이다. 또한 원시형(Primitive-int, char), 참조형과 같은 자바의 데이터 타입 중 하나이다.
용도는 class 클래스를 표기하기 위해 사용됨!(정확히는 Class 클래스의 객체를 표기하기 위해)
** class 클래스는 java.lang 패키지에, 프로그램의 클래스와 인터페이스를 관리하는데에 사용된다.

instanceOf 연산자

원래 인스턴스 형태가 맞는지 여부를 체크해준다 = object instanceOf type
여기서 object가 type or 상속받는 class라면 true를, 아니면 false를 return해준다.

class Product {}
class Snack extends Product{}

public class instanceOf {
	public static void main(String[] args) {
    	Product p = new Product();
        Snack sn = new Snack();
        
        System.out.println(sn instanceOf Product) // true
        System.out.println(p instanceOf Snack) // false
    }
}

2. 비검사 경고를 제거해라

타입이 안전하다는 생각이 들 때면 @Surpresswarnings("unchecked") 애노테이션을 통해 ClassCastException(하위 유형이 아닌 유형 참조시 발생)의 등장을 막아라!
단, 이 애노테이션의 사용 범위를 줄이고(클래스->하나의 메서드) 사용 이유를 주석으로 적어주면 좋다.

3. 배열보다는 리스트를 사용해라(제네릭 사용이 되는)

  • 배열 -> 공변(함께 변한다) O
    = 함께 변한다
    = 상위 타입이 변하면 하위 타입도 함께 변한다
    (Super과 Sup 클래스가 서로 상속 관계라면, 이를 활용해 만든 배열 Super[]과 Sup[]도 상속 관계 라는 말!)
    //공변 -> 다형성 찾아보다가 알게 된 사실
    //조상 타입의 배열에 하위 객체를 담을 수 있다!
    public class Product {
    	int price;
    	public Product(int price) {
        	this.price = price;
        }
        Product() {}
    }
    public class Icecream extends Product {
    	Icecream() {super(1000);}
        
        public String toString() {
        	return "Icecream";
        }
    }
    public class Snack extends Product {
    	Snack() {super(2000);}
        
        public String toString() {
        	return "Snack";
        }
    }
    public class Chicken extends Product {
    	Chicken() {super(15000);}
        
        public String toString() {
        	return "Chicken";
        }
    }
    class Main {
      public static void main(String[] args) {
      	 Product[] products = {new Icecream(), new Chicken(), new Snack()};
      }
   }
    

= 컴파일 시 문제가 안되나, 런타임 시 ArrayStoreException(객체 배열에 잘못된 유형을 넣을 때 두둥등장)을 발생시킨다.
= 실체화 된다 (=런타임시에도 원소의 타입 체크)

//컴파일 시 오류가 발생하는 예시
Object array[] = new String[10];
-> 배열이 공변이라서 가능한 것!
-> String을 Object의 하위 타입으로 인식하여 컴파일 됨
array[0] = 3;

**무조건 컴파일 시 오류를 잡는 것이 제어에 용이하므로
String[] arr = new String[10];
//이런식으로 타입을 특정지어주는 것이 좋음
  • 리스트 -> 제네릭 O -> 공변 X
    = 불공변하기 때문에 당연히 위의 예시는 컴파일 자체가 안됨!
    = 서로 다른 제네릭 타입 간에는 상하위 관계가 X
    = 타입 안전성이 보장됨

  • 그렇담 왜 배열은 공변일까?
    = 다형성을 위해!
    (프로그램의 다양한 요소들이 다양한 자료형에 속하는 것이 허용되는 성질)

4. 이왕이면 제네릭 메서드, 제네릭 타입을 사용할 것!

제네릭 타입을 활용해 형변환 없이도 설계할 수 있도록 한다.

  • 제네릭 클래스
    (1) 타입 매개변수 선언
    (2) 일반 타입 -> 타입 매개변수로
    (3) static 사용 X (static 선언 시 메모리에 저장되는데 아직 타입 구체화가 되지 않았으므로)

    public class Stack<E> {
    	private E[] element;
        public Stack {
        	element = (E[]) new Object[10];
        }
    }
  • 제네릭 메서드
    (1) 컴파일러에게 내가 제네릭 메서드라는 것을 알려야 하며, 리턴 타입 을 정의하기 전에 반드시 타입을 확실히 명시해줘야 함!
    (2) 일반 클래스 에서도 제네릭 메서드를 사용할 수 있음
    (3) static 사용 O (호출 시 타입을 지정하므로)

     public static<T,V> boolean compare(People<T,V> p1, People<T,V> p2) {
          boolean nameCompare = p1.getName().equals(p2.getName());
          boolean ageCompare = p1.getAge().equals(p2.getAge());
          return nameCompare && ageCompare;
      }

    이제 두개를 main함수에서 사용할 때

    public class ExGeneric {
         public static void main(String []args){
              People<String,Integer> p1 = new People("SK",24);
              People<String,Integer> p2 = new People("YW",25);
    
              boolean result = p1.compare(p1,p2);
              System.out.println(result);
          }
    }

    이렇게 타입 파라미터를 지정한 뒤 메서드를 호출해준다!

    5 플러스 알파 제네릭 와일드 카드

    와일드 카드의 형태만 알고 가자!

    List<?> // 선언 시 모든 클래스나 인터페이스 삽입 가능
    List<? extends 상위타입> //특정 객체의 상위 클래스만
    List<? super 하위타임> //특정 객체의 하위 클래스만

참고 (하찮은 제게 지식의 기회를..)

https://hwan33.tistory.com/24
https://recordsoflife.tistory.com/695
https://tecoble.techcourse.co.kr/post/2020-10-27-polymorphism/
(다형성과 오버라이딩, 오버로딩 + a 로 설명하셨는데 나도 공부해야쥐)
https://madplay.github.io/post/effectivejava-chapter5-generics
https://qdgbjsdnb.tistory.com/28
https://coding-factory.tistory.com/573
https://93jpark.tistory.com/118

profile
노션에서 자라는 중 (●'◡'●)

0개의 댓글