[JAVA] 제네릭

Organ·2023년 10월 16일
0

JAVA

목록 보기
11/14

스텝 1 - 제네릭의 필요성

package com.in28minutes.generics;

public class GenericsRunner {
	public static void main(String[] args) {
		MycustomList list = new MycustomList();
		list.addElement("Element 1");
		list.addElement("Element 2");
//1.같은 클래스를 숫자를 가지고 만든다고 해보자
		MycustomList list2 = new MycustomList();
		list.addElement(Integer.valueOf(5));
		list.addElement(Integer.valueOf(6));
//2.하지만 지금 구현한 건 한 가지 데이터 종류에만 적용된다. 바로 String이다.
// 그래서 오류가 뜬 것
	}
}

package com.in28minutes.generics;
import java.util.ArrayList;

public class MycustomList {
	ArrayList<String> list = new ArrayList();
	
	public void addElement(String element) {
		list.add(element);
	}
	public void removeElement(String element) {
		list.remove(element);
	}
}

// 이 구현은 String만 받아들이게 짜여졌다. 어떻게 하면 데이터 종류에 묶이지 않은 
// 클래스를 만들까? 이 때문에 제네릭이 필요하다.

스텝 2 - 제네릭 구현

package com.in28minutes.generics;

public class GenericsRunner {

	public static void main(String[] args) {
//2.제네릭 타입을 정의하자 MycustomList에 에러가 뜨는데 매개변수화를 시도하라고 나온다.
		MycustomList<String> list = new MycustomList<>();
		list.addElement("Element 1");
		list.addElement("Element 2");

		System.out.println(list);//[Element 1, Element 2]

		MycustomList<Integer> list2 = new MycustomList<>();
//3.그러나 <Integer>을 넣어줘도 아래 메소도는 String형으로 만들어 줬기 때문에 정수를 못 받는다.
		list2.addElement(Integer.valueOf(5));
		list2.addElement(Integer.valueOf(6));

		System.out.println(list2);//[5, 6]
	}

}

package com.in28minutes.generics;

import java.util.ArrayList;

//1.<>안에는 제네릭 타입을 정의할 수 있다.
public class MycustomList<T> {
//4.이를 해결하기 위해 String 대신 T를 넣어준다
	ArrayList<T> list = new ArrayList();

	public void addElement(T element) {
		list.add(element);
	}

	public void removeElement(T element) {
		list.remove(element);
	}

	@Override
	public String toString() {
		return list.toString();
	}
}

// 이렇게 String을 저장하는 List와 Integer를 저장하는 List2를 만들었다.

스텝 3 - 제네릭 return 메소드

package com.in28minutes.generics;

public class GenericsRunner {

	public static void main(String[] args) {
		MycustomList<String> list = new MycustomList<>();
		list.addElement("Element 1");
		list.addElement("Element 2");
//1.이 특정 메소드에서 문자열뿐 아니라 정수도 출력하고 싶다.
		String value = list.get(0);

		System.out.println(value);

		MycustomList<Integer> list2 = new MycustomList<>();
		list2.addElement(Integer.valueOf(5));
		list2.addElement(Integer.valueOf(6));
		Integer number = list2.get(0);

		System.out.println(number);
	}

}
package com.in28minutes.generics;

import java.util.ArrayList;

public class MycustomList<T> {
	ArrayList<T> list = new ArrayList();

	public void addElement(T element) {
		list.add(element);
	}

	public void removeElement(T element) {
		list.remove(element);
	}

	@Override
	public String toString() {
		return list.toString();
	}
//2. 여기서도 또한 String대신 정수 숫자 둘 다 원하기 때문에 T사용했다.
//public String get(int index)
	public T get(int index) {
		return list.get(index);
	}
}

스텝 4 - 제한과 확장, 제네릭 메소드

package com.in28minutes.generics;

import java.util.ArrayList;

public class GenericsRunner {
// 7. 제네릭을 가지고도 메소드를 만들 수 있는데 간단한 메소드를 만들어보자
	static <X> X doubleValue(X value){
			return value;
}
// 8. 같은 종류의 값을 받아들이기 같은 종류의 값을 반환한다는 뜻 이제 뭐든 호출이 가능하다.
// 10. List를 상속받는 아무거나 라고 제한한다면 
static <X extends List> void duplicate(X list){
			list.addAll(list);
// 11. 이렇게 하면 ArrayList이든 LinkedList이든 list를 상속받는 것들이면 뭐든지 list에
// 더해질 것이다.
}
	public static void main(String[] args) {
		String value = doubleValue(new String());
		Integer number = doubleValue(Integer.valueOf(5));
		ArrayList list1 = doubleValue(new ArrayList());
// 9. 이것들은 넣어준 종류의 값을 반환하기 때문에 같은 종류로 받아야한다. 이런것들을 
// 함으로써 진짜 이득은 종류를 제한할때 생긴다.
		
// 12. Integer ArrayList를 하나 만들자
		ArrayList<Integer> numbers = new ArrayList<>(List.of(1,2,3));
		duplicate(numbers);
		System.out.println(numbers);  // 13. 어떤일이 벌어질까?
// 1,2,3,1,2,3  -> 기존에 1,2,3 에 duplicate메소드에서 1,2,3이 더해져서 나온 결과다

// 1. MycustomList를 정수로만 Integer가 아닌 number로만 사용하기를 원한다고 가정하자
		MycustomList<String> list = new MycustomList<>();
// 3. 이렇게 하면 String밑에 에러가 뜨면서 String은 Number가 아니라는 에러문이 뜬다.
		list.addElement("Element 1");
		list.addElement("Element 2");

		String value = list.get(0);

		System.out.println(value);

		MycustomList<Integer> list2 = new MycustomList<>();
//4. Integer는 Number에서 상속받기 때문에 문제가 안된다. 그렇기 때문에 Long등을 사용해도
// 문제가 없지만 String은 문제가 된다.
		list2.addElement(Integer.valueOf(5));
		list2.addElement(Integer.valueOf(6));
		Integer number = list2.get(0);

		System.out.println(number);
	}

}
package com.in28minutes.generics;

import java.util.ArrayList;
// 2. 이렇게 extends Number로 해줬다.
public class MycustomList<T extends Number> {
// 5. 이것이 제한하는 방법이고 제한하는 것의 장점은 이제 요소에 가능한 모든 
// 메소드들을 사용할 수 있다는 것이다.
	ArrayList<T> list = new ArrayList();

	public void addElement(T element) {
//6. element.byteValue() / DoubleValue() / FloatValue 등등의 메소드들은 Number 클래스안에
// 모두 존재하는 메소드이기 때문에 사용이 가능하다.
		list.add(element);
	}

	public void removeElement(T element) {
		list.remove(element);
	}

	@Override
	public String toString() {
		return list.toString();
	}
	public T get(int index) {
		return list.get(index);
	}
}

스텝 5 - 제네릭과 와일드 카드

package com.in28minutes.generics;

import java.util.ArrayList;

public class GenericsRunner {
	static <X> X doubleValue(X value){
			return value;
				}
 
static <X extends List> void duplicate(X list){
			list.addAll(list);
}
		// 1. 숫자로 이뤄진 아무 리스트나 더할 수 있는 메소드를 만들고 싶다고 가정해보자
	 // Number를 상속받는 어떤 list라도 받을 수 있고 double를 반환하는 메소드를 만들었다
// 5. 이 와일드카드를 상한경계 와일드카드라고 부른다.
static double sumOfNumberList(list<? extends Number> numbers){
		// 2. 여기서 ?가 와일드카드라고 불리는 것이다. Number 클래스를 연장하는 모든 종류의
// 리스트는 적절한 리스트 인 것이다.
		double sum = 0.0;
		for(Number number : numbers){
				sum += number.doubleValue();
		}
		return sum;
		// 3. 이 메소드는 어떠한 리스트든 더하는데 사용할 수 있다.
}
// 6. 이것이 하한 경계 와일드카드라고 하는데 즉 하한 경계가 Number라고 정의된 것
static void addACoupleValues(list<? super Number> numbers){
		numbers.add(1);
		numbers.add(1.0);
		numbers.add(1.0f);
		numbers.add(1l);
// 7. 즉 number클래스의 하위 클래스인 이상 아무 종류나 이 특정한 number에 추가될 수 있는 것
}

	public static void main(String[] args) {
		List emptyList = new ArrayLisy<number>();
		addACoupleValues(emptyList);
		System.out.println(emptyList);
// 1. 1.0. 1.0, 1


// 4. 우리는 이제 Integer, Double, Long리스트를 마음껏 사용할 수 있다.
		System.out.println(sumOfNumberList(List.of(1,2,3,4,5)));
		System.out.println(sumOfNumberList(List.of(1.1,2.1,3.1,4.1,5.1)));
		System.out.println(sumOfNumberList(List.of(1l,2l,3l,4l,5l)));
// 15.0
// 15.5
// 15.0

		String value = doubleValue(new String());
		Integer number = doubleValue(Integer.valueOf(5));
		ArrayList list1 = doubleValue(new ArrayList());

		ArrayList<Integer> numbers = new ArrayList<>(List.of(1,2,3));
		duplicate(numbers);
		System.out.println(numbers); 

		MycustomList<String> list = new MycustomList<>();

		list.addElement("Element 1");
		list.addElement("Element 2");

		String value = list.get(0);

		System.out.println(value);

		MycustomList<Integer> list2 = new MycustomList<>();

		list2.addElement(Integer.valueOf(5));
		list2.addElement(Integer.valueOf(6));
		Integer number = list2.get(0);

		System.out.println(number);
	}

}
package com.in28minutes.generics;

import java.util.ArrayList;

public class MycustomList<T extends Number> {
	ArrayList<T> list = new ArrayList();

	public void addElement(T element) {
		list.add(element);
	}

	public void removeElement(T element) {
		list.remove(element);
	}

	@Override
	public String toString() {
		return list.toString();
	}
	public T get(int index) {
		return list.get(index);
	}
}

0개의 댓글