2-5. 제네릭 메서드 문제 풀이

shin·2024년 7월 28일

문제1 - 제네릭 메서드와 상한


  • 다음 코드와 실행 결과를 참고해서 UnitUtil 클래스를 만들어라
  • UnitUtil.maxHp() 메서드의 조건은 다음과 같다.
    • 두 유닛을 입력 받아서 체력이 높은 유닛을 반환한다. 체력이 같은 경우 둘 중 아무나 반환해도 된다.
    • 제네릭 메서드를 사용해야 한다.
    • 입력하는 유닛의 타입과 반환하는 유닛의 타입이 같아야 한다.

package generic.test.ex3;

import generic.test.ex3.unit.Marine;
import generic.test.ex3.unit.Zealot;

public class UnitUtilTest {

	public static void main(String[] args) {
    
 		Marine m1 = new Marine("마린1", 40);
 		Marine m2 = new Marine("마린2", 50);
 		Marine resultMarine = UnitUtil.maxHp(m1, m2);
 		System.out.println("resultMarine = " + resultMarine);
        
 		Zealot z1 = new Zealot("질럿1", 100);
 		Zealot z2 = new Zealot("질럿2", 150);
 		Zealot resultZealot = UnitUtil.maxHp(z1, z2);
 		System.out.println("resultZealot = " + resultZealot);
        
    }
    
 }

실행결과

resultMarine = BioUnit{name='마린2', hp=50}
resultZealot = BioUnit{name='질럿2', hp=150}

정답 - UnitUtil 클래스


package generic.test.ex3;
import generic.test.ex3.unit.BioUnit;
public class UnitUtil {

	public static <T extends BioUnit> T maxHp(T t1, T t2) {
 		
        if (t1.getHp() > t2.getHp()) {
 			return t1;
		} 
		else {
 			return t2;
        }
        
    }
}


문제2 - 제네릭 타입과 상한

  • 다음 코드와 실행 결과를 참고해서 Shuttle 클래스를 만들어라
  • Shuttle 클래스의 조건은 다음과 같다.
    • 제네릭 타입을 사용해야 한다.
    • showInfo() 메서드를 통해 탑승한 유닛의 정보를 출력한다.

package generic.test.ex3;

import generic.test.ex3.unit.Marine;
import generic.test.ex3.unit.Zealot;
import generic.test.ex3.unit.Zergling;

public class ShuttleTest {

 	public static void main(String[] args) {
    
 		Shuttle<Marine> shuttle1 = new Shuttle<>();
        shuttle1.in(new Marine("마린", 40));
        shuttle1.showInfo();
        
 		Shuttle<Zergling> shuttle2 = new Shuttle<>();
        shuttle2.in(new Zergling("저글링", 35));
        shuttle2.showInfo();
        
 		Shuttle<Zealot> shuttle3 = new Shuttle<>();
        shuttle3.in(new Zealot("질럿", 100));
        shuttle3.showInfo();
        
    }
    
}

실행 결과

이름: 마린, HP: 40
이름: 저글링, HP: 35
이름: 질럿, HP: 100

정답 - Shuttle 클래스

package generic.test.ex3;

import generic.test.ex3.unit.BioUnit;

public class Shuttle<T extends BioUnit> {

 	private T unit;
    
 	public void in(T t) {
        unit = t;
    }
    
 	public T out() {
 		return unit;
    }
    
 	public void showInfo() {
 		System.out.println("이름: " + unit.getName() + ", HP: " + unit.getHp());
    }
    
 }


문제3 - 제네릭 메서드와 와일드카드


  • 앞서 문제에서 만든 Shuttle을 활용한다.
  • 다음 코드와 실행 결과를 참고해서 UnitPrinter 클래스를 만들어라.
  • UnitPrinter 클래스의 조건은 다음과 같다.
    • UnitPrinter.printV1()은 제네릭 메서드로 구현해야 한다.
    • UnitPrinter.printV2()는 와일드카드로 구현해야 한다.
    • 이 두 메서드는 셔틀에 들어있는 유닛의 정보를 출력한다.

package generic.test.ex3;

import generic.test.ex3.unit.Marine;
import generic.test.ex3.unit.Zealot;
import generic.test.ex3.unit.Zergling;

public class UnitPrinterTest {

	public static void main(String[] args) {

		Shuttle<Marine> shuttle1 = new Shuttle<>();
        shuttle1.in(new Marine("마린", 40));
        
		Shuttle<Zergling> shuttle2 = new Shuttle<>();
        shuttle2.in(new Zergling("저글링", 35));
        
 		Shuttle<Zealot> shuttle3 = new Shuttle<>();
        shuttle3.in(new Zealot("질럿", 100));
        
 		UnitPrinter.printV1(shuttle1);
 		UnitPrinter.printV2(shuttle1);
 
    }
    
 }

실행결과

이름: 마린, HP: 40
이름: 마린, HP: 40

정답 - UnitPrinter 클래스

package generic.test.ex3;

import generic.test.ex3.unit.BioUnit;

public class UnitPrinter {

 	public static <T extends BioUnit> void printV1(Shuttle<T> t1) {
    
 		T unit = t1.out();
 		System.out.println("이름: " + unit.getName() + ", HP: " + unit.getHp());
    }
    
 	public static void printV2(Shuttle<? extends BioUnit> t1) {
 		BioUnit unit = t1.out();
 		System.out.println("이름: " + unit.getName() + ", HP: " + unit.getHp());
    }
    
}


정리


  • 실무에서 직접 제네릭을 사용해서 무언가를 설계하거나 만드는 일은 드물게 있음

    • 그것보다는 대부분 이미 제네릭을 통해 만들어진 프레임워크나 라이브러리들을 가져다 사용하는 경우가 훨씬 많음
    • 그래서 이미 만들어진 코드의 제네릭을 읽고 이해하는 정도면 충분함
  • 실무에서 직접 제네릭을 사용하더라도 어렵고 복잡하게 사용하기 보다는 보통 단순하게 사용함

    • 지금까지 학습한 정도면 실무에 필요한 제네릭은 충분히 이해했다고 볼 수 있음

  • 제네릭은 지금까지 설명한 내용보다 더 복잡하고 어려운 개념들도 있음

    • 특히 공변(covariant), 반공변(contravariant)과 같은 개념이 그러함
    • 이런 개념들을 이해하면 와일드 카드가 존재하는 이유도 더 깊이 있게 알 수 있음
  • 하지만 제네릭을 사용해서 매우 복잡한 라이브러리나 프레임워크를 직접 설계하지 않는 이상 이런 개념들을 꼭 이해할 필요는 없음

    • 이런 부분은 실무에서 많은 경험을 쌓고 본인이 필요하다고 느껴질 때 따로 공부하는 것을 권장함

  • 제네릭은 이후에 설명하는 컬렉션 프레임워크에서 가장 많이 사용함
    • 따라서 컬렉션 프레임워크를 통해서 제네릭이 어떻게 활용되는지 자연스럽게 학습할 수 있음


강의 출처 : 김영한의 실전 자바 - 중급 2편

profile
Backend development

0개의 댓글