일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- BufferedReader
- 백엔드
- 프론트엔드
- StringBuilder
- select문
- String클래스
- 예외처리
- 정보처리기사필기요약
- 프로그래머스 sql 고득점 kit
- Java
- 자바스크립트
- SQL
- select
- 프로그래머스 SQL
- 메서드
- 리눅스
- 클래스
- DML
- 웹개발
- 프로그래밍
- where
- 알고리즘
- github
- Linux
- html
- scanner
- mybatis
- 자바
- 형변환
- 정보처리기사
- Git
- 백준
- sql문
- JavaScript
- 개발자
- 입출력
- 스프링
- 데이터 조회
- MySQL
- order by
- Today
- Total
ToBe끝판왕
[ JAVA ] 제네릭 ( Generic ) 본문
제네릭 ( Generic )
1) Generic 이란 ?
• Generic에 대해 알아보자
- Class , Interface, Method 에 타입 매개변수를 추가해 코드의 유연성과 안정성을 높일수 있는 기능
- 다양한 타입을 처리가 가능토록 하여, 컴파일 시 타입 안정성을 보장한다.
- 특히, 컬렉션 프레임워크에서 자주 사용된다.
- 컴파일 시, 타입을 체크하여 타입 오류를 방지한다.
• Generic 타입 매개변수 명명 관례
- T : Type을 의미하며, 일반적인 타입을 나타낼 때 사용
- E : Element의 약어로, 주로 컬렉션의 요소를 나타낼 때 사용
- K, V : Key 와 Value 의 약어로, 주로 Map 과 같은 키 - 값 구조에서 사용
- N : Number의 약어로, 숫자를 나타낼 때 사용
• Generic 사용 제한
- 기본 타입 ( int, double 등 ) 대신 래퍼 클래스 ( Integer, Double 등 ) 을 사용해야 한다.
- 정적 ( Static ) 멤버에 사용 불가능
2) Generic 예시
• Generic 사용 예시 1
package hello.blog.generic;
public class GenericBoxMain {
public static void main(String[] args) {
GenericBox<Integer> integerBox = new GenericBox<Integer>();
// Integer 타입만 허용, 다른 타입의 경우 컴파일시 오류 발생
integerBox.set(10);
Integer integer = integerBox.get();
System.out.println("integer = " + integer);
GenericBox<String> stringBox = new GenericBox<String>();
stringBox.set("hello");
String str = stringBox.get();
System.out.println("str = " + str);
// 제네릭이기 때문에 모든 타입이 가능
GenericBox<Double> doubleBox = new GenericBox<Double>();
doubleBox.set(10.5);
Double doubleValue = doubleBox.get();
System.out.println("doubleValue = " + doubleValue);
// 타입 추론 -> 제네릭 객체 생성시 생성하는 제네릭 타입 생략 가능
GenericBox<Integer> integerBox2 = new GenericBox<>();
integerBox2.set(20);
Integer integer2 = integerBox2.get();
System.out.println("integer2 = " + integer2);
}
}
// 결과
integer = 10
str = hello
doubleValue = 10.5
integer2 = 20
• Generic 사용 예시 2
package hello.blog.generic;
public class GenericMain {
public static void main(String[] args) {
Pair<Integer, String> pair1 = new Pair<>();
pair1.setFirst(1);
pair1.setSecond("data");
System.out.println(pair1.getFirst());
System.out.println(pair1.getSecond());
System.out.println("pair1 = " + pair1);
Pair<String, String> pair2 = new Pair<>();
pair2.setFirst("key");
pair2.setSecond("value");
System.out.println(pair2.getFirst());
System.out.println(pair2.getSecond());
System.out.println("pair2 = " + pair2);
}
}
package hello.blog.generic;
public class Pair<T1, T2> {
private T1 first;
private T2 second;
public T1 getFirst() {
return first;
}
public void setFirst(T1 first) {
this.first = first;
}
public T2 getSecond() {
return second;
}
public void setSecond(T2 second) {
this.second = second;
}
@Override
public String toString() {
return "Pair{" +
"first=" + first +
", second=" + second +
'}';
}
}
// 결과
1
data
pair1 = Pair{first=1, second=data}
key
value
pair2 = Pair{first=key, second=value}
• 제네릭에 "타입 매개변수 상한" 을 두기 예시
package hello.blog.generic.animal;
public class Animal {
private String name;
private int size;
public Animal(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public int getSize() {
return size;
}
public void sound() {
System.out.println("동물 울음 소리");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", size=" + size +
'}';
}
}
package hello.blog.generic.animal;
public class Cat extends Animal{
public Cat(String name, int size) {
super(name, size);
}
@Override
public void sound() {
System.out.println("냐옹");
}
}
package hello.blog.generic.animal;
public class Dog extends Animal{
public Dog(String name, int size) {
super(name, size);
}
@Override
public void sound() {
System.out.println("멍멍");
}
}
package hello.blog.generic.animal;
public class AnimalHospital <T extends Animal>{
private T animal;
public void set(T animal) {
this.animal = animal;
}
public void checkUp() {
System.out.println("동물 이름: " + animal.getName());
System.out.println("동물 크기: " + animal.getSize());
animal.sound();
}
public T getBigger(T target) {
return animal.getSize() > target.getSize() ? animal : target;
}
}
package hello.blog.generic.animal;
public class AnimalHospitalMain {
public static void main(String[] args) {
AnimalHospital<Dog> dogHospital = new AnimalHospital<>();
AnimalHospital<Cat> catHospital = new AnimalHospital<>();
Dog dog = new Dog("멍멍이1", 100);
Cat cat = new Cat("냐옹이1", 300);
// 개 병원
dogHospital.set(dog);
dogHospital.checkUp();
// 고양이 병원
catHospital.set(cat);
catHospital.checkUp();
// 개병원에 고양이 전달 -> 컴파일 오류 발생 ( 다른 타입 입력 )
// dogHospital.set(cat);
// 개 타입 반환
dogHospital.set(dog);
Dog biggerDog = dogHospital.getBigger(new Dog("멍멍이2", 200));
System.out.println("biggerDog = " + biggerDog);
}
}
- < T extends Animal > 을 통해 상한이 Animal 이 된다.
- T 에 타입 인자로 Animal, Cat, Dog 만 들어올 수 있다. ( 전혀 관계 없는 타입인자를 컴파일시 막는다. )
- Animal이 제공하는 getName(), getSize() 메서드가 사용 가능하다.
▶ 타입 매개변수 상한을 사용해서 타입 안정성을 지키면서 상위 타입의 기능 (메서드) 까지 사용 가능하였다.
즉, 코드 재사용과 타입 안정성 모두를 가져 갈 수 있다.
3) Generic 메서드
- 특정 메서드 단위로 제네릭을 도입할 수 있다.
- <T> T genericMethod( T t ) 와 같이 사용한다.
- 메서드를 실제 호출하는 시점에 타입을 지정하고 호출한다. ( 타입 안정성 보장 )
※ 제네릭 클래스의 경우, 클래스 내 모든 메서드에 제네릭이 적용된다.
※ 정적 메서드의 경우 제네릭 클래스가 아닌 메서드 단위로 제네릭을 도입해야 한다.
※ 인스턴스 메서드의 경우 제네릭 메서드가 제네릭 클래스보다 우선순위가 높다
▶ 실무에서는 직접 제네릭을 사용하여 무언가를 설계하거나 만드는일이 드물며, 제네릭을 통해 만들어진
프레임워크나 라이브러리를 가져다 사용하는 경우가 많다.
그러므로, 이미 만들어진 코드의 제네릭을 읽고 이해하는 정도면 충분하다고 볼 수 있다.
※ 해당 내용은 인프런 김영한 강사님의 "실전 자바 중급2" 인강의 자료와 예시들을 참고하였습니다
'■ 프로그래밍 SKILLS > JAVA' 카테고리의 다른 글
[ JAVA ] 컬렉션 프레임워크 (3) - Map (3) | 2024.10.24 |
---|---|
[ JAVA ] 컬렉션 프레임워크 (2) - Set (5) | 2024.10.23 |
[ JAVA ] 컬렉션 프레임워크 (1) - List (3) | 2024.10.23 |
[ JAVA ] 예외 처리 (2) (0) | 2024.08.21 |
[ JAVA ] 예외 처리 (1) (0) | 2024.08.21 |