Java泛型
关于泛型的知识点
JDK5引入的特性,为了解决使用Object强转带来的可读性问题,泛型的本质是将变量的类型参数化
泛型只在编译阶段有效,运行时擦除
静态方法中不能使用类的泛型,因为泛型引用在实例化时定义,而静态资源在实例化之前
泛型方法可以是静态的,因为它的泛型是调用方法时确定的,而不是实例化类时确定的
泛型有三种使用方法:泛型类,泛型方法,泛型
异常类不能是泛型
泛型的使用
泛型类
public class Map<K,V>{
private K key;
private V value;
public Map(K key,V value){
this.key = key;
this.value = value;
}
public void setKey(K key){
this.key = key;
}
public K getKey(){
return key;
}
public void setValue(V value){
this.value = value;
}
public V getValue(){
return value;
}
}
public class Test{
public static void main(String[] args){
Map<String ,String> map = new Map<>("key","value");
}
}
//如果泛型类实例化时没有指名类的泛型,则默认为Object类
//建议实例化时要指名泛型
泛型接口
//接口
public interface Generator<T>{
public T next();
}
public interface Generator<T1,T2>{
public T1 next();
public T2 next();
}
//继承接口,接口是泛型,实现时将泛型参数确定
//实例化时不需要指明泛型
public class StringGenerator implements Generator<String>{
@Override
public String next(){
return "String";
}
}
//接口泛型未声明,实现类也要标注泛型
public class SonOfGenerator<T> implements Generator<T> {
parivate T next;
public SonOfGenerator(T next){
this.next = next;
}
public T next(){
return next;
}
}
//实现类部分保留接口的引用
public class SonOfGenerator2<T2> implements Generator2<String T2>{}
//接口确定了类型,但实现类又新定义了泛型引用
public class SonOfGenerator3<A,B> implements Generator2<Integer,String>{}
//接口泛型应用保留,实现类又新定义了泛型
public class SonOfGenerator4<T1,T2,A,B> implements Generator2<T1,T2>{}
//接口部分保留泛型引用,实现类又新定义泛型
public class SonOfGenerator5<T2,A,B> implements Generator2<Integer,T2>{}
//实例化
public class Test{
public static void main(String[] args){
Generator<String> generator = new SonOfGenerator<>("value");
Generaotr<String> generaotr2 = new StringGeneraotr();
}
}
泛型方法
public class Data<T>{
private T data;
//泛型方法的泛型参数和类泛型参数不同
public <E> List<E> getList(E[] arr){
ArrayList<E> list = ArrayList<E>();
for(e:arr){
list.add(e);
}
return list;
}
}
通配符: ?
通配符的使用
//通配符解决的问题
public class Test{
public void main(String[] args){
List<String> list1 = null;
List<Integer> list2 = null;
//下面语句编译时会报错
//list1 = list2;
//解决问题
List<?> list = null;
list = list1;
list = list2;
//通配符的泛型类不能添加数据,除了null
list。add(null);
//以下代码报错
//list.add("aa");
}
}
有限制的通配符
public class Test{
public static void main(String[] args){
//有限制的通配符
//?可以是子类,也可以是本类()
List<? extends Person> list1 = null;
//?可以是本类,也可以是父类
List<? super Person> list2 = null;
//Student extends Person
List<Person> list3 = new ArrayList<Person>();
List<Student> list4 = new ArrayList<Student>();
List<Object> list5 = new ArrayList<Object>();
//下列赋值 不报错
list1 = list3;
list1 = list4;
//下列赋值 报错
list1 = list5;
list2 = list3;
//下列赋值 不报错
list2 = list4;
list2 = list5;
//读取数据
list1 = list3;
Person person = list1.get(0);
//下列赋值 报错
Student student = list1.get(0);
list2 = list4;
Object obj = list2.get(0);
//下列赋值 报错, ?有可能比Person更大
//Person person = list2.get(0);
//写入数据
//下面代码 报错: ?可能是student的子类
//list1.add(new Student());
//不报错
list2.add(new Person());
//<? super Person> 限制传入对象必须是person及其父类,但传入数据可以是person子类
list2.add(new Student());
}
}