泛型是JDK5.0之后推出的新特性,泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的,运行阶段泛型是不起作用的。

使用泛型的好处


1) 集合中存储的元素类型统一了。
2)集合中取出来的元素类型是泛型指定的类型,不需要进行大量的“向下转型”。

泛型的缺点

 
1)集合存储的元素缺少多样性。
   大多数业务中,集合中的元素类型还是统一的,所以这种功能还是被大家认可的。

案例

首先创建一个JAVA项目,在项目中创建一个类,类里面写上主方法,然后在这个类中再创建三个类,其中一个类是剩下两个类的父类。每个类里都写上一个方法,然后子类重写父类的eat方法。

image.png

image.png

主方法中创建一个List集合先不指定泛型,用list.add方法将我们创建的类的对象存入到集合中,因为是三个不同的类所以存入到集合中的元素类型也是不一样的,接下来我们用调用list的迭代器方法来遍历集合。

image.png

可以看到it.next方法返回的对象是一个Object类,而这个类中并没有提供eat方法。所以我们调用不了编译器报错。要想解决这个方法我们可以使用向下转型(强制转换)。

image.png

这样把it.next返回的类型强制转换成Animals类就可以调用里面的eat方法了,可以看到控制台输出了三个eat的方法,分别是三个不同类的,因为子类继承了父类然后重写了方法(不重写的话默认是父类的eat方法体内容),我们之前通过list.add添加了三个类的对象再集合中所以遍历输出了三个类的eat方法。

image.png

如果要使用泛型我们需要再集合上用<类型> 尖括号里面写上你要指定的集合中能存储的元素类型。
迭代器上也要写上你要指定遍历的元素类型。

image.png

这样你的List集合中能存储的元素类型就是你用泛型指定的类型,
因为迭代器上用了泛型所以遍历的也是集合里面这个泛型指定的类型,it.next中返回的类型就是你指定的类型,我们之所以指定Animals而不是指定它的子类是因为如果你指定其中一个子类那么剩下的Animals中的子类就不能存储到元素中编译器会报错因为不是同个类型。

image.png

使用了泛型后迭代器循环中就不需要把Object类强制转换成Animals了,因为it.next默认返回的类型就是你指定的类型。

image.png

image.png

如果要输出子类的特有方法我们还是需要向下转型将Animals转换成它的子类,无论是不是用泛型,这样才不会编译报错,因为是特有方法,父类中并没有写这个方法,这个方法是子类特有的所以,不能使用父类对象调用子类方法,只能向下转型。

image.png

image.png

在JDK8之后引入了自动类型推断机制(也称为钻石表达式)

也就是ArrayList后面的尖括号里可以不写类型了,它会自动推断,只有在JDK8之后才允许。因为这两个尖括号看起来像钻石所以也叫钻石表达式。

image.png

自定义泛型

自定义泛型的使用方法,创建一个类。类名后面写上泛型,这个泛型里的内容是个标识符可以随便写,一般写E(Element)和T(Type)。然后写上泛型后,类里的方法如果有参数就必须是这个类上的泛型的标识符,也可以没有参数,如果有返回类型的话也必须是这个泛型的标识符,也可以是void。

image.png

可以看到当我们在方法里new对象时如果加上泛型那么这个泛型就会传到我们在类上写的泛型,就会传到方法的类型参数或者返回类型上,这样就是自定义泛型。在创建GenericaTest对象时在写上泛型String这样传到类中,就会把E改成String,方法里的参数E o 也就变成String o 方法返回值上的 public E run()就变成public String run()。在调用这两个方法,add()中需要传入一个String 类型参数否则会报错,而run()方法返回值则可以是String或者Object因为Object是所有没有主动继承类的超级父类。


仓悬
19 声望2 粉丝