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; } }
型在介面中的使用泛型和使用字元, super的使用
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()); } }
方法泛型,方法裡面多個泛型
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; } }
泛型,可變參數,類似於javascript裡的Arguments物件
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 + " ,"); } } }
更多java泛型學習範例相關文章請關注PHP中文網!