泛型:
我们查看API帮助文档可知,Collection接口的定义格式为Interface Collection,那么代表什么呢?E - 此集合中元素的类型 !为什么要用<>括起来呢?就是我们将要学习到的泛型。
学习思路:
泛型的通配符:
泛型中的通配符有四种:T、E、K V、?
泛型有以上四种定义格式;
T Java的类型的是一个形参!在方法声明的时候使用。一般指代泛型类。
E 通常用于规定集合中的元素类型。
K V 一般表示Java中Map集合的键值对。
==?==一般表示不确定的Java类型,这是一种无限的符号,代表任何类型都可以。是一个实参!在方法使用的时候直接调用,但是 ?不能作为元素类型添加值,也就是 ?只能在没有定义元素类型的时候接收不同类型的元素。
?一般只是接收某种数据类型,并不能作为返回值;
?extends XX:向下限定,E及其子类;
? super XX:向上限定,E极其父类。
(在后面详细讲解 ?请继续学习。)
在学习Collection集合的时候,我们了解到,集合可以存储任意类型的元素,那么我们如果在使用增强for循环遍历集合的过程中,不使用Object接收对象,而使用特定的元素类型,就会爆出ClassCastException异常,表示类型转换异常,类型不兼容;
public static void main(String[] args) {
//此处指定了Collection集合的类型为Integer,所以不能添加别的元素类型
Collection<Integer> num = new ArrayList();
num.add(123);
num.add(456);
num.add(789);
// num.add("123");在编译的时候都会报错
//我们定义了一个没有指定类型的Collection集合
Collection str = new ArrayList();
str.add("123");
str.add("456");
str.add("789");
//因为指定集合的元素类型<E>,只会在编译的时期判断,存入的内容类型
//在运行时会把元素类型都默认为Object类型,这就叫做“泛型的擦除”
num.addAll(str);
//在增强for循环的时候我们使用了Integer作为元素输出类型
//但是num集合中是存在String类型的元素的,所以会存在类型不兼容无法完成遍历
for (Integer in : num){
System.out.println(in);
}
}
泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
泛型类:
<数据类型> 此处的数据类型只能是引用类型。
好处:
A:把运行时期的问题提前到了编译期间 ;
B:避免了强制类型转换。
/*
* 泛型类:把泛型定义在类上
*/
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
/*
* 泛型类的测试
*/
public class ObjectToolDemo {
public static void main(String[] args) {
ObjectTool<String> ot = new ObjectTool<String>();//规范了数据的存储
ot.setObj(new String("江一燕"));
String s = ot.getObj();
System.out.println("姓名是:" + s);
ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
ot2.setObj(27);
Integer i = ot2.getObj();
System.out.println("年龄是:" + i);
}
}
泛型方法:
修饰符 <代表泛型的变量> 返回值类型 方法名 (参数){ }
//普通方法
//修饰符 返回值类型 方法名(参数){}
public int show(int i){
return i;
}
/*
* 泛型方法:把泛型定义在方法上
*/
public <T> Object show(T t) {
return t;
}
//定义一个泛型方法
//返回类型不应该明确,因为泛型方法的类型都不明确
//建议:Object 或者 T(泛型)
public <T> T show(T t){
return t;
}
//实现类
public class TestCollection {
public <T> Object show(T t){
return t;
}
public <T> T show2(T t){
return t;
}
public int show(int i){
return i;
}
public static void main(String[] args) {
System.out.println(new TestCollection().show(1111111111));
System.out.println(new TestCollection().show("2222222222"));
System.out.println(new TestCollection().show2(new Date()));
}
}
/*
1111111111
2222222222
Tue May 03 16:03:35 CST 2022
*/
泛型接口:
修饰符 interface 接口名<代表泛型的变量> { }
/*
* 泛型接口:把泛型定义在接口上
*/
public interface Inter<T> {
public abstract void show(T t);
}
//实现类在实现接口的时候
//第一种情况:已经知道该是什么类型的了
public class InterImpl implements Inter<String> {
@Override
public void show(String t) {
System.out.println(t);
}
}
//第二种情况:还不知道是什么类型的
public class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
//测试类
public static void main(String[] args) {
//第一种情况:实现类已经明确类型,实例化对象时必须与实现类中的类型一致
InterDemo<String> i = new InteImpl();//我在实现的时候,已经明确类型--String
i.show("aaa");
i.show("bbb");
//第二种情况:实现类也没有明确类型
InterDemo<Integer> ii = new InteImpl2<>();//我在实现的时间也没有给出明确
ii.show(11);
ii.show(22);
InterDemo<String> ii2 = new InteImpl2<>();//我在实现的时间也没有给出明确
ii2.show("11");
ii2.show("22");
}
}
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
关于 ?通配符:
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。此时只能接受数据,不能往该集合中存储数据。
/*
* 泛型高级(通配符)
* ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
* ? extends E:向下限定,E及其子类
* ? super E:向上限定,E极其父类
*/
public class Animal {
}
public class Dog extends Animal {
}
public class Cat extends Animal {
}
public class GenericDemo {
public static void main(String[] args) {
// 泛型如果明确的写的时候,前后必须一致
Collection<Object> c1 = new ArrayList<Object>();
//错误写法:
// Collection<Object> c2 = new ArrayList<Animal>();
// Collection<Object> c3 = new ArrayList<Dog>();
// Collection<Object> c4 = new ArrayList<Cat>();
// ?表示任意的类型都是可以的
Collection<?> c5 = new ArrayList<Object>();
Collection<?> c6 = new ArrayList<Animal>();
Collection<?> c7 = new ArrayList<Dog>();
Collection<?> c8 = new ArrayList<Cat>();
// ? extends E:向下限定,E及其子类,表示包括E在内的任何子类;
// Collection<? extends Animal> c9 = new ArrayList<Object>();
Collection<? extends Animal> c10 = new ArrayList<Animal>();
Collection<? extends Animal> c11 = new ArrayList<Dog>();
Collection<? extends Animal> c12 = new ArrayList<Cat>();
// ? super E:向上限定,E极其父类,表示包括E在内的任何父类;
Collection<? super Animal> c13 = new ArrayList<Object>();
Collection<? super Animal> c14 = new ArrayList<Animal>();
// Collection<? super Animal> c15 = new ArrayList<Dog>();
// Collection<? super Animal> c16 = new ArrayList<Cat>();
}
}
欢迎关注微信公众号:小红的成长日记,一起学Java!