泛型是JDK5引入的新特性,提供了编译时类型安全检测机制,把运行时期的问题提前到了编译时期,优化代码避免了强制类型转换
1. 泛型类
如果一个类名的后面有<E>,表示这个类是一个泛型类
集合类在定义时,并不知道需要存放的数据类型,所以需要使用泛型定义,直到创建具体对象时才需要确定数据类型
创建泛型类对象时,必须给泛型确定具体的数据类型
自定义泛型类:public class 类名<T>{ }
//盒子类,自定义泛型类
public class Box <E>{
private E element;
public E getElement() {
return element;
}
public void setElement(E element) {
this.element = element;
}
}
//测试类
public class Test {
public static void main(String[] args) {
//String类型
Box<String> box1 = new Box<>();
box1.setElement("落霞与孤鹜齐飞,秋水共长天一色");
System.out.println(box1.getElement());
//Integer类型
Box<Integer> box2 = new Box<>();
box2.setElement(24);
System.out.println(box2.getElement());
}
}
2. 泛型方法
调用泛型方法时,必须给泛型确定具体的数据类型
Java中泛型方法的使用(toArray):
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("落霞与孤鹜齐飞");
list.add("秋水共长天一色");
//将list集合转换为一个数组并返回
//如果是空参,返回的数组类型为Object
Object[] objects = list.toArray();
System.out.println(Arrays.toString(objects));
//泛型方法 toArray(T[] a)
String[] strings = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(strings));
}
自定义泛型方法:public <T> void show(T t){ }
//自定义一个泛型方法,传递一个集合和四个元素,将四个元素存入集合并返回集合
public class Demo {
public static void main(String[] args) {
ArrayList<String> list1 = addElement(new ArrayList<String>(),
"高渐离", "东皇太一",
"裴擒虎", "兰陵王");
System.out.println(list1);
ArrayList<Integer> list2 = addElement(
new ArrayList<Integer>(), 6, 6, 6 , 6);
System.out.println(list2);
}
public static <T> ArrayList<T> addElement(ArrayList<T> list,
T t1, T t2, T t3, T t4){
list.add(t1);
list.add(t2);
list.add(t3);
list.add(t4);
return list;
}
}
3. 泛型接口
定义格式:修饰符 interface 接口名<类型> { }
泛型接口的使用方式:
- 定义实现类时,定义和接口相同泛型,创建实现类对象时再明确泛型的具体类型
- 定义实现类时,直接明确泛型的具体类型
public class Demo {
public static void main(String[] args) {
GenericityImpl1<String> stringGenericity = new GenericityImpl1<>();
stringGenericity.method("落霞与孤鹜齐飞,秋水共长天一色");
GenericityImpl2 genericityImpl2 = new GenericityImpl2();
genericityImpl2.method(18);
}
}
//泛型接口
interface Genericity<E>{
public void method(E e);
}
//实现类定义和接口相同泛型
class GenericityImpl1<E> implements Genericity<E>{
@Override
public void method(E e) {
System.out.println(e);
}
}
//定义实现类直接明确泛型的具体类型
class GenericityImpl2 implements Genericity<Integer>{
@Override
public void method(Integer integer) {
System.out.println(integer);
}
}
4. 类型通配符
类型通配符: <?>
- ArrayList<?>: 表示元素类型未知的ArrayList,它的元素可以匹配任何的类型
- 但是并不能把元素添加到ArrayList中了,获取出来的也是父类类型
类型通配符上限: <? extends 类型>
- ArrayListList <? extends Number>: 它表示的类型是Number或者其子类型
类型通配符下限: <? super 类型>
- ArrayListList <? super Number>: 它表示的类型是Number或者其父类型
public class GenericDemo4 {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
ArrayList<Number> list3 = new ArrayList<>();
ArrayList<Object> list4 = new ArrayList<>();
method(list1);
method(list2);
method(list3);
method(list4);
getElement1(list1);
getElement1(list2);//报错
getElement1(list3);
getElement1(list4);//报错
getElement2(list1);//报错
getElement2(list2);//报错
getElement2(list3);
getElement2(list4);
}
// 泛型通配符: 此时的泛型?,可以是任意类型
public static void method(ArrayList<?> list){}
// 泛型的上限: 此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(ArrayList<? extends Number> list){}
// 泛型的下限: 此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(ArrayList<? super Number> list){}
}
如有错误欢迎留言评论,及时更正。 5月30日 羽露风