Java Generics (Generics) ist eine neue Funktion, die in JDK5 eingeführt wurde und die Verwendung von Typparametern (Typparameter) beim Definieren von Klassen und Schnittstellen ermöglicht. Die deklarierten Typparameter werden bei Verwendung durch bestimmte Typen ersetzt. Die wichtigste Anwendung von Generika liegt jetzt im neuen Collection-Klassen-Framework in JDK5, wo Map und List verwendet werden. Die Vorteile liegen auf der Hand. Wir können mehr Klassen horizontal erweitern, denn wenn wir generische Klassen verwenden, müssen wir uns über den Zweck unseres Codes im Klaren sein und dürfen keine Fehler verwenden.
Die grundlegendste generische Klasse
package com.garinzhang.javabase.generic.e1; /** * 最基本的泛型类,类型由自己定义 * @author Garin Zhang * * @param <T> */ public class Point<T> { private T var; public T getVar() { return var; } public void setVar(T var) { this.var = var; } } package com.garinzhang.javabase.generic.e1; public class GenericExample { /** * @param args */ public static void main(String[] args) { Point<String> p = new Point<String> (); p.setVar("coder"); System.out.println(p.getVar()); } }
Mehrere generische Typen
package com.garinzhang.javabase.generic.e2; /** * 多个泛型类型,一般多个最好是以靠近T的字母,如S,R等 * @author Garin Zhang * * @param <T> * @param <S> */ public class Notepad<T, S> { private T key; private S value; public T getKey() { return this.key; } public S getValue() { return this.value; } public void setKey(T key) { this.key = key; } public void setValue(S value) { this.value = value; } } package com.garinzhang.javabase.generic.e2; public class GenericExample { /** * @param args */ public static void main(String[] args) { Notepad<String, Integer> p = new Notepad<String, Integer> (); p.setKey("coder"); p.setValue(99999); System.out.println("key: " + p.getKey()); System.out.println("value: " + p.getValue()); } }
Verwenden Sie den Platzhalter „?“ in Methodenparametern
package com.garinzhang.javabase.generic.e3; /** * 该例子关键在main方法里 * @author Garin Zhang * * @param <T> */ public class Info<T> { private T key; public T getKey() { return this.key; } public void setKey(T key) { this.key = key; } @Override public String toString() { return this.key.toString(); } } package com.garinzhang.javabase.generic.e3; /** * 在方法参数中使用通配符 * @author Garin Zhang * */ public class GenericExample { /** * @param args */ public static void main(String[] args) { Info<String> i = new Info<String>(); i.setKey("coder"); fun(i); Info<Integer> j = new Info<Integer>(); j.setKey(9999); fun(j); } public static void fun(Info<?> temp) { System.out.println("Content: " + temp); } }
Upcast fehlgeschlagen
package com.garinzhang.javabase.generic.e4; /** * 该例子关键在main方法里 * @author Garin Zhang * * @param <T> */ public class Info<T> { private T key; public T getKey() { return this.key; } public void setKey(T key) { this.key = key; } @Override public String toString() { return this.key.toString(); } } package com.garinzhang.javabase.generic.e4; public class GenericExample { /** * @param args */ public static void main(String[] args) { Info<String> strEg = new Info<String>(); Info<Object> objEg; // 编译错误"Type mismatch: cannot convert from Info<String> to Info<Object>" // 向上转型失败,String -> Object // objEg = strEg; } }
Verwendung von Generika in Schnittstellen
package com.garinzhang.javabase.generic.e5; /** * 该例子关键在main方法里 * @author Garin Zhang * * @param <T> */ interface Info<T> { public T getVar(); } package com.garinzhang.javabase.generic.e5; /** * 泛型类 * @author Garin Zhang * * @param <T> */ public class InfoImpl<T> implements Info<T> { private T var; public InfoImpl(T var) { this.setVar(var); } public void setVar(T var) { this.var = var; } public T getVar() { return this.var; } } package com.garinzhang.javabase.generic.e5; /** * 非泛型类 * @author Garin Zhang * * @param <T> */ public class InfoImpl1 implements Info<String> { private String var; public InfoImpl1(String var) { this.setVar(var); } public void setVar(String var) { this.var = var; } public String getVar() { return this.var; } } package com.garinzhang.javabase.generic.e5; public class GenericExample { /** * @param args */ public static void main(String[] args) { Info<String> strEg = new InfoImpl<String>("coder"); System.out.println("Content: " + strEg.getVar()); Info<String> strEg1 = new InfoImpl1("coder1"); System.out.println("Content: " + strEg1.getVar()); } }
Platzhalter und Erweiterungen, Verwendung von Super
package com.garinzhang.javabase.generic.e6; /** * 该例子关键在main方法里 * @author Garin Zhang * * @param <T> */ public class Info<T> { private T key; public T getKey() { return this.key; } public void setKey(T key) { this.key = key; } @Override public String toString() { return this.key.toString(); } } package com.garinzhang.javabase.generic.e6; public class GenericExample { /** * @param args */ public static void main(String[] args) { Info<String> strEg = new Info<String>(); strEg.setKey("coder"); // 编译报错"The method fun(Info<? extends Number>) in the type GenericExample is not applicable for the arguments (Info<String>)" // upTypeLimit(i); // 使用Integer,Number类型均可以 Info<Integer> intEg = new Info<Integer>(); intEg.setKey(9999); upTypeLimit(intEg); // 编译报错"The method downTypeLimit(Info<? super String>) in the type GenericExample is not applicable for the arguments (Info<Integer>)" // downTypeLimit(intEg); // 由于使用的是super,downTypeLimit只能接收String本身和Object // 查看了String的继承关系,没有继承其他类,只有Object downTypeLimit(strEg); Info<Object> objEg = new Info<Object>(); objEg.setKey(999); downTypeLimit(objEg); } /** * <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 * @param temp */ public static void upTypeLimit(Info<? extends Number> temp) { System.out.println("Content: " + temp); } /** * <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object * 在此例中,表示T只能为Object或String,因为String只继承于Object * @param temp */ public static void downTypeLimit(Info<? super String> temp) { System.out.println("Content: " + temp); } }
Methodengenerika, mehrere Generika in der Methode
package com.garinzhang.javabase.generic.e7; /** * 方法泛型,方法里面多个泛型 * @author Garin Zhang * * @param <T> */ public class Info { /** * 格式:方法修饰付 <以逗号隔开的类型列表>返回值类型方法名(参数列表) * 例如:public <T, S> T fun(T t, S s) * @param t * @param s * @return */ public <T, S> T fun(T t, S s) { System.out.println(s.toString()); return t; } } package com.garinzhang.javabase.generic.e7; public class GenericExample { /** * @param args */ public static void main(String[] args) { Info info = new Info(); String str = info.fun("coder", "print second generic param"); System.out.println(str); int i = info.fun(30, "print second param again"); System.out.println(i); } }
Der in der Methode übergebene oder zurückgegebene generische Typ wird durch den beim Aufruf der Methode festgelegten Parametertyp bestimmt
package com.garinzhang.javabase.generic.e8; /** * extends * @author Garin Zhang * * @param <T> */ public class Info<T extends Number> { private T var; public T getVar() { return this.var; } public void setVar(T var) { this.var = var; } @Override public String toString() { return this.var.toString(); } } package com.garinzhang.javabase.generic.e8; public class GenericExample { /** * @param args */ public static void main(String[] args) { Info<Integer> intEg = fun(30); // 这里类型已经确定为Integer System.out.println(intEg.getVar()); } /** * 方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定 * @param param * @return */ public static <T extends Number> Info<T> fun(T param) { Info<T> temp = new Info<T>(); temp.setVar(param); return temp; } }
Die Methode muss übergeben werden. Die beiden Parametertypen sind konsistent
package com.garinzhang.javabase.generic.e9; /** * 查看main * @author Garin Zhang * * @param <T> */ public class Info<T> { private T var; public T getVar() { return this.var; } public void setVar(T var) { this.var = var; } @Override public String toString() { return this.var.toString(); } } package com.garinzhang.javabase.generic.e9; public class GenericExample { /** * @param args */ public static void main(String[] args) { Info<String> i1 = new Info<String>(); i1.setVar("Hello"); Info<String> i2 = new Info<String>(); i2.setVar("Coder"); Info<Integer> i3 = new Info<Integer>(); i3.setVar(999); add(i1, i2); //编译错误"The method add(Info<T>, Info<T>) in the type GenericExample is not applicable for the arguments (Info<String>, Info<Integer>)" // add(i1, i3); } /** * 方法中传入两个参数类型必须一致 * @param param * @return */ public static <T> void add(Info<T> i1, Info<T> i2) { System.out.println(i1.getVar() + ":" + i2.getVar()); } }
Generische, variable Parameter, ähnlich dem Arguments-Objekt in JavaScript
package com.garinzhang.javabase.generic.e10; public class GenericExample { /** * @param args */ public static void main(String[] args) { Integer i[] = fun(1, 2, 3, 4, 5, 6); fun2(i); } public static <T> T[] fun(T... arg) { return arg; } public static <T> void fun2(T param[]) { System.out.println("generic array: "); for(T t : param) { System.out.println(t + " ,"); } } }
Generische Verschachtelung: Verwenden Sie generische Klassen als Parameter; Bestimmen Sie den Rückgabewert basierend auf dem Rückgabewerttyp
package com.garinzhang.javabase.generic.e11; /** * 接受两个泛型类型 * @author Garin Zhang * * @param <T> */ public class Info<T, V> { private T var; private V value; public T getVar() { return this.var; } public void setVar(T var) { this.var = var; } public V getValue(){ return this.value; } public void setValue(V value) { this.value = value; } @Override public String toString() { return this.var.toString(); } } package com.garinzhang.javabase.generic.e11; /** * 接受1个泛型类型 * @author Garin Zhang * * @param <T> */ public class Demo<S> { private S info; public Demo(S info) { this.setInfo(info); } public void setInfo(S info) { this.info = info; } public S getInfo() { return this.info; } } package com.garinzhang.javabase.generic.e11; import java.util.List; import com.google.common.collect.Lists; public class GenericExample { /** * @param args */ public static void main(String[] args) { Demo<Info<String, Integer>> d; Info<String, Integer> i; i = new Info<String, Integer>(); i.setVar("Coder"); i.setValue(999); d = new Demo<Info<String,Integer>>(i); System.out.println("Content: " + d.getInfo().getVar()); System.out.println("Content: " + d.getInfo().getValue()); System.out.println(query(1, 2, 3, 4, 5).toString()); // [1, 2, 3, 4, 5] // 警告"Type safety: A generic array of Object&Comparable<?>&Serializable is created for a varargs parameter" System.out.println(query(1, 2, 3, "StringType").toString()); // [1, 2, 3, StringType] System.out.println(query("I ", "am ", "a ", "coder").toString());// [I , am , a , coder] List<String> list = Lists.newArrayList("I ", "am ", "a ", "coder"); System.out.println(list.toString()); // [I , am , a , coder] } /** * 通过返回值确定泛型类型,这个方法里面的返回值类型,是由方法的定义自动生成的 * @param elements * @return */ public static <E> List<E> query(E... elements) { // https://github.com/exitsoft/exit-web-framework/commit/1d2f1098a2a4b6abab175b793e2308aa8bd0ea16. // import com.google.common.collect.Lists; // <dependency> // <groupId>com.google.guava</groupId> // <artifactId>guava</artifactId> // <version>16.0.1</version> // </dependency> return Lists.newArrayList(elements); } }
Weitere Java-Generika-Lernbeispiele und verwandte Artikel finden Sie auf der chinesischen PHP-Website!