java 泛型使用方法

来源:互联网 发布:买了域名怎么解析 编辑:程序博客网 时间:2024/06/01 11:23

符号说明:<=>表示等价于 //!表示注释的代码是错误的

1 不可创建泛型数组

//! Object o = new List<String>[10];//! Object o = new E[10];//! Object o = new List<E>[10];// 上面3行代码是错误的

2 数组是协变的,int 不是Object的子类,所以int[]不是Object[]的子类型,但Integer[]是Object[]的子类型,即Integer[]类型变量可以赋值给Object[]

3 可变参数可以用数组赋值或多个参数赋值;而数组参数只能用数组赋值

public void varargs(int[] arg) {}public void callVarargs() {//!     varargs(1, 3);    varargs(new int[] {3, 3});}

4 可以声明泛型数组但不可以创建泛型数组,可以把泛型数组作为函数的参数(不会产生警告)或使用泛型可变参数(会有potential heap pollution警告,用@SafeVarargs已知警告)

5 泛型单例工厂,需要类型兼容即

package com.ape.effectivejava;import java.lang.reflect.Array;import java.util.ArrayList;import java.util.Collections;import java.util.HashSet;import java.util.List;/** * Hello world! * */public class App<E> {private static final UnaryFunction<Object> IDENTITY_FUCNTION = new UnaryFunction<Object>() {@Overridepublic Object apply(Object arg) {return arg;}};private static final UnaryFunction<App<String>> APP_FUNCTION = new UnaryFunction<App<String>>() {@Overridepublic App<String> apply(App<String> arg) {return arg;}};public static <T> UnaryFunction<T> identityFunction() {return (UnaryFunction<T>) IDENTITY_FUCNTION;}public static <T> UnaryFunction<T> appFunction() {return (UnaryFunction<T>) APP_FUNCTION;}    public static void main( String[] args )    {        System.out.println("Hello World!" );        UnaryFunction<String> sm = identityFunction();         System.out.println("string test: " + sm.apply("ff"));                UnaryFunction<Integer> im = identityFunction();        UnaryFunction<String> appByte = appFunction();        appByte.apply("ff");  //!这里会报错,因为类型不兼容String与App<String>        new HashSet();        App x = new App();        if (x instanceof Object) {        System.out.println("xx");        }        App[] arx = new App[10];        Object[] oarx = arx;//        ArrayList<String>[] fi = {new ArrayList()};        if (arx instanceof Object[]) {                }        App argx = new App();        argx.varargs(new int[]{3, 5});        new ArrayList<String>().toArray();        Class<?> cc = App[].class;        System.out.println("equals: " + (arx.getClass() == cc) + "");        ArrayList<String> list1 = new ArrayList<String>();        ArrayList<Integer> list2 = new ArrayList<Integer>();        reduce(list1, null, "");        reduce(list2, null, 1);    }        @SafeVarargs    //避免使用泛型可变参数public final void genericVariable(List<String>... args) {        }public void varargs(int... arg) {Object o = new int[10];}public static <T> T reduce(ArrayList<T> list, Function<T> f1, T init) {T[] es = null;es = (T[]) list.toArray();System.out.println("class type: " + init.getClass() + (init.getClass() == String.class) );T r = init;for (T e : es) {if (f1 != null) {r = f1.apply(r, e);}}return r;}public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {        T[] copy = (newType == (Object) Object[].class)            ? (T[]) new Object[newLength]            : (T[]) Array.newInstance(newType.getComponentType(), newLength);        System.arraycopy(original, 0, copy, 0,                         Math.min(original.length, newLength));        return copy;    }}interface Function<E> {E apply(E e1, E e2);}interface UnaryFunction<T> {T apply(T arg);}

6 深刻理解泛型中类型擦除的含义:

private static final UnaryFunction<App<String>> APP_FUNCTION = new UnaryFunction<App<String>>() {@Overridepublic App<String> apply(App<String> arg) {return arg;}};public static <T> UnaryFunction<T> identityFunction() {return (UnaryFunction<T>) APP_FUNCTION;}

或者代码如下

private static final UnaryFunction<Object> IDENTITY_FUCNTION = new UnaryFunction<Object>() {@Overridepublic Object apply(Object arg) {return arg;}};public static <T> UnaryFunction<T> identityFunction() {return (UnaryFunction<T>) IDENTITY_FUCNTION;}//使用方法public static void test() {    UnaryFunction<String> idString = identityFunction();    idString.apply("xx");}

//类型擦除补充

6.1 声明的类型是什么类型,类型推断时就是什么类型; A b = new B();  putFavorite(b, B.class); 推断出的泛型为A   //public static <T> void putFavorite(T instance, Class<T> type)

6.2 原始类型和泛型之间可以互相赋值 List<String> <= List 或 List <= List<String> 泛型之间List<?> <= List<String>, List<String> !<= List<?>

6.3 假定HashSet<Double>.class,HashSet<String>.class存在,那么就有HashSet<Double>.class == HashSet.class == HashSet<String>.class == new HashSet<Double>().getClass();  要点:所有HashSet<E>泛型的类对象对应同一个List.class

6.4 代码片段

package com.ape.effectivejava;import java.lang.annotation.Annotation;import java.lang.reflect.AnnotatedElement;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;public class GenericJava {public static void main(String[] args) {//testSet();typeInference();restrictIntegerString();rawHole();//!getFavorite(Integer.class);}/** * 把Integer对象放入HashSet!!! */public static void testSet() {HashSet hashSet = new HashSet();hashSet.add("string");HashSet intSet = hashSet;intSet.add(new Integer(12));System.out.println("intSet has: " + intSet); //intSet has: [string, 12]}private static Map, Object> favorites = new HashMap, Object>();public static  void putFavorite(T instance, Class type) {favorites.put(type, instance);}public static  T getFavorite(Class type) {return type.cast(favorites.get(type));}public static  void putFavorite2(T instance, F type) {}/** * 原生态漏洞,String实例和Integer类型对应,违背设计原则并且getFavorite会抛异常 */public static void rawHole() {Class integer = Integer.class;Class f = integer;Class g = f;String xx = "";putFavorite(xx, integer); //}public static void typeInference() {B b = new B();Object a = b;CharSequence cs = new String("");A aa = b;//putFavorite((HashSet) a, HashSet.class);putFavorite2(aa, cs);//!putFavorite(aa, B.class);//需要HashSet类型和HashSet实例,结果传入HashSet和HashSet实例HashSet hashInteger = new HashSet();Class hashClass = new HashSet().getClass();Class cL = List.class;System.out.println("HashSet.class == " + (HashSet.class == hashClass));HashSet xhi = (HashSet) hashClass.cast(hashInteger);HashSet h = hashInteger;HashSet xhfi = h;putFavorite(hashInteger, hashClass);}public static void restrictIntegerString() {List hi = Collections.checkedList(new ArrayList(), Integer.class);List rawList = hi;List stringList = rawList;stringList.add("fff");}public static void testAnnotatedElement(AnnotatedElement element) {Class c = GenericJava.class;Class extendClass = (Class) c;Annotation x = element.getAnnotation(extendClass);}}class A {}class B extends A {}
7 泛型中显示类型参数 Set<Number> f3f = App.<Number>union2(set5, set6);

Set<Integer> set5 = new HashSet<Integer>();Set<Double> set6 = new HashSet<Double>();Set<Number> f3f = App.<Number>union2(set5, set6);

8 无限制类型参数可以和无限制通配符相互替换,有限制类型参数可以和有限制通配符相互替换;有限制类型参数表示法

public static <T> void put(Set<T> set) {        }    public static void put2(Set<?> set1) {        }public static <T extends GenericTest> void putSet(Set<T> xx) {        }    public static void putSet2(Set<? extends GenericTest> xx) {        }


//正确代码

public static <T extends Object> T getSet(Set<T> xx) {
        return null;
  }

//下面代码错误

public static <T> T getSet(Set<T extends Object> xx) {
        return null;
}












0 0
原创粉丝点击