java泛型的一些常見用法
阿新 • • 發佈:2018-12-30
本文主要參考下面幾篇文章:
http://blog.csdn.net/seu_calvin/article/details/52230032
http://blog.csdn.net/orzlzro/article/details/7017435
http://sharewind.iteye.com/blog/1622164
https://www.zhihu.com/question/20400700
1、 泛型類(介面)的寫法以及繼承
// 類似java.util.function.Function public interface GenericInterface<T, R> { public R apply(T t); } // 類似java.util.stream.IntStream public interface InheritGeneric0 extends GenericInterface<String, Integer> { } // 類似java.util.function.UnaryOperator public interface InheritGeneric1<T> extends GenericInterface<T, T> { } // 類似java.util.HashMap public interface InheritGeneric2<T, R> extends GenericInterface<T, R> { } // JDK庫尚未找到類似的 public interface InheritGeneric3<V, T, R> extends GenericInterface<T, R> { public V apply2(T t, R r); }
2、泛型方法的寫法
public class Retryer<T> { private T value; private int id = 0; public Retryer() { } public Retryer(int id) { this.id = id; } public T getValue() { return value; } public void setValue(T value) { this.value = value; } public int getId() { return id; } public void setId(int id) { this.id = id; } } // 泛型的宣告:方法的修飾符(public,static,final,abstract等)之後, 返回值(void,int等)之前 public class SpecificClass { // 入參泛型,返回值非泛型 public <L, R> int sum(L[] left, R[] right) { return left.length + right.length; } // 入參非泛型,返回值泛型 public static <T> Retryer<T> build() { return new Retryer<T>(); } // 入參泛型,返回值泛型 public <L, R, V> Retryer<V> buildLength(L[] left, R[] right) { return new Retryer<V>(left.length + right.length); } // 限制泛型: 只能是某個類的子類或者只能是實現了某些介面的類 // <T extends Comparable> // <T extends Number&Serializable> // <T extends Comparable&Serializable> public <L extends Number, R extends Number> double add(L left, R right) { return left.doubleValue() + right.doubleValue(); } }
3、泛型的一些基本特性:不能例項化物件和陣列
import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public class GenericBasicFeature { public static void main(String[] args) { test1(); String[] stringArray = (String[]) Array.newInstance(String.class, 5); System.out.println("stringArray.length=" + stringArray.length); String[] stringArray2 = GenericBasicFeature.test2(5, String.class); System.out.println("stringArray2.length=" + stringArray2.length); } // 泛型只在編譯期有效 // http://blog.csdn.net/seu_calvin/article/details/52230032 public static void test1() { List<String> stringList = new ArrayList<String>(); stringList.add("aaa"); // 編譯報錯 // stringList.add(new Object()); // 執行時通過反射新增元素 try { Class clazz = stringList.getClass(); Method method = clazz.getMethod("add", Object.class); method.invoke(stringList, 100); } catch (Exception e) { e.printStackTrace(); } // [aaa, 100] System.out.println(stringList); } // java不支援建立泛型陣列 // http://blog.csdn.net/orzlzro/article/details/7017435 public static <T> T[] test2(int length, Class<T> newType) { // T t = new T(); 編譯錯誤 // T[] wrong = new T[length]; 編譯錯誤 // T[] newArray = (T[]) new Object[length]; 執行時ClassCastException // 參考Arrays.copyOf T[] newArray = (T[]) Array.newInstance(newType, length); return newArray; } }
4、泛型的super和extend的PECS原則
// PECS(Producer Extends Consumer Super)
public class Demo {
static class Food {
}
static class Fruit extends Food {
}
static class Apple extends Fruit {
}
public void testExtend() {
List<? extends Food> flist = new ArrayList<Food>();
flist.add(new Apple()); //compile error
flist.add(new Fruit()); //compile error
flist.add(new Object()); //compile error
Food fruit = flist.get(0); //ok
}
public void testSuper() {
List<? super Food> flist = new ArrayList<Food>();
flist.add(new Food()); //ok
flist.add(new Fruit()); //ok
flist.add(new Apple()); //ok
Food f = flist.get(0);// compile error
}
}
5、一種使用例子public class ExtendsContainer<T> {
private T data;
public ExtendsContainer(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public class Demo {
static class Food {
}
static class Fruit extends Food {
}
static class Apple extends Fruit {
}
public static void main(String[] args) {
ExtendsContainer<Food> food = new ExtendsContainer<Food>(new Food());
ExtendsContainer<Fruit> fruit = new ExtendsContainer<Fruit>(new Fruit());
ExtendsContainer<Apple> apple = new ExtendsContainer<Apple>(new Apple());
ExtendsContainer<String> string = new ExtendsContainer<String>("abc");
getDataNoLimit(food);
getDataNoLimit(fruit);
getDataNoLimit(apple);
getDataNoLimit(string);
getDataOnlyFood(food);
getDataOnlyFood(fruit);
getDataOnlyFood(apple);
getDataOnlyFood(string);
getDataAnyFood(food);
getDataAnyFood(fruit);
getDataAnyFood(apple);
getDataAnyFood(string);
}
public static void getDataNoLimit(ExtendsContainer<?> container) {
System.out.println("data:" + container.getData());
}
public static void getDataOnlyFood(ExtendsContainer<Food> container) {
System.out.println("data:" + container.getData());
}
public static void getDataAnyFood(ExtendsContainer<? extends Food> data) {
System.out.println("data :" + data.getData());
}
}