나를 기록하다
article thumbnail
Published 2023. 10. 11. 15:00
[Java] 제네릭스(Generics) Java
반응형

자바

제네릭스(Generics)

정의
  • 다양한 타입의 객체를 지원하는 클래스나 인터페이스 또는 메서드를 정의하는 방법
  • 똑같은 동작을 하는 클래스나 메서드를 여러 번 만들 필요 없이 딱 한 번만 정의한 후 여러 타입에 대해서 지원할 수 있도록 해주는 것

 

[예시] 제네릭스 사용 전

public class Main {
	public static void main(String[] args) {
		//제네릭스
		int[] iArray = {1, 2, 3, 4, 5};
		double[] dArray = {1.0, 2.0, 3.0, 4.0, 5.0};
		String[] sArray = {"A", "B", "C", "D", "E"};

		printIntArray(iArray);
		printDoubleArray(dArray);
		printStringArray(sArray);
	}

	private static void printStringArray(String[] sArray) {
		for (String s : sArray) {
			System.out.print(s + " ");
		}
		System.out.println();
	}

	private static void printDoubleArray(double[] dArray) {
		for (double d : dArray) {
			System.out.print(d + " ");
		}
		System.out.println();
	}

	private static void printIntArray(int[] iArray) {
		for (int i : iArray) {
			System.out.print(i + " "); //1 2 3 4 5
		}
		System.out.println();
	}
}
  • 자료형만 다르고 각 메서드의 코드가 반복된다.
  • 만약 long, float, boolean 등의 자료형이 추가된다면 서로 다른 자료형을 지원하는 메서드를 추가해야 한다.
  • 이럴 때 제네릭스를 이용할 수 있다.

 

[예시] 제네릭스 사용 후

public class Main {
	public static void main(String[] args) {
		//제네릭스
		Integer[] iArray = {1, 2, 3, 4, 5};
		Double[] dArray = {1.0, 2.0, 3.0, 4.0, 5.0};
		String[] sArray = {"A", "B", "C", "D", "E"};
		
		printAnyArray(iArray);
		printAnyArray(dArray);
		printAnyArray(sArray);
	}

	private static <T> void printAnyArray(T[] array) {
		for (T t : array) {
			System.out.print(t + " ");
		}
		System.out.println();
	}
}
  • 전달받는 값이 어떤 값인지 모르기 때문에 static과 void 사이에 <T>를 적어주고 전달받는 값도 T[] array과 같이 받는다.
  • 이때 T는 Type을 의미하고 일반적으로 T를 적지만 꼭 T가 아니더라도 다른 값을 넣어도 쌍만 이루어진다면 상관없다.
  • T(Type), K(Key), V(Value), E(Element)와 같이 쓴다.
  • 출력을 위해 printAnyArray(iArray), printAnyArray(dArray)를 작성하면 에러 발생
    • 제네릭스에서 지원하는 것은 객체. 기본 자료형(int, double, float ...)과 참조 자료형(Integer, Double, Float ...)
    • 이런것들은 제네릭스 타입으로 바로 사용 불가
    • 래퍼 클래스를 이용해야 함
    • int → Integer.parseInt()
    • double → Double.parseDouble()

제네릭 클래스(Generic Class)

[예시] 커피숍 주문 - 제네릭 클래스 적용 전

Main

public class Main {
	public static void main(String[] args) {
		//제네릭 클래스
		CoffeeByNumber c1 = new CoffeeByNumber(33);
		c1.ready();
		CoffeeByNickname c2 = new CoffeeByNickname("prao");
		c2.ready();
	}
}

CoffeeByNumber

public class CoffeeByNumber {
	public int waitingNumber;

	public CoffeeByNumber(int waitingNumber) {
		this.waitingNumber = waitingNumber;
	}

	public void ready() {
		System.out.println("커피 준비 완료 : " + waitingNumber);
	}
}

CoffeeByNickName

public class CoffeeByNickname {
	public String nickname;

	public CoffeeByNickname(String nickname) {
		this.nickname = nickname;
	}

	public void ready() {
		System.out.println("커피 준비 완료 : " + nickname);
	}
}
  • CoffeeByNumber와 CoffeeByNickname의 동작은 같다.
  • 어떤 값을 전달받고 ready 메서드를 호출하면 값을 출력하는 형태
  • 자료형이 바뀌면 매번 새로운 클래스를 생성해야 함

 

모든 자료형의 조상인 Object를 사용하면?

Main

public class Main {
	public static void main(String[] args) {
		//제네릭 클래스
		CoffeeByName c3 = new CoffeeByName(34);
		c3.ready();
		CoffeeByName c4 = new CoffeeByName("ugirin");
		c4.ready();
	}
}

CoffeeByName

public class CoffeeByName {
	public Object name;

	public CoffeeByName(Object name) {
		this.name = name;
	}

	public void ready() {
		System.out.println("커피 준비 완료 : " + name);
	}
}
  • 정수, 문자 상관없이 출력 성공
  • 사용자가 실수를 하지 않으면 괜찮지만 코드를 실행해보기 전까지 에러를 알 수 없음

메인 클래스

  • 위 코드와 같이 주문 고객 이름에 실수로 주문 고객 번호를 넣어도 에러가 발생하지 않는 문제 발생

제네릭 클래스 적용

Coffee

public class Coffee<T> {
	public T name;

	public Coffee(T name) {
		this.name = name;
	}

	public void ready() {
		System.out.println("커피 준비 완료 : " + name);
	}
}

 

Main

public class Main {
	public static void main(String[] args) {
		//제네릭 클래스
		Coffee<Integer> c5 = new Coffee<>(35);
		c5.ready();
		Coffee<String> c6 = new Coffee<>("손흥민");
		c6.ready();
	}
}
  • 제네릭 클래스 사용 시 자료형을 먼저 설정하였기 때문에 설정한 자료형만 넣을 수 있어서 실수를 방지 가능

 

커피숍 이용 고객의 데이터를 클래스로 관리

CoffeeByUser

public class CoffeeByUser<T extends User> {
	public T user;

	public CoffeeByUser(T user) {
		this.user = user;
	}

	public void ready() {
		System.out.println("커피 준비 완료 : " + user.name);
		user.addPoint();
	}
}
  • 원하는 형태의 클래스 객체만 받음
  • 어떤 형태의 타입을 쓰던 상관없지만 반드시 User라는 클래스를 상속하는 T를 써야한다.

User

public class User {
	public String name;

	public User(String name) {
		this.name = name;
	}

	public void addPoint() {
		System.out.println(this.name + "님 포인트 적립되었습니다.");
	}
}

VipUser

public class VIPUser extends User {
	public VIPUser(String name) {
		super("VIP " + name);
	}
}

Main

public class Main {
	public static void main(String[] args) {
		//제네릭 클래스
		CoffeeByUser<User> c7 = new CoffeeByUser<>(new User("강호동"));
		c7.ready();
		CoffeeByUser<User> c8 = new CoffeeByUser<>(new VIPUser("유재석"));
		c8.ready();
	}
}
  • new User()을 통해 객체를 생성하고 바로 CoffeeByUser에 객체를 넣음

결과

커피 준비 완료 : 강호동
강호동님 포인트 적립되었습니다.
커피 준비 완료 : VIP 유재석
VIP 유재석님 포인트 적립되었습니다.

 

두 개 이상의 데이터를 처리하는 메서드

Main

public class Main {
	public static void main(String[] args) {
		//제네릭 클래스
		orderCoffee("김영철");
		orderCoffee(36);
		orderCoffee("이동국", "아메리카노");
		orderCoffee(37, "카페라떼");
	}

	public static <T> void orderCoffee(T name) {
		System.out.println("커피 준비 완료 : " + name);
	}

	public static <T, V> void orderCoffee(T name, V coffee) {
		System.out.println(coffee + " 준비 완료 : " + name);
	}
}

결과

커피 준비 완료 : 김영철
커피 준비 완료 : 36
아메리카노 준비 완료 : 이동국
카페라떼 준비 완료 : 37

Wrapper 클래스

래퍼(Wrapper) 클래스란?
  • 기본 자료형(int, double, float, char)을 객체 형태로 만들어서 사용할 수 있도록 함
public class Main {
	public static void main(String[] args) {
		//래퍼(Wrapper) 클래스
		//int, double, float, char
		Integer i = 123; // int i = 123;
		Double d = 1.0; // double d = 1.0;
		Character c = 'A'; // char c = 'A';

		System.out.println(i);
		System.out.println(d);
		System.out.println(c);

		System.out.println("-----------------");

		System.out.println(i.intValue()); // 정수값 출력
		System.out.println(d.intValue()); // 정수값 출력
		System.out.println(c.charValue()); // char값 출력

		System.out.println("-----------------");

결과

123
1.0
A
-----------------
123
1
A
-----------------
123

참고자료

https://www.inflearn.com/course/%EB%82%98%EB%8F%84%EC%BD%94%EB%94%A9-%EC%9E%90%EB%B0%94-%EA%B8%B0%EB%B3%B8/dashboard

 

나도코딩의 자바 기본편 - 풀코스 (20시간) - 인프런 | 강의

배움의 즐거움을 알게 해주는 강의. 나도코딩의 자바 기본편을 소개합니다., 빠르고 효율적이면서퀴즈까지 풀 수 있는 자바 강의가 있다? 😮 '너무 재밌어요.가르쳐주시는 짧은 주제마다 응용

www.inflearn.com

 

반응형
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...