Java Generics (Generics) is a new feature introduced in JDK5, which allows the use of type parameters (Type Parameter) when defining classes and interfaces. The declared type parameters are replaced with specific types when used. The most important application of generics now is in the new collection class framework in JDK5, where Map and List are used. The advantages are self-evident. We can extend more classes horizontally. The disadvantages are actually its advantages, because when we use generic classes, we need to be very clear about the purpose of our code and cannot use errors. type.
The most basic generic class
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()); } }
Multiple generic types
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()); } }
Use wildcard "?" in method parameters
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 failed
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; } }
The use of generics in interfaces
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()); } }
The use of wildcards and extends, 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); } }
Method generics, multiple generics in methods
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); } }
The generic type passed in or returned in the method is determined by the parameter type set when calling the method
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; } }
Make the two parameter types passed in the method consistent
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()); } }
Generic, Variable parameters, similar to the Arguments object 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 + " ,"); } } }
Generic nesting: use generic classes as parameters; determine the return value based on the return value type
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); } }
More java generics For articles related to learning examples, please pay attention to the PHP Chinese website!