-
[Java] Java Generic(μ λ€λ¦)Android/Java 2021. 3. 1. 15:43λ°μν
- μ΄ κΈμ "μλ° μ¨λΌμΈ μ€ν°λ"μμ 곡λΆν λ΄μ©μ μμ±νμμ΅λλ€.
Genericμ΄λ?
Integerν λ°°μ΄, Stringν λ°°μ΄ λ±λ± λ°°μ΄μ ν¬ν¨λλ μμμ νμ λ§λ€ μΆκ°, μμ , μ λ ¬κ³Ό κ°μ ν¨μλ₯Ό μ μνκ³ μ¬μ©νλ κ²μ λΆλͺ λΉν¨μ¨μ μΌ κ²μ λλ€.
μλ°μ Genericμ λ°μ΄ν°μ νμ μ μΌλ°ννλ€λ μλ―Έλ‘ ν΄λμ€λ λ©μλ μ μ μ μΌλ°ννμ¬ μ¬μ©ν λ°μ΄ν° νμ μ μ»΄νμΌ μμ 미리 μ§μ νλ λ°©λ²μ λλ€.
JDK1.5 λΆν° Genericμ μ¬μ©κ°λ₯νλ©°, μ»΄νμΌ μ νμ μ΄ μ ν΄μ§κΈ° λλ¬Έμ, ν΄λμ€λ λ©μλ λ΄λΆμ μ¬μ©λ λ°μ΄ν°μ νμ μμ μ±μ λμΌ μ μμ΅λλ€.
JDK1.5 μ΄μ μλ Object νμ μ μ¬μ©νμ¬ μνλ κ°μ²΄μ νμ μΌλ‘ μΊμ€ν νμ¬ μ¬μ©ν΄μΌλ§ νκ³ , μλͺ»λ μΊμ€ν μΌλ‘ μΈν΄ λ°νμ μ€λ₯ λ°μν κ°λ₯μ±μ΄ μμ΅λλ€.
public class Example { public static void main(String[] args) { // JDK 1.5 μ΄μ ArrayList arrayList = new ArrayList(); arrayList.add("Hello"); String str = (String)arrayList.get(0); // μΊμ€ν μν μ, μ»΄νμΌ μ€λ₯ System.out.println("Not Generic : "+str); ArrayList<String> stringArrayList = new ArrayList<>(); stringArrayList.add("World"); String str2 = stringArrayList.get(0); // μΊμ€ν μκ΄ μλ€. => νμ μμ μ± μ 곡 System.out.println("Generic : "+str2); } }
Generic ν΄λμ€
μλ°μ μ λλ¦ ν΄λμ€μ κΈ°λ³Έ Syntaxλ λ€μκ³Ό κ°μ΅λλ€.
public class Box<T>{ private T t; }
μ μμ μμ μ¬μ©λ Tλ₯Ό νμ λ³μλΌκ³ νλ©°, μμμ μ°Έμ‘°ν νμ μ μλ―Έν©λλ€. νμ μ 맀κ°λ³μμ μ΄λ¦μ μ무거λ λ€μ΄κ°λ μκ΄μμ§λ§, 곡μλ¬Έμμ Name Conventionμ λ°λ₯΄λ κ² μ’μ΅λλ€.
- E : μ£Όλ‘ μλ° Collection frameworkμ μ¬μ©λλ Element
- K : mapμμ 맀κ°λ³μλ‘ μ¬μ©λλ Key
- V : mapμμ 맀κ°λ³μλ‘ μ¬μ©λλ Value
- N : μ«μλ₯Ό λνλ΄λ Number
- T : μΌλ°μ μΌλ‘ μ¬μ©νλ μ λ€λ¦ Type
- S : λλ²μ§Έλ‘ μ¬μ©νλ μΌλ° μ λ€λ¦ Type
- U : μΈλ²μ§Έλ‘ μ¬μ©νλ μΌλ° μ λ€λ¦ Type
- V : λ€λ²μ§Έλ‘ μ¬μ©νλ μΌλ° μ λ€λ¦ Type
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Example { public static void main(String[] args) { Box<Integer, String> box = new Box<Integer, String>(); box.add(Integer.valueOf(10),"Hello World"); System.out.printf("Integer Value :%d\n", box.getFirst()); System.out.printf("String Value :%s\n", box.getSecond()); Pair<String, Integer> pair = new Pair<>(); pair.addKeyValue("1", Integer.valueOf(10)); System.out.printf("(Pair)Integer Value :%d\n", pair.getValue("1")); CustomList<Box> list = new CustomList<Box>(); list.addItem(box); System.out.printf("(CustomList)Integer Value :%d\n", list.getItem(0).getFirst()); } } class Box<T, S> { private T t; private S s; public void add(T t, S s) { this.t = t; this.s = s; } public T getFirst() { return t; } public S getSecond() { return s; } } class Pair<K,V>{ private Map<K,V> map = new HashMap<K,V>(); public void addKeyValue(K key, V value) { map.put(key, value); } public V getValue(K key) { return map.get(key); } } class CustomList<E>{ private List<E> list = new ArrayList<E>(); public void addItem(E value) { list.add(value); } public E getItem(int index) { return list.get(index); } }
μμ μμλ 곡μλ¬Έμμ μμ λ₯Ό κ°μ§κ³ μμ΅λλ€. λ€μκ³Ό κ°μ Name Conventionμ λ°λ₯΄λ©΄ λκ³ , λͺ κ°μ§ μ£Όμν μ μΌλ‘λ Generic νμ μΌλ‘λ Primitive Typeμ μ¬μ©ν μ μμ΅λλ€. μ¦, int νκ³Ό κ°μ κΈ°λ³Έν νμ μ μ¬μ©ν μ μκ³ Intergerμ κ°μ μ°Έμ‘°ν νμ μ μ¬μ©ν μ μμ΅λλ€. λν, PairλΆλΆμμ newλ‘ ν λΉνλ λΆλΆμμλ νμ μ λͺ μνμ§ μμμ§λ§ μ€λ₯λ λνλμ§ μμμ΅λλ€. μλ° 7λ²μ μ΄νλ‘λ νμ μΆλ‘ μ΄ κ°λ₯νμ¬ new λ€μμλ μλ΅μ΄ κ°λ₯ν©λλ€.
Generic μΈν°νμ΄μ€
public class Example { public static void main(String[] args) { GenericClass genericClass = new GenericClass(); System.out.println(genericClass.print()); // Hello world } } class GenericClass implements GenericInterface<String>{ @Override public String print() { return "Hello world"; } } interface GenericInterface<T>{ T print(); }
μΈν°νμ΄μ€λ ν΄λμ€μ λμΌνκ² μΈν°νμ΄μ€λͺ μμ νμ λ³μλ₯Ό μ§μ νμ¬ μ¬μ©ν μ μμ΅λλ€.
Generic λ©μλ
Generic λ©μλλ₯Ό μ¬μ©νμ¬ λ©μλμ νλΌλ―Έν°μ μ¬λ¬ νμ μ λμ νλλ‘ ν μ μμ΅λλ€. Generic λ©μλμ μ λ¬λ 맀κ°λ³μμ νμ μ κΈ°λ°μΌλ‘ μ»΄νμΌλ¬λ μ μ ν λ©μλ νΈμΆμ μ²λ¦¬ν©λλ€.
- μ λ€λ¦ λ©μλμ νμ λ³μλ λ¦¬ν΄ νμ μμ μ μΈλμ΄μΌ ν©λλ€.
- νμ λ³μλ μ¬λ¬ κ°λ₯Ό κ°μ§ μ μμΌλ©°, κΈ°λ³Έ Name Conventionμ λ°λ¦ λλ€.
- μΌλ° ν΄λμ€μμ μ λ€λ¦ λ©μλλ₯Ό μ μΈν μ μκ³ , νμ λ³μλ λμΌνκ² κΈ°λ³Ένμ μλκ³ , μ°Έμ‘°νλ§ κ°λ₯ν©λλ€.
import java.util.ArrayList; import java.util.Arrays; public class Example { public static <E> void printArray(ArrayList<E> array){ for(E element : array){ System.out.print(element+" "); } System.out.println(); } public static void main(String[] args) { ArrayList<Integer> integerArrayList = new ArrayList<>(Arrays.asList(1,2,3,4,5)); ArrayList<Double> doubleArrayList = new ArrayList<>(Arrays.asList(1.1,2.2,3.3,4.4,5.5)); ArrayList<Character> characterArrayList = new ArrayList<>(Arrays.asList('a','b','c','d','e')); printArray(integerArrayList); printArray(doubleArrayList); printArray(characterArrayList); } }
Bounded Type
ν΄λμ€, μΈν°νμ΄μ€, λ©μλλ₯Ό μ λ€λ¦μΌλ‘ μμ±ν λ, νμ λ³μλ₯Ό μ ννκΈ° μν΄μλ Bounded TypeμΌλ‘ μ μΈν΄μΌ ν©λλ€.
<T extends μμνμ > μΌλ‘ νμ λ³μλ₯Ό μ§μ νμ¬ μμνμ μ νμν΄λμ€λ‘λ§ μ νν μ μμ΅λλ€.public class Example { public static void main(String[] args) { // bounded λ΄μ νμ μ΄ μλμ¬μ μ»΄νμΌ μ€λ₯ λ°μ // BoundedGeneric<String> boundedGeneric = new BoundedGeneric<String>(); BoundedGeneric<Integer> boundedGeneric = new BoundedGeneric<>(); boundedGeneric.setT(Integer.valueOf(10)); boundedGeneric.print(); } } class BoundedGeneric<T extends Number>{ T t; public void print(){ System.out.println(t); } public void setT(T t){ this.t = t; } }
WildCard
μλ°μμ μμΌλ μΉ΄λλ μ λ€λ¦ λ©μλμμ 맀κ°λ³μλ₯Ό λ°μ λ, νμ λ³μκ° μλ ? λ₯Ό μ¬μ©νμ¬ λ§€κ°λ³μμ νμ μ μ ννλ κ²μ λ§ν©λλ€.
import java.util.Arrays; import java.util.List; public class Example { public static double sum(List<? extends Number> numberlist){ double sum = 0.0; for(Number n : numberlist){ sum+=n.doubleValue(); } return sum; } public static void main(String[] args) { List<Integer> integerList = Arrays.asList(1,2,3); System.out.println("sum : "+sum(integerList)); // 6.0 List<Double> doubleList = Arrays.asList(1.1,2.2,3.3); System.out.println("sum : "+sum(doubleList)); // 6.6 } }
맀κ°λ³μλ‘ List numberlistλ‘ μ μΈλμλ€κ³ κ°μ ν΄λ³΄λ©΄, StringμΌλ‘ ꡬμ±λ 리μ€νΈ, Characterλ‘ κ΅¬μ±λ 리μ€νΈκ° 맀κ°λ³μλ‘ λμ μ΄ λλλΌλ μ€λ₯κ° λνλμ§ μμ΅λλ€. λ§μ½ λ©μλμμ Number νμμλ§ νΈμΆν μ μλ λ©μλλ₯Ό μ€ννλ€λ©΄ String, Characterλ‘ κ΅¬μ±λ 리μ€νΈκ° λμ λ κ²½μ° λ°νμ μ€λ₯κ° λ°μνκ² λ©λλ€.
μ΄κ²μ λ°©μ§νκΈ° μν΄μ WildCardλ₯Ό μ¬μ©νμ¬ Numberμ μμν΄λμ€λ‘λ§ μ΄λ£¨μ΄μ§ 리μ€νΈλ§ λμ μ λ°λλ‘ μ νμ λλ©΄ μ€λ₯λ₯Ό λ°©μ§ν μ μμ΅λλ€.<?> : λͺ¨λ ν΄λμ€λ μΈν°νμ΄μ€ λͺ¨λ μ¬ μ μμ΅λλ€.
<? extends μμνμ > : μμνμ μ μμν΄λμ€λ§ κ°λ₯ν©λλ€.
<? super νμνμ > : νμνμ μ λΆλͺ¨ν΄λμ€λ§ κ°λ₯ν©λλ€.
T extends vs ? extends
λ°μ΄λλ νμ κ³Ό μμΌλμΉ΄λλ₯Ό 곡λΆνλ©΄μ λ κ°μ§μ μ°¨μ΄μ μ΄ κΆκΈνμμ΅λλ€. μ μ λμΌνκ² μ§λ¬Έν κΈμμ λ΅λ³ λ°μ λ΄μ©μΌλ‘ μμ±νμμ΅λλ€.
private static <T extends Number> void processList(List<T> someList) { T n = someList.get(0); someList.add(1,n); //addition allowed. } private static void processList2(List<? extends Number> someList) { Number n = someList.get(0); //someList.add(1,n);//Compilation error. Addition not allowed. processList(someList);//Helper method for capturing the wildcard }
- λ°μ΄λλ νμ μ 맀κ°λ³μλ elementλ₯Ό μΆκ°ν μ μμ§λ§, μμΌλμΉ΄λμμλ λΆκ°λ₯ν©λλ€.
- λ°μ΄λλ νμ μ TλΌλ νμ λ³μλ₯Ό κ°μ§κ³ μμ΄ λ©μλ λ΄μμ Tλ₯Ό μ μνκ³ T λ΄λΆ ν΄λμ€μ λ©μλλ₯Ό νΈμΆνλ λ±μ μμ μ μνν μ μμ§λ§ μμΌλμΉ΄λμμλ νμ μ λν νΈλ€μ΄ μκΈ° λλ¬Έμ μμ μ μνν μ μμ΅λλ€.
- μ°Έμ‘°(https://stackoverflow.com/questions/38944896/difference-between-bounded-type-parameter-t-extends-and-upper-bound-wildcard)
Erasure
μ λ€λ¦ νλ‘κ·Έλλ°μμ μΌλ°μ μΈ λμμ μννκΈ° μν΄μ μ»΄νμΌλ¬κ° μ»΄νμΌ νμμ μ λ€λ¦ 맀κ°λ³μλ₯Ό μ€μ ν΄λμ€λ‘ λ°κΎΈλ type erasureλ₯Ό μ μ©ν©λλ€. type erasureλ μΆκ° ν΄λμ€λ₯Ό μμ±νμ§ μκ³ λ°νμ μ μ€λ²ν€λκ° μΌμ΄λμ§ μλλ‘ νκ² ν΄μ£Όλ νλ‘μΈμ€μ λλ€. μ΄λ‘ μΈν΄ μ λ€λ¦ νλ‘κ·Έλλ°μμμ νμ μμ μ±μ κ°λ ₯νκ² λ³΄μ₯ν©λλ€.
Type Erasure rules
- bounded typeμΌλ‘ 맀κ°λ³μλ₯Ό μ¬μ©ν κ²½μ°λ Generic typeμ bounded typeμΌλ‘ λ³κ²½ν©λλ€.
- λ°μ΄λ λμ§ μμλ€λ©΄ Generic typeμ Objectλ‘ λ°κΏλλ€.
- νμ μμ μ±μ 보μ₯νκΈ° μν΄ type castλ₯Ό μΆκ°ν©λλ€.
- νμ₯λ generic typeμμ λ€νμ±μ μ μ§νκΈ° μν bridge methodλ₯Ό μ€νν©λλ€.
- μ°Έμ‘°(https://www.tutorialspoint.com/java_generics/java_generics_quick_guide.htm)
public class Example { public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); Box<Double> doubleBox = new Box<Double>(); integerBox.add(new Integer(10)); doubleBox.add(new Double(10.0)); System.out.printf("Integer Value :%d\n", integerBox.get()); System.out.printf("Double Value :%s\n", doubleBox.get()); } } class Box<T extends Number> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } }
λ€μμ μ λ€λ¦μ μ΄μ©ν μ½λμ λλ€.
public static void main(String[] args) { Box integerBox = new Box(); Box doubleBox = new Box(); integerBox.add(new Integer(10)); doubleBox.add(new Double(10.0)); System.out.printf("Integer Value :%d\n", integerBox.get()); System.out.printf("Double Value :%s\n", doubleBox.get()); } } class Box { private Number t; public void add(Number t) { this.t = t; } public Number get() { return t; } }
μλ° μ»΄νμΌλ¬λ Erasure ruleμ λ§κ² generic typeμ μ€μ ν΄λμ€λ‘ λ°κΎΈκ² λκ³ , λ€μ μ½λμ κ°μ λ°μ΄νΈμ½λλ₯Ό μμ±νκ² λ©λλ€.
λ°μν'Android > Java' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Java] λμμΈ ν¨ν΄(Strategy ν¨ν΄) (0) 2021.05.11 [Java] λλ€μμ΄λ? (0) 2021.03.21 [Java] Java IO, NIO (0) 2021.02.22 [Java] Annotation, Meta dataλ? (0) 2021.02.19 [Java] Enumμ΄λ? (0) 2021.02.14