根据《Java编程思想 (第4版)》中的描述,泛型出现的动机在于:有许多缘由促成了泛型的出现,而最引人注意的一个缘由,就是为了建立容器类。java
泛型类编程
容器类应该算得上最具重用性的类库之一。先来看一个没有泛型的状况下的容器类如何定义:dom
public class Container { private String key; private String value; public Container(String k, String v) { key = k; value = v; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
Container类保存了一对key-value
键值对,可是类型是定死的,也就说若是我想要建立一个键值对是String-Integer
类型的,当前这个Container
是作不到的,必须再自定义。那么这明显重用性就很是低。ide
固然,我能够用Object
来代替String
,而且在Java SE5以前,咱们也只能这么作,因为Object
是全部类型的基类,因此能够直接转型。可是这样灵活性仍是不够,由于仍是指定类型了,只不过此次指定的类型层级更高而已,有没有可能不指定类型?有没有可能在运行时才知道具体的类型是什么?ui
因此,就出现了泛型。this
public class Container<K, V> { private K key; private V value; public Container(K k, V v) { key = k; value = v; } public K getKey() { return key; } public void setKey(K key) { this.key = key; } public V getValue() { return value; } public void setValue(V value) { this.value = value; } }
在编译期,是没法知道K
和V
具体是什么类型,只有在运行时才会真正根据类型来构造和分配内存。能够看一下如今Container
类对于不一样类型的支持状况:code
public class Main { public static void main(String[] args) { Container<String, String> c1 = new Container<String, String>("name", "findingsea"); Container<String, Integer> c2 = new Container<String, Integer>("age", 24); Container<Double, Double> c3 = new Container<Double, Double>(1.1, 2.2); System.out.println(c1.getKey() + " : " + c1.getValue()); System.out.println(c2.getKey() + " : " + c2.getValue()); System.out.println(c3.getKey() + " : " + c3.getValue()); } }
输出:接口
name : findingsea age : 24 1.1 : 2.2
泛型接口内存
在泛型接口中,生成器是一个很好的理解,看以下的生成器接口定义:get
public interface Generator<T> { public T next(); }
而后定义一个生成器类来实现这个接口:
public class FruitGenerator implements Generator<String> { private String[] fruits = new String[]{"Apple", "Banana", "Pear"}; @Override public String next() { Random rand = new Random(); return fruits[rand.nextInt(3)]; } }
调用:
public class Main { public static void main(String[] args) { FruitGenerator generator = new FruitGenerator(); System.out.println(generator.next()); System.out.println(generator.next()); System.out.println(generator.next()); System.out.println(generator.next()); } }
能够看到方法的参数完全泛化了,这个过程涉及到编译器的类型推导和自动打包,也就说原来须要咱们本身对类型进行的判断和处理,如今编译器帮咱们作了。这样在定义方法的时候没必要考虑之后到底须要处理哪些类型的参数,大大增长了编程的灵活性。
再看一个泛型方法和可变参数的例子:
输出和前一段代码相同,能够看到泛型能够和可变参数很是完美的结合。
以上,泛型的第一部分的结束