Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 타임리프 - 기본기능
- 자바의 정석 기초편 ch9
- 자바의 정석 기초편 ch11
- 자바의 정석 기초편 ch12
- 자바의 정석 기초편 ch8
- @Aspect
- 자바의 정석 기초편 ch4
- 스프링 mvc2 - 검증
- 자바의 정석 기초편 ch6
- jpa 활용2 - api 개발 고급
- 스프링 입문(무료)
- 자바의 정석 기초편 ch5
- 스프링 mvc2 - 타임리프
- 자바의 정석 기초편 ch2
- 스프링 db2 - 데이터 접근 기술
- 스프링 mvc1 - 서블릿
- 스프링 mvc1 - 스프링 mvc
- 2024 정보처리기사 수제비 실기
- 게시글 목록 api
- 2024 정보처리기사 시나공 필기
- 스프링 고급 - 스프링 aop
- 자바의 정석 기초편 ch13
- 스프링 mvc2 - 로그인 처리
- 스프링 db1 - 스프링과 문제 해결
- 자바의 정석 기초편 ch14
- 자바의 정석 기초편 ch7
- 코드로 시작하는 자바 첫걸음
- 자바의 정석 기초편 ch3
- 자바의 정석 기초편 ch1
- jpa - 객체지향 쿼리 언어
Archives
- Today
- Total
나구리의 개발공부기록
자바의 정석 기초편 ch12 - 1 ~ 6[제네릭스란?, 타입변수, 제네릭스 용어, 제네릭 타입과 다형성] 본문
유튜브 공부/JAVA의 정석 기초편(유튜브)
자바의 정석 기초편 ch12 - 1 ~ 6[제네릭스란?, 타입변수, 제네릭스 용어, 제네릭 타입과 다형성]
소소한나구리 2023. 12. 13. 10:301) 제네릭스(Generics)
- 클래스이름<타입> 처럼 작성
- 컴파일시 타입을 체크해주는 기능 - JDK1.5부터 적용됨
- 실행시 에러(프로그램 비정상 종료)보다 컴파일 에러가 더 안전하기 때문에 실행시 발생하는 타입에러를 컴파일 에러로 바꾸기 위해 나옴
- 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌 (ClassCastException - 형변환에러 발생을 막음)
(1) 형변환 에러 발생 예제
- 제네릭스 적용 전에는 List와 같은 컬렉션에 여러 타입을 저장할 수 있는데 해당 컬렉션의 값을 조회시 특정 타입으로 고정하여 값을 출력 하려고하면 컴파일 시에는 에러가 발생하지 않지만 실행시에 ClassCastException(형변환에러) 에러가 발생됨
- 제네릭스를 적용하여 컬렉션에 타입을 지정하면 지정한 타입으로만 값을 저장할 수 있게 되어 다른 타입을 저장하려고하면 컴파일 시에 에러가 발생하여 실행에러를 미연에 방지할 수 있음
// 제네릭스 활용 전
import java.util.ArrayList;
public class GenericTest {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(10);
list.add(20); // int 입력
list.add("30"); // 문자열 입력
// index2번의 값을 Integer타입으로 형변환 후 인티저타입의 참조변수에 저장
Integer i = (Integer)list.get(2);
// list.get이 반환하는 타입이 Object -> Integer로 형변환
// 컴파일 OK - 컴파일러의 한계(실제로 들어있는건 문자열)
// 실행 에러 발생 (ClassCastException - 형변환에러)
System.out.println(list);
}
}
// 제네릭스 활용
import java.util.ArrayList;
public class GenericTest {
public static void main(String[] args) {
// 객체에 여러 종류를 넣고자 하면<Object>로 제네릭스 작성 -> 단 아래에서 형변환을 해야함
// JDK1.5 이후에는 클래스 안에 Object타입이 있는 클래스들은 제네릭스로 클래스를 만들어야 함
ArrayList<Integer> list = new ArrayList<Integer>(); // Integer타입만 넣을 수 있도록 변경
list.add(10);
list.add(20); // int 입력
list.add("30"); // 문자열 입력 -> 컴파일 에러발생(타입 체크가 강화됨)
// 형변환 생략 가능(제네릭스에서 이미 알고 있음)
// Integer i = (Integer)list.get(2);
Integer i = list.get(2);
System.out.println(list);
}
}
(2) NullPointerException 에러 방지
- 참조변수를 선언할 때 null이아닌 빈문자열이나 길이가 0인 배열로 초기화하여 선언하면 실행에러인 NullPointerException을 방지할 수 있음
- 이러한 아이디어로 실행 시 발생하는 형변환 에러로 변경하고자 한 것이 제네릭스임
// NullPointerException 방지하기 위한 초기화 방법
String str = null; // null로 초기화
str.length(); // 메서드 호출 -> NullPointException 발생
String str = ""; // 빈문자열로 초기화로 방지
Object[] obArr = null; //null로 배열 초기화
obArr.length; // 배열의 길이 출력 -> NullPointException 발생
Object[] objArr = {}; // 길이가 0인 배열로 초기화로 방지
2) 타입변수
- JDK 1.5 이후부터 자바에 내장된 클래스들이 Object타입 대신 타입 변수<E>를 선언하여 제네릭클래스로 변경이됨
- 아무 문자를 써도 상관은 없지만 Type의 T나 Element의 E가 많이 선언되어 있음
(1) 타입변수에 실제 객체를 대입
- 객체 생성 시 타입변수 대신 사용할 타입을 지정하여 대입하고 그 참조값을 저장할 참조변수의 타입에도 동일한 타입을 지정해야 함
- 지정한 타입을 제네릭스로 적용하면 타입이 명시적으로 선언 되어있어 동일 타입으로 값을 다룰 경우 형변환이 불필요 함
// 기존의 ArrayList가 정의된 모습
public class ArrayList extends AbstractList {
private transient Object[] elementData;
public boolean add(Object o) { /* */ }
public Object get(int index) { /* */ }
...
}
// 타입 변수가 사용 된 ArrayList (JDK1.5 이후부터 바뀜)
public class ArrayList<E> extends AbstractList<E> {
private transient E[] elementData;
public boolean add(E o) { /* */ }
public E get(int index) { /* */ }
...
}
// TV 객체 생성시 타입 변수 대신 실제 타입을 지정 대입, 형변환 생략 가능
ArrayList<Tv> tvList = new ArrayList<Tv>(); // 객체 생성
tvList.add(new Tv());
Tv t = tvList.get(0); // 형변환 불필요
(2) 예제
import java.util.ArrayList;
class Tv {}
class Audio {}
public class Ex12_GenericTest {
public static void main(String[] args) {
// Tv타입의 객체만 저장 가능하도록 제네릭스로 타입을 지정
ArrayList<Tv> list = new ArrayList<Tv>();
list.add(new Tv());
// list.add(new Audio()); // 에러 발생, 타입 오류
Tv t = list.get(0); // list가 Tv 타입이기 때문에 Tv타입 참조변수에 바로 저장이 가능함
}
}
3) 제네릭스용어
(1) Box<T>
- 제네릭 클래스, 'T의 Box' or 'T Box'라고 읽음
(2) T
- 제네릭 안에 있는 T는 타입 변수, 타입 매개변수라고 함
(3) Box
- 원시타입(raw type) 클래스
(4) class Box<T> { }
- <T>에 String 타입을 대입 후 객체를 생성하면 <String> 처럼 표기되고 대입된 타입(매개변수화된 타입, parameterized type)이라고 함
- 아래처럼 객체를 선언할 때 지정하며, 객체를 생성할 때마다 타입은 변경이 가능함
Box<String> b = new Box<String>();
4) 제네릭 타입과 다형성
- 기본적으로는 참조 변수와 생성자의 대입된 타입은 무조건 일치해야 함
- 제네릭 클래스간의 다형성과 매개변수의 다형성은 성립함
- 즉, 제네릭의 타입 자체는 다형성이 적용되지 않지만, 일반적으로 우리가 적용하는 다형성의 관계는 모두 적용된다고 보면 됨
(1) 예제
- List<Tv> tvList = new ArrayList<Tv>(); 처럼 제네릭스의 타입이 일치하면 제네릭클래스의 다형성은 적용이 됨
- ArrayList<Product> productList = ... 처럼 ArrayList객체를 참조한 참조변수를 조상 타입으로 지정하면 해당 참조변수에는 다형성이 적용되어 제네릭스타입의 자손의 객체들을 저장할 수 있음
import java.util.*;
class Product {}
class Tv extends Product {}
class Audio extends Product {}
class Ex12_1 {
public static void main(String[] args) {
ArrayList<Product> productList = new ArrayList<Product>();
ArrayList<Tv> tvList = new ArrayList<Tv>();
// ArrayList<Product> tvList = new ArrayList<Tv>(); // 에러. 제네릭 타입이 다름
// List<Tv> tvList = new ArrayList<Tv>(); // OK. 다형성(제네릭 클래스간의 다형성)
//매개변수의 다형성(자손의 객체 사용 가능)
productList.add(new Tv()); // public boolean add(Product e) { }
productList.add(new Audio());
Product p = productList.get(0); // 형변환 생략 가능
Tv t = (Tv)productList.get(1); // 형변환 생략불가(다른타입)
tvList.add(new Tv()); // public boolean add(Tv e) { }
tvList.add(new Tv());
printAll(productList);
// printAll(tvList); // 컴파일 에러가 발생한다.
}
public static void printAll(ArrayList<Product> list) {
for (Product p : list) System.out.println(p);
}
}
** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의
'유튜브 공부 > JAVA의 정석 기초편(유튜브)' 카테고리의 다른 글
자바의 정석 기초편 ch12 - 15 ~ 22 [제네릭형변환, 열거형, 열거형의 조상, 열거형에 멤버 추가하기] (0) | 2023.12.14 |
---|---|
자바의 정석 기초편 ch12 - 7 ~ 14[제네릭스 적용 예제(Iterator, HashMap), 제한된 제네릭클래스, 제네릭스의 제약, 와일드카드, 제네릭메서드] (0) | 2023.12.13 |
자바의 정석 기초편 ch11 - 52 ~ 56[Collections클래스, 컬레션클래스 요약] (0) | 2023.12.12 |
자바의 정석 기초편 ch11 - 46 ~ 51[HashMap과 Hashtable] (1) | 2023.12.12 |
자바의 정석 기초편 ch11 - 34 ~ 45 [HashSet, TreeSet] (0) | 2023.12.12 |