일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 11659
- 코드스테이츠 백엔드
- 버블정렬
- 재귀와반복문
- 자바
- 스택
- 코딩테스트
- GCP
- 클라우드에서 도커 실행하기
- 구간합구하기
- vm인스턴스생성
- 재귀함수
- 인텔리제이
- 프로그래머스
- 투포인터알고리즘
- 코드스테이츠
- MySQL
- java
- 성능테스트툴
- 백준
- 알고리즘
- List.of
- 백준 11659
- String.valueOf()
- Spring MVC 동작원리
- OOP
- Spring MVC 구성요소
- 싱글톤패턴
- Spring Web MVC
- Array.asList
- Today
- Total
순간을 기록으로
[JAVA] 제네릭1 본문
제네릭 이전의 코드의 단점
1.클래스가 자료형에 의존적이게 된다.
2.인스턴스를 꺼낼 때 형변환을 해야한다.
Apple ap = (Aplle)aBox.get();
Orange og = (Orange)oBox.get();
3.실수가 컴파일 과정에서 발견되지 않는다.
aBox.set("Apple"); // 문자열 "Apple" 담았는데 실수다
oBox.set("Orange"); // 문자열 "Orange" 담았는데 실수다
제네릭 기반 클래스 정의
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
제네릭의 등장으로 자료형에 의존적이지 않은 클래스를 정의할 수 있고 앞에서 본 문제점을 해결할 수 있다.
제네릭의 <T>는 인스턴스 생성 시 T의 자료형을 결정한다.
용어정리
Box<Apple> aBox = new Box<Apple>();
- <T>: 타입 매개변수(Type Parameter)
- Apple: 타입 인자(Type Argument)
- Box<Apple>: 매개변수화 타입(Parameterized Type), 제네릭 타입(Generic Type)
다중 매개변수 제네릭 클래스
class DBox<L, R> { // 다중 매개변수 기반 제네릭 클래스
private L left;
private R right;
public void set(L o, R r) {
left = o;
right = r;
}
}
타입 인자의 규칙1: 기본자료형은 불가능
Box<Apple>처럼 '매개변수화 타입'을 만들 때 '타입인자'는 기본 자료형이 불가능하다. 즉 Box<int>는 사용할 수 없다.
그러므로 래퍼클래스를 사용하게 되고 상황에 따라 자동으로 박싱과 언박싱이 진행된다.
타입 인자의 규칙2: 생략가능
Box<Apple> aBox = new Box<Apple>();
Box<Apple> aBox = new Box<>();
위 두 문장은 같다. 즉 컴파일러는 참조변수의 선언을 보고 오른쪽의 타입인자를 생략해도 추론할 수 있다.
타입 인자의 규칙3: 매개변수화 타입을 타입인자로 사용할 수 있다.
Box<Box<Apple>> aBox = new Box<>();
다음과 같이 '매개변수화 타입'을 '타입 인자'로 사용할 수 있다.
타입 인자 제한하기1: extends 클래스
때로는 담고 싶은 것을 제한하고 싶을 수도 있다. 그럴때는 'extends'를 사용한다.
class Box<T enxtends Number>{...}
다음과 같이 사용하면 타입 인자로 사용할 수 있는 것은 Number와 Number을 상속하는 하위 클래스만 가능하다.\
타입 인자를 제한함으로써 얻는 효과: 특정 메소드 호출 가능
class Box<T extends Number> {
private T ob;
...
public int toIntValue() {
return ob.intValue(); // 가능
}
}
다음과 같이 타입인자를 extends Number로 제한을 하면 T는 적어도 Number 이거나 Number을 상속하는 클래스이므로 ob 객체는 intValue() 메소드를 호출할 수 있다.
타입인자 제한하기2: extends 인터페이스
class Box<T extends Eatable> {...}
Eatable을 인터페이스라고 한다면 다음과 같이 인터페이스로 타입 인자를 제한할 수있다.
또한 타입인자는 클래스와 인터페이스로 동시에 제한 할 수 있다.
class Box<T extends Number & Eatable> {...}
제네릭 메소드
클래스 전체가 아닌 일부 메소드에 대해서만 제네릭의 정의할 수 있다. static과 관련이 없다.
public static <T> Box<T> makeBox(T o) {...} // 제네릭 메소드
맨 앞의 <T>는 제네릭 메소드를 알려주는 표시이다.
제네릭 클래스와 제네릭 메소드의 자료형 결정 시기
제네릭 클래스의 경우 인스턴스 생성시 자료형이 결정된다.
반면, 제네릭 메소드의 경우 메소드 호출시에 자료형이 결정된다.
Box<String> sBox = BoxFactory.<String>makeBox("Sweet");
Box<String> sBox = BoxFactory.makeBox("Sweet");
컴파일러는 메소드 이름앞 <String>을 보고 제네릭 메소드의 자료형을 결정한다. 하지만 현재 컴파일러는 발전되어 참조변수의 형을 보고 제네릭 메소드형을 추론할 수 있다. 따라서 아래와 같이 생략할 수 있다.
제네릭 메소드의 타입인자 제한하기: extends
public static <T extends Number> Box<T> makeBox(T o) { // 제한된 타입 인자
Box<T> bo = new Box<T>();
box.set(o);
System.out.println("Boxed data: " + o.intValue()); // 타입인자 제한 효과
return box;
}
}
제네릭 메소드도 제네릭 클래스와 같이 타입인자를 제한할 수 있다. 그리고 그 효과도 같다.
'Development > JAVA' 카테고리의 다른 글
[Java] 배열을 복사하는 방법 (0) | 2022.05.08 |
---|---|
[Java] 오버라이딩이란 무엇이고 왜 사용할까? (0) | 2022.04.21 |
[Java] JDK, JRE, JVM는 차이점은 무엇일까? (0) | 2022.04.18 |
[JAVA] 제네릭2 (0) | 2021.11.29 |
[열혈자바] 18-1 자바 예외처리의 기본 (0) | 2021.10.18 |