ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 제너릭 (Generic)
    JAVA 2022. 9. 24. 17:31

    Generic

    클래스 선언 및 객체화 할 때 원하는 타입만을 넣기 위해서 쓰는 것

    -> 어떤 타입이 들어 있는지 정보가 없기 때문에 확인 작업이 필요하다.

    -> 제네릭을 사용하면 확인 작업을 안해도 된다.

     

    package chap08.ex03.obj;
    
    public class Box {
    
    	private Object value; // 이 안에 뭐가 들어올지 몰라서 Object로 만들어 둔다.
    
    	public void setValue(Object value) {
    		this.value = value;
    	}
    
    	public Object getValue() {
    		return value;
    	}
    }
    package chap08.ex03.obj;
    
    public class Main {
    
    	public static void main(String[] args) {
    
    		// 박스에 무엇인가 넣는다.
    		Box box = new Box();
    		box.setValue(123);
    		
    		// 박스에서 물건을 꺼낸다.
    		// box에 무엇이 들었는지 정보가 없음
    		// 그래서 확인 작업이 필요
    		int val = (int)box.getValue();
    		System.out.println(val);
    	}
    
    }

     

    Generic 사용법

    클래스나 인터페이스 선언 시 <T>를 붙인다.

    T의 타입에 따라 데이터 타입이 변경된다.

     

    package chap08.ex04.generic;
    
    public class Box<T> { // 뭐가 들어올지 모르므로 일단 T라고 해둔다.
    	
    	private T value; // T 타입에 따라 변수의 데이터 타입이 변경된다.
    
    	public T getValue() {
    		return value;
    	}
    
    	public void setValue(T value) {
    		this.value = value;
    	}
    
    }
    package chap08.ex04.generic;
    
    public class Main {
    
    	public static void main(String[] args) {
    
    		// 박스에 들어갈 물건의 종류를 명시해준다.
    		Box<Integer> box = new Box<Integer>();
    		box.setValue(123);
    		
    		// 박스를 열어본다.
    		// 내용물을 알 수 있으므로 확인이 필요없다.
    		int val = box.getValue();
    		System.out.println(val);
    	}
    
    }

     

    복수개의 제네릭을 사용 가능하다. (콤마로 구분하여)

     

    package chap08.ex05.multi;
    
    public class MultiBox<K,V> { // 두 개의 타입을 지정할 수 있다.
    
    	private K key;
    	private V value;
    	
    	public K getKey() {
    		return key;
    	}
    	public void setKey(K key) {
    		this.key = key;
    	}
    	public V getValue() {
    		return value;
    	}
    	public void setValue(V value) {
    		this.value = value;
    	}
    }
    package chap08.ex05.multi;
    
    public class Main {
    
    	public static void main(String[] args) {
    	
    		// 첫 변수는 String 타입, 두 번째 변수는 Integer가 데이터 타입이 된다.
    		MultiBox<String, Integer> box = new MultiBox<String, Integer>();
    		
    		//넣기
    		box.setKey("홍길동");
    		box.setValue(90);
    		
    		//꺼내기
    		String name = box.getKey();
    		int score = box.getValue();
    		System.out.println(name+" : " + score);
    		
    	}
    
    }

     

    Generic의 클래스 사용

    객체화 부분 제네릭에 데이터 타입을 명시하지 않아도 작동은 하지만 이를 다이아몬드 연산자라고 부른다 -> 사용은 편리하지만 효율성이 떨어진다.

     

    package chap08.ex06.multi;
    
    public class Employee<A,B,C,D,E,F,G,H> {
    
    	private A number;
    	private B name;
    	private C age;
    	private D money;
    	private E asset;
    	private F pay;
    	private G marry;
    	private H hobby;
    	
    	public A getNumber() {
    		return number;
    	}
    	public void setNumber(A number) {
    		this.number = number;
    	}
    	public B getName() {
    		return name;
    	}
    	public void setName(B name) {
    		this.name = name;
    	}
    	public C getAge() {
    		return age;
    	}
    	public void setAge(C age) {
    		this.age = age;
    	}
    	public D getMoney() {
    		return money;
    	}
    	public void setMoney(D money) {
    		this.money = money;
    	}
    	public E getAsset() {
    		return asset;
    	}
    	public void setAsset(E asset) {
    		this.asset = asset;
    	}
    	public F getPay() {
    		return pay;
    	}
    	public void setPay(F pay) {
    		this.pay = pay;
    	}
    	public G getMarry() {
    		return marry;
    	}
    	public void setMarry(G marry) {
    		this.marry = marry;
    	}
    	public H getHobby() {
    		return hobby;
    	}
    	public void setHobby(H hobby) {
    		this.hobby = hobby;
    	}
    	
    }
    package chap08.ex06.multi;
    
    public class Main {
    
    	// 제너릭 타입을 클래스로 사용하지 않은 경우
    	public static void main(String[] args) {
    
    		// 객체화 부분 제너릭에 데이터 타입을 명시해주지 않는 것을 다이아몬드 연산자라고 부른다.
    		// 사용은 편리하지만 효율성이 떨어진다.
    		Employee<Integer, String, Integer, Integer, Long, Float, Boolean, String> emp = new Employee<>();
    		
    		// 데이터 넣기
    		emp.setAge(25);
    		emp.setAsset((long) 50000000);
    		emp.setHobby("독서");
    		emp.setMarry(true);
    		emp.setMoney(10000);
    		emp.setName("홍길동");
    		emp.setNumber(12);
    		emp.setPay(1.0f);
    		
    		// 데이터 가져오기
    		int age = emp.getAge();
    		System.out.println(age);
    		
    	}
    
    }

     

    제네릭 부분이 길어질 경우 클래스를 사용할 수 있다.

    클래스를 사용하지 않을 때 데이터를 setter/getter로 바로 꺼내올 수 있지만 코드가 길어지고 실수가 생길 수 있다는 단점이 있다.

    클래스를 사용한다면 데이터를 넣고 가져오는데 한 번씩의 작업을 더 해야하지만 코드를 줄일 수 있다. (제네릭이 많을 때 유리하다.)

     

    package chap08.ex07.classtype;
    
    public class Info {
    
    	private int emp_no;
    	private String name;
    	private int age;
    	private int salary;
    	private long assets;
    	private float commision;
    	private boolean married;
    	private String hobby;
    	
    	public int getEmp_no() {
    		return emp_no;
    	}
    	public void setEmp_no(int emp_no) {
    		this.emp_no = emp_no;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public int getSalary() {
    		return salary;
    	}
    	public void setSalary(int salary) {
    		this.salary = salary;
    	}
    	public long getAssets() {
    		return assets;
    	}
    	public void setAssets(long assets) {
    		this.assets = assets;
    	}
    	public float getCommision() {
    		return commision;
    	}
    	public void setCommision(float commision) {
    		this.commision = commision;
    	}
    	public boolean isMarried() {
    		return married;
    	}
    	public void setMarried(boolean married) {
    		this.married = married;
    	}
    	public String getHobby() {
    		return hobby;
    	}
    	public void setHobby(String hobby) {
    		this.hobby = hobby;
    	}
    	
    	
    }
    package chap08.ex07.classtype;
    
    public class Employee <T>{
    
    	private T t;
    
    	public T getT() {
    		return t;
    	}
    
    	public void setT(T t) {
    		this.t = t;
    	}
    }
    package chap08.ex07.classtype;
    
    public class Main {
    
    	// 제너릭 타입을 클래스로 사용한 경우
    	public static void main(String[] args) {
    
    		Employee<Info> emp = new Employee<Info>();
    		
    		// 데이터 넣기
    		Info info = new Info();
    		
    		info.setAge(25);
    		info.setAssets(1000000);
    		info.setCommision(1.0f);
    		info.setEmp_no(2);
    		info.setHobby("영화");
    		info.setMarried(false);
    		info.setName("김철수");
    		info.setSalary(10000);
    		
    		emp.setT(info);
    		
    		//데이터 가져오기
    		info = emp.getT();
    		int age = info.getAge();
    		System.out.println(age);
    	}
    
    }

     

    method에서 Generic 사용

    메소드에서 제네릭을 사용하면 각각 다른 매개변수 타입을 사용할 수 있다.

    -> 상황에 따라 유연하게 사용 가능하다.

    반환이 없는 메소드일 경우 접근제한자와 void 사이에 제네릭을 쓰고 매개변수도 제네릭 타입으로 사용한다.

    반환이 있는 메소드일 경우 메소드의 반환타입도 제네릭 타입으로 적어야한다.

     

    package chap08.ex08.gmethod;
    
    public class Gmethod {
    
    	// 제너릭을 사용하면 사용 시마다 각각 다른 매개변수 타입을 사용할 수 있다.
    	public <T> void method1(T t) {
    		System.out.println("입력값 : " + t);
    	}
    	
    	// 받은 그대로 반환해 주는 경우  
    	public <T> T method2(T t) {
    		return t;
    	}
    }
    package chap08.ex08.gmethod;
    
    public class Main {
    
    	public static void main(String[] args) {
    
    		Gmethod gm = new Gmethod();
    		gm.method1(100);
    		gm.method1("감자");
    		
    		System.out.println(gm.method2("고구마"));
    		System.out.println(gm.method2(true));
    	}
    
    }

     

    Generic의 상속

    클래스에서 자식의 생성자 매개변수를 받아 부모의 생성자에 전달한 것처럼 자식에서 부모에서 사용할 제네릭 타입을 받아서 전달해야 한다.

    package chap08.ex09.inherit;
    
    public class BasicInfo<N,A> {
    
    	private N name;
    	private A age;
    	
    	public N getName() {
    		return name;
    	}
    	public void setName(N name) {
    		this.name = name;
    	}
    	public A getAge() {
    		return age;
    	}
    	public void setAge(A age) {
    		this.age = age;
    	}
    	
    	
    }
    package chap08.ex09.inherit;
    
    public class DetailInfo<N, A, H> extends BasicInfo<N, A> {
    
    	private H hobby;
    
    	public H getHobby() {
    		return hobby;
    	}
    
    	public void setHobby(H hobby) {
    		this.hobby = hobby;
    	}
    	
    }
    package chap08.ex09.inherit;
    
    public class Main {
    
    	public static void main(String[] args) {
    
    		DetailInfo<String, Integer, String> info = new DetailInfo<String, Integer, String>(); 
    		
    		info.setName("홍길동");
    		info.setAge(25);
    		info.setHobby("게임");
    		
    		String name = info.getName();
    		int age = info.getAge();
    		String hobby = info.getHobby();
    		
    		System.out.println(name + "/" + age + "/" + hobby);
    	}
    
    }

    'JAVA' 카테고리의 다른 글

    thread - 1 (스레드 생성~join)  (1) 2022.09.24
    컬렉션 프레임워크(List, Set, Map)  (1) 2022.09.24
    문자열 (String)  (1) 2022.09.24
    예외 (Exception)  (0) 2022.09.24
    추상화 (abstract, interface)  (0) 2022.09.24
Designed by Tistory.