[1] 제네릭 적용
1) 선언
// string 타입
public class StringBox {
private String value;
public void set(String object) {
this.value = object;
}
public String get() {
return value;
} }
//int 타입
public class IntegerBox {
private Integer value;
public void set(Integer value) {
this.value = value;
}
public Integer get() {
return value;
} }
2) 꺼내기
public class BoxMain1 {
public static void main(String[] args) {
IntegerBox integerBox = new IntegerBox();
integerBox.set(10); //오토 박싱
Integer integer = integerBox.get();
System.out.println("integer = " + integer);
StringBox stringBox = new StringBox();
stringBox.set("hello");
String str = stringBox.get();
System.out.println("str = " + str);
}
}
1) Object로 선언
public class ObjectBox {
private Object value;
public void set(Object object) {
this.value = object;}
public Object get() {
return value;
} }
2) 출력
public class BoxMain2 {
public static void main(String[] args) {
ObjectBox integerBox = new ObjectBox();
integerBox.set(10);
Integer integer = (Integer) integerBox.get(); //Object -> Integer 캐스팅
System.out.println("integer = " + integer);
ObjectBox stringBox = new ObjectBox();
stringBox.set("hello");
String str = (String) stringBox.get(); //Object -> String 캐스팅
System.out.println("str = " + str);
//잘못된 타입의 인수 전달시
integerBox.set("문자100");
Integer result = (Integer) integerBox.get();
// String -> Integer 캐스팅 예외
System.out.println("result = " + str);
}
}
Object를 이용해 다형성을 활용하게 됐지만 입력할 때 실수로 원하지 않는 타입이 들어갈 수 있는 타입 안전성 문제가 생긴다.
따라서 제네릭을 사용한다.
[2] 제네릭 사용
public class Generic <T> {
private T value;
public void set(T value){
this.value = value;
}
public T get(){
return value;
}
}
public class GenericMain {
public static void main(String[] args) {
Generic<Integer> box = new Generic<>(); //이때 T의 타입이 결정됨
box.set(10);
box.get();
}
}
[3] Generic 용어
타입 매개변수: GenericBox<T> 에서 T
타입 인자: GenericBox<Integer> 에서 Integer, GenericBox<String> 에서 String
E - Element, K - Key, N - Number, T - Type, V - Value
class Data<K, V> {} 처럼 사용 가능함
[4] Generic 사용 예시
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+" size: "+size;
}
}
public class Dog extends Animal{
public Dog(String name, int size) {
super(name, size);
}
@Override
public void sound(){
System.out.println("멍멍");
}
}
public class Cat extends Animal{
public Cat(String name, int size) {
super(name, size);
}
@Override
public void sound(){
System.out.println("냐옹");
}
}
public class Box <T>{
private T value;
public void set(T value){
this.value = value;
}
public T get(){
return value;
}
}
public class AnimalMain {
public static void main(String[] args) {
Animal animal = new Animal("동물", 23);
Dog dog = new Dog("멍멍이", 100);
Cat cat = new Cat("냐옹이", 50);
Box <Dog> dogBox = new Box<>();
dogBox.set(dog);
Dog findDog = dogBox.get();
System.out.println("개 찾음: "+ findDog);
Box <Cat> catBox = new Box<>();
catBox.set(cat);
Cat findCat = catBox.get();
System.out.println("고양이 찾음: "+ findCat);
}
}
Box를 이용해서 Dog, Cat 타입을 보관할 수 있음
[5] Generic2
1) 타입 매개변수 제한
: T extends Animal로 설정해서 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;
}
}
[6] 예시
public class GenericMethod {
public static Object objectMethod(Object obj){
System.out.println(obj);
return obj;
}
public static <T> T genericMethod(T t){
System.out.println(t);
return t;
}
public static <T extends Number> T numberMethod(T t){
System.out.println(t);
return t;
}
}
public class MethodMain {
public static void main(String[] args) {
Integer i = 10;
Object object = GenericMethod.objectMethod(i);
Integer result = GenericMethod.<Integer>genericMethod(i);
Integer integerValue = GenericMethod.<Integer>numberMethod(10);
Double doubleValue = GenericMethod.<Double>numberMethod(20.0);
}
}
1) 제네릭 메서드
정의: <T> T genericMethod(T t)
타입 전달: genericMethod.<Integer>genericMethod(10)
2) static 메서드에는 T 못 씀 -> generic 메서드로 만들기
class Box<T> {
static T staticMethod(T t) {} // 에러!
}
static <T> T staticMethod(T t) {} // 가능!
[7] 와일드 카드
public class WildcardEx {
static<T> void printGenericV1(Box<T> box){
System.out.println(box.get());
}
static void printWildcardV1(Box<?> box){
System.out.println(box.get());
}
static <T extends Animal> void printGenericV2(Box<T> box){
T t = box.get();
System.out.println(t.getName());
}
static void printWildcardV2(Box<? extends Animal> box) { //Animal의 자식들만 받음
Animal animal = box.get(); //Animal로 받아서 사용함
System.out.println("이름 = " + animal.getName());
}
static <T extends Animal> T printAndReturnGeneric(Box<T> box) {
T t = box.get(); // T는 Animal의 자식
System.out.println("이름 = " + t.getName());
return t; //T 타입을 반환
// 1. Generic이라는 타입을 기억함
}
static Animal printAndReturnWildcard(Box<? extends Animal> box) {
Animal animal = box.get(); // Animal 타입으로 받음
System.out.println("이름 = " + animal.getName());
return animal; // Animal 타입 반환
// 2. Wildcard는 타입 정보 손실됨
}
}
제네릭 메서드 <T>: 메서드에 직접 타입 매개변수를 정의함, 타입을 반환 / 변경 시에 필요
와일드 카드 <?>: 타입 정의 없이 어떤 타입이든 받음, 단순히 읽을 때만 적합
[8] 이레이저
1) 자바 컴파일러가 casting을 대신 해줌
예전)
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); // 직접 캐스팅함
제네릭)
List<String> list = new ArrayList<>();
list.add("hello");
String s = list.get(0); // 컴파일러가 자동으로 캐스팅해줌
2) 타입 이레이저
: 자바의 제네릭은 컴파일 타임(코드 짤 때)에만 사용되고, 런타임(실행할 때)에는 제네릭 정보가 지워지는 것List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
컴파일 타입에는 다른 타입, 실행 시점에는 둘 다 List로 처리됨
'Spring' 카테고리의 다른 글
[6] 자바 중급 문법 - List (0) | 2025.03.28 |
---|---|
[5] 자바 중급 문법 - ArrayList (0) | 2025.03.28 |
[3] 자바 중급 문법 3 -- 날짜와 시간 (0) | 2025.03.21 |
[2] 자바 중급 문법 2 (0) | 2025.03.21 |
[1] 자바 중급 문법 1 (0) | 2025.03.19 |