简单泛型

使用泛型可以处理多种类型的数据,增加了代码的灵活性。同时,数据类型的确定被推迟到编译阶段,因此编译阶段就可以完成检查,提前发现错误。本文通过例子来说明泛型的使用。

泛型简单使用

元组

元组:将一组对象打包放在了单一对象中,有点像java bean, 使用泛型可以很容易的构造多元元组出来。

二元组

public class TwoTuple<A,B> {
	public final A a;
	public final B b;

	public TwoTuple(A a, B b) {
		this.a = a;
		this.b = b;
	}
}

三元组

public class ThreeTuple<A, B, C> extends TwoTuple<A, B>{
	public final C c;
	public ThreeTuple<A a, B b, C c) {
		super(a, b);
		this.c = c
	}
}
创建一个栈
public class LinkedStack<T> {	
	private Node<T> head;
 	class Node<T>{
      	T element;
      	Node<T> next;
  	}

	public void push(T t) {
		Node<T> node = new Node<>();
		node.element = t;
		node.next = head;
		head = node;
	}

	public T pop() {
		if (head != null) {
			Node<T> node = head;
			head = node.next;
			return node.element;
		} else
			return null;
	}

	public static void main(String[] args) {
		LinkedStack<String> stack = new LinkedStack<String>();
		stack.push("aa");
		stack.push("bbb");
		System.out.println(stack.pop());
	}
}

类型推断

//正常写法
Map<String, String> map = new HashMap<String, String>();

//类型推断
Map<String, String> map = new HashMap<>();

类型推断只对赋值操作有校,编译器会自动推断出容器中存储的具体类型。

泛型擦除

擦除例子
public static void main(String[] args) {
    Class c1 = new ArrayList<Integer>().getClass();
    Class c2 =  new ArrayList<String>().getClass();
    System.out.println(c1 == c2);
}

上面的代码输出结果为true, ArrayList< Integer >ArrayList< String>会被认为是同一种类型。这看起来很奇怪,如果是同一种类型,那么其行为是一致,但事实上我们不能把一个字符串放入ArrayList< Integer >中。这是因为在使用泛型时,任何具体类型信息都会被擦除,你唯一知道的是你在使用一个对象。因此List<Stirng>List<String>在运行时事实上都是原生类型List。

泛型的擦除是将具体类型信息擦除成原始类型信息,如何实现这一操作请参考连接

擦除补偿

由于擦除将类型信息抹掉了,但在实际开发中又需要根据类型进行不同操作,如下所示:

public class Erased<T> {
	private final int SIZE = 100;
	public static void f(Object arg) {
		if (arg instanceof T) {}             // Compile Error
		T var = new T();                     // Compile Error
         T[] array = new T[SIZE];             // Compile Error
         T[] array2 = (T) new Oject[SIZE];    // Unchecked warning
	}
}

由于擦除,我们获取不同T的任何信息,因此也不能基于T进行相关的类型操作了。那怎么做呢,可以使用Class对象进行处理。

public class Erased<T> {
    private final int SIZE = 100;
    private final Class<T> kind;

    public Erased(Class<T> kind) {
        this.kind = kind;
    }

    public void f(Object arg) {
        System.out.println(kind.isInstance(arg));

        try {
            T var = kind.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
posted @ 2017-09-18 12:02  被罚站的树  阅读(182)  评论(0编辑  收藏  举报