java 泛型使用方法

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

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>() {
		@Override
		public Object apply(Object arg) {
			return arg;
		}
	};
	
	private static final UnaryFunction<App<String>> APP_FUNCTION = new UnaryFunction<App<String>>() {
		@Override
		public 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>>() {
		@Override
		public 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>() {
		@Override
		public 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<? extends Annotation> extendClass = (Class<? extends Annotation>) 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;
}












猜你喜欢

转载自blog.csdn.net/menghu07/article/details/70176771