열심히 끝까지
[10분 테코톡] 두강의 Generics 본문
두강의 Generics
https://www.youtube.com/watch?v=n28M8iryFPw
[Generics - 타입문지기]
- Generic?
: 다양한 타입의 객체들을 다루는 메서드나 클래스에
컴파일 시의 타입 체크를 해주는 기능
ex ) List<String> stringList = new ArrayList<>();
stringList.add(1); < 에러
stringList.add(3.14); < 에러
stringList.add("우테코"); < ok
>> 이처럼 의도치 않는(1, 3.14) 타입이 들어오는 것을 막는
작업 == "타입 체크"
제네릭 사용 효과
: 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어듦
제네릭 형태
public class Box<T> { }
>> 클래스명 뒤에 꺽세에 타입 매개변수가 추가 되는 것
>> T : 타입 매개변수
>> Box<T> : 제네릭 클래스
예시 ----
public class Box<T> {
List<T> items = new ArrayList<>();
public void add(T item) {
item.add(item);
}
}
>> T가 전달이 되면 아래의 T들에게도 공유가 됨
: String으로 변경되면 String으로 공유
int로 변경되면 int로 공유
: 형태가 공유되면 그 형태의 값만 설정 가능
> String이면 String값만 추가 가능
> int면 int값만 추가 가능
- 제네릭을 사용하면 좋은 점
1. 강력한 타입 체크를 해줌
>> int형(Integer)만 들어가게 설정하게 되면
정수는 잘 들어가다가 문자형이 들어오면 밑줄이 그어지며
타입 체크를 함 > 문자형을 정수로 바꾸면 밑줄 사라짐
2. 형변환을 하지 않아도 됨
>> 제네릭이 없을 때, 인덱스에 해당하는 값을 보여줌
>> 모든 타입이 들어오기 때문에 어떤 값을 넣더라도 잘 들어감
> 하지만 나중에 꺼내서 쓸 때는 형변환을 명시적으로 하여야 하는데
제네릭이 존재하면 형변환을 하지 않아도 된다는 장점 존재
- 제네릭 사용법
1. 참조변수와 생성자에 대입된 타입이 일치해야 함
ex )
Box<Apple> appleBox = new Box<Apple>();
Box<Grape> appleBox = new Box<Grape>();
Box<Fruit> fruitBox = new Box<Apple>();
>> Apple이 Fruit를 상속해도 불가능!
2. 제네릭 클래스가 상속 관계인 것은 괜찮음
ex )
Box<Fruit> fruitBox = new FruitBox<Fruit>();
List<Fruit> fruitBox = new ArrayList<Fruit>();
Box<Fruit> fruitBox = new FruitBox<Apple>();
>> 단, 여전히 대입되는 타입은 같아야 함
- 제네릭의 문제점
Box에 과일 종류만 넣고 싶은데, 아무거나 다 들어감
ex )
과일만을 넣고 싶어서 FruitBox 생성
Box<Toy> fruitBox = new FruitBox<Toy>();
> 근데 Toy가 제네릭 안에 들어가면 Toy도 들어가는 문제점 발생
>> 그럴 때 쓸 수 있는 것이 제네릭
public class Box<T extends Fruit>{
List<T> items = new ArrayList<>();
void add(T item){
item.add(item);
}
}
>> 전달된 타입 매개변수 뒤에 Fruit이라는 제한된 범위를 지정해주면
Fruit을 상속하는 타입만 들어올 수 있음
>> 제한해주면 Toy객체는 더이상 들어가지 않음
: Box 타입 매개변수로 Fruit을 상속하지 않는 타입은 올 수 없음
- 다양한 타입 매개변수
T - Type(일반적인 타입)
E - Element(자바 컬렉션 프레임워크에서 주로 사용 - 요소)
K - Key (페어나 맵 같은 곳에서 사용)
V - Value(페어나 맵 같은 곳에서 사용)
N - Number
S, U, V .. - 2nd, 3rd, 4th type, .. (타입 뒤를 잇는 두번째 세번째 타입을 표시)
> 타입 매개변수를 이렇게 표기하는 것이 관례
>> 하지만 원한다면 자신이 원하는 대로 표기하여 사용해도 문제가 되지 않음
ex ) public class Box<woowa123>{ }
// Map
public Interface Map<K,V>{
Set<Map.Entry<K,V>> entrySet();
}
// List
public Interface List<K,V>{
Interface<E> iterator();
}
// Type, 2nd, Return type
public Interface BiFunction<T,U,R>{
R apply(T t, U u);
}
//
public Interface BiConsumer<T,U>{
void accept(T t, U u);
}
>> 제네릭 메서드
[ public <T> T foo(List<T> list){ } ]
<T> : 타입 매개변수
T : 리턴 타입
foo : 메소드 명
List<T> list : 매개변수
>> 일반적인 메서드와의 차이 리턴타입 앞에
타입 매개변수 작성하는 곳이 존재한다는 것
[ public <T> T foo(List<T> list){ } ]
> 위의 메서드에 전달되는 타입 매개변수의 범위를 제한하고 싶다면?
>> public <T extends Fruit> T foo(List<T> list) { } 로 하면 됨
>> public <T> foo(List<T extends Fruit> list) { }가 아니다!!!
>> 뒤가 아닌 앞에 넣을 것
ex )
public static <T> T getFirstItem(List<T> list){
return list.get(0);
}
>> 안에 있는 여러가지 T중에 앞에 있는 T가 호출
T 같은 경우 제네릭 메서드에서 T도 리턴이 가능하다는 것을 보여주기 위해서 사영
>> 다 사용 가능
- 제네릭 사용하면서 헷갈리는 것
1. 제네릭 메서드의 타입과 제네릭 클래스의 타입은 서로 다른 것!!!
public class Box<T> {
public <T> void printParamClass(T t){
System.out.println(t.getClass());
}
}
>> 이때 Box의 T와 아래 public T는 같아보이지만
다른 타입일 수 있음
>> PrintParamClass의 T는 전달된 타입의 클래스를 출력하는 메서드
ex )
Box<Fruit> box = new Box();
box.printParamClass("String");
box.printParamClass(1);
box.printParamClass(3.14);
>> box에 전달이 되면 만약에
제네릭 클래스에서 사용되는 T와
메서드에서 사용되는 T가
같다면?
>> String이나 Double이 전달될 수 없음
>> 근데 String도 Double도 전달 가능
2. 제네릭 클래스가 아닌 일반 클래스에서도 사용 가능
- 와일드 카드
: 기호 '?'로 표현
: 어떠한 타입도 될 수 있다는 것을 의미
사용법
: 아무 타입의 list를 출력하는 메서드
<MyClass>
public static void printList(List<Object> list) {
for(Object elem : list){
System.out.println(elem + " ");
}
}
>> static 메서드는 아무 타입이나 출력하는 메서드
> list Object를 넣고 출력
main문에...
List<Fruit> fruits = new ArrayList<>();
MyClass.printList(fruits);
저 List 타입에 <Fruit>를 넣어서 전달하려고 하면 컴파일 에러가 남
>> list Object가 아니기 때문에 못받음
>> 정확히 Object 형의 요소를 갖는 List만 들어올 수 있기 때문!
>> 이 것을 해결하기 위해서 와일드 카드를 사용
: 모든 타입이 들어올 수 있도록 수정
public static void printList(List<? extends Object> list) {
for(Object elem : list){
System.out.println(elem + " ");
}
}
> 아무 타입이나 다 받을 수 있게 됨
>> 결론
제네릭은 형변환의 번거로움을 줄임
의도하지 않은 타입이 들어오는 것을 막기 위한 것(강력한 타입체크)
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(과제)' 카테고리의 다른 글
[에러사항] - Oracle 진행 시 존재하는 오류 해결 사항 (0) | 2022.07.15 |
---|---|
[10분 테코톡] 웨지의 OOP (0) | 2022.07.11 |
[10분 테코톡] 라이언의 애자일 (0) | 2022.07.09 |
[10분 테코톡] 해리&션의 MVC 패턴 (0) | 2022.07.08 |
[10분 테코톡] 제리의 MVC 패턴 (0) | 2022.07.07 |