20.不能实例化类型变量

1.TestMakePair2.java

package javacore.chapter8;

import java.util.function.Supplier;

public class TestMakePair2 {
	public static void main(String[] args) {
		// 1.接受Suppier<T>--它是一个函数式接口。表示无参数且返回类型为T的函数。
		/**
		 * 因为不能实例化类型变量,如:
		 * public Pair2 {first = new T();second = new T();}
		 * 所以最好的方式是让调用者提供一个构造器表达式.形式如下:
		 * @param constr
		 * @return
		 */
		Pair2<String> pair2 = Pair2.makePair(String::new);
		System.out.println(pair2.getFirst().length());

		/**
		 * public void makeT(){
			2.传统的方式是通过Class.newInstance方法来构造泛型对象.
			但由于细节过于复杂,T.class是不合法的.它会被擦除为Object.class.如下:
			Illegal class literal for the type parameter T
			T.class.newInstance();
		}
		 * 3.
		 * T.class是不合法的,但若API設計為如下形式卻可以
		 * reason:因為String.class是Class<String>的一個实例.
		 */
		Pair2<String> pair =  Pair2.makePair(String.class);
	}
}

class Pair2<T> {
	private T first;
	private T second;

	public T getFirst() {
		return first;
	}

	public void setFirst(T first) {
		this.first = first;
	}

	public T getSecond() {
		return second;
	}

	public void setSecond(T second) {
		this.second = second;
	}

	public Pair2(T first, T second) {
		this.first = first;
		this.second = second;
	}
	
	public static <T> Pair2<T> makePair(Supplier<T> constr) {
		return new Pair2<>(constr.get(), constr.get());
	}
	
	/**
	 * Cannot infer type arguments for Pair2<>
	 * 当函数头返回值为Pair时,无法推断,改为Pair2后可以推断.
	 * @param c1
	 * @return
	 */
	public static <T> Pair2<T> makePair(Class<T> c1){
		try {
			return new Pair2<>(c1.newInstance(),c1.newInstance());
		} catch (InstantiationException | IllegalAccessException e) {
			return null;
		}
	}
}


posted @ 2019-01-10 14:48  王杰涛  阅读(812)  评论(0编辑  收藏  举报