泛型指的就是广泛通用的类型
但泛型还有一种较为准确的说法就是为了参数化类型,或者说可以将类型当作参数传递给一个类或者是方法。
那么,如何解释类型参数化呢?
public class Cache {
Object value;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
假设 Cache 能够存取任何类型的值,于是,我们可以这样使用它。
Cache cache = new Cache();
cache.setValue(134);
int value = (int) cache.getValue();
cache.setValue("hello");
String value1 = (String) cache.getValue();
使用的方法也很简单,只要我们做正确的强制转换就好了。
但是,泛型却给我们带来了不一样的编程体验。
public class Cache<T> {
T value;
public Object getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
这就是泛型,它将 value 这个属性的类型也参数化了,这就是所谓的参数化类型。再看它的使用方法。
Cache<String> cache1 = new Cache<String>();
cache1.setValue("123");
String value2 = cache1.getValue();
Cache<Integer> cache2 = new Cache<Integer>();
cache2.setValue(456);
int value3 = cache2.getValue();
最显而易见的好处就是它不再需要对取出来的结果进行强制转换了。但,还有另外一点不同。
泛型除了可以将类型参数化外,而参数一旦确定好,如果类似不匹配,编译器就不通过。
上面代码显示,无法将一个 String 对象设置到 cache2 中,因为泛型让它只接受 Integer 的类型。
如果一个类被 的形式定义,那么它就被称为是泛型类。
那么对于泛型类怎么样使用呢?
public <T> void show(T t){
System.out.print(t);
} //这里的<T>就是用来定义()泛型类型的
package com.example.studyprocess;
import java.util.ArrayList;
public class Test <T>{
private String name;
public void eat(T t){
System.out.println("今晚我想吃"+t);
}
public <E> E run(E e){
System.out.println(e);
return e;
}
}
class Animal{
private String name;
public Animal(){
}
}
class ceyan{
public static void main(String[] args) {
Test<String> test=new Test<>();
test.eat("烤红薯");
Test<Integer> test1=new Test<>();
test1.eat(88);
test.run(new String("你好"));
test.run(new Animal());
// Animal animal=new Animal("狮子");
// System.out.println(animal);
}
}
编译器不会让它通过的。Sub 是 Base 的子类,不代表 List 和 List 有继承关系。
但是,在现实编码中,确实有这样的需求,希望泛型能够处理某一范围内的数据类型,比如某个类和它的子类,对此 Java 引入了通配符这个概念。
有人说,<?> 提供了只读的功能,也就是它删减了增加具体类型元素的能力,只保留与具体类型无关的功能。它不管装载在这个容器内的元素是什么类型,它只关心元素的数量、容器是否为空?我想这种需求还是很常见的吧。
有同学可能会想,<?> 既然作用这么渺小,那么为什么还要引用它呢?
个人认为,提高了代码的可读性,程序员看到这段代码时,就能够迅速对此建立极简洁的印象,能够快速推断源码作者的意图。