JAVA中的泛型
[写在开始]
以前在博彦给微软做外包的时候,做的是浏览器的测试,接触到C#相关知识点比较多,经常学习相关知识,对泛型有略微了解,但不深入,只知道方法的参数可以为任意类型,前天看了篇文章,总结的比较好,一直都觉得泛型这东西很好,今天再对JAVA中的泛型总结总结。
[扫盲]
Java泛型(Generics)是JDK5开始引入的一个新特性,允许在定义类和接口的时候使用类型参数(Type Parameter)。声明的类型参数在使用时用具体的类型来替换,现在泛型最主要的应用是在JDK5中的新集合类框架中,Map, List均有用到。其中的优点不言而喻,我们可以横向扩展更多的类,缺点呢,其实也就是他的优点,因为这需要我们在使用泛型类的时候,要很清楚自己的代码目地,不能使用错误的类型。
[看例子学习]
最基本的泛型类
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()); } }
多个泛型类型
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()); } }
在方法参数中使用通配符"?"
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); } }
向上转型失败
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; } }
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()); } }
通配符和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); } }
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); } }
方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定
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; } }
让方法中传入两个参数类型保持一致
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()); } }
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 + " ,"); } } }
泛型嵌套:使用泛型类做为参数;根据返回值类型确定返回值
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); } }
参考资料:
http://www.cnblogs.com/sharpxiajun/archive/2013/05/19/3087179.html
http://blog.csdn.net/jinuxwu/article/details/6771121
http://luckykapok918.blog.163.com/blog/static/2058650432012102341548827/
http://sharewind.iteye.com/blog/1622164
http://love-love-l.blog.163.com/blog/static/21078304201081312858230/
http://www.cnblogs.com/panjun-Donet/archive/2008/09/27/1300609.html
Thinking in Java