一.泛型介绍
(1) 是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
(2)泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
二.例子
我们这里有一个案例,我们创建一个集合,然后将new出来的不同对象放到同一个集合当中。我们注意到(1)行的obj只能是Object类型。所以我们如果想要调用Animal或者Cat或者Bird的方法,只能向下转型,而向下转型之前又要判断,比较麻烦。
package com.sdnu;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Beyong
* @Description generics
* @date 2021/07/06 18:32
*/
public class generics {
public static void main(String[] args) {
Cat c = new Cat();
Bird b = new Bird();
Collection myList = new ArrayList();
myList.add(c);
myList.add(b);
Iterator it = myList.iterator();
while(it.hasNext()){
Object obj = it.next();//**************************(1)
if(obj instanceof Animal){
Animal a = (Animal)obj;
a.animalMove();
}
if(obj instanceof Cat){
Cat a = (Cat)obj;
a.catchMouse();
}
if(obj instanceof Bird){
Bird a = (Bird)obj;
a.birdFly();
}
}
}
}
class Animal {
public void animalMove(){
System.out.println("Animal is moving");
}
}
class Cat extends Animal {
public void catchMouse(){
System.out.println("Cat catch mouse");
}
}
class Bird extends Animal {
public void birdFly(){
System.out.println("Bird is fly");
}
}
三.引入泛型
针对上面例子的问题,我们引入泛型,如(2)所示,我们指定了集合中的类型为Animal,所以存储在该集合中的所有元素均为Animal.
package com.sdnu;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Beyong
* @Description generics
* @date 2021/07/06 18:32
*/
public class generics {
public static void main(String[] args) {
Cat c = new Cat();
Bird b = new Bird();
Collection<Animal> myList = new ArrayList<Animal>();//***(2)
myList.add(c);
myList.add(b);
Iterator<Animal> it = myList.iterator();
while(it.hasNext()){
Animal a = it.next();
a.animalMove();
if( a instanceof Cat){
Cat a1 = (Cat)a;
a1.catchMouse();
}
if( a instanceof Bird){
Bird a1 = (Bird)a;
a1.birdFly();
}
}
}
}
class Animal {
public void animalMove(){
System.out.println("Animal is moving");
}
}
class Cat extends Animal {
public void catchMouse(){
System.out.println("Cat catch mouse");
}
}
class Bird extends Animal {
public void birdFly(){
System.out.println("Bird is fly");
}
}
四.泛型优缺点
优点:
集合中的存储元素统一。
集合中取出的元素的类型都是泛型指定的类型,减少了向下转型。
缺点:
导致集合中的元素多样性减少。
五.类型自动推断
在JDK8.0之后,我们的泛型可以使用自动类型判断机制,也称"钻石表达式"。
简单来说,就是上面例子的(2)可以改为如下
Collection myList = new ArrayList<>();//***(2)
后面<>中的参数类型能根据前面推出。
六.泛型方法
我们可以写一个泛型方法,在方法声明的返回值类型前加一个<>,在其中添加一个标识符,比如下面的E(不是关键字,任取都可以,只是一般来说,E代表Element,T代表Type),在泛型中可以声明多个类型参数。为了指定两个或更多个类型参数,只需要使用逗号分隔参数列表即可。
package com.sdnu.generics;
/**
* @author Beyong
* @Description genericsMethod
* @date 2021/07/07 14:18
*/
public class genericsMethod {
public static <E> void printElement( E[] object){
for(E element : object){
System.out.print(element);
}
System.out.println("");
}
public static void main(String[] args) {
Integer[] integerObject = {1,2,3,4,5,6};
Double[] doubleObject = {1.0,2.0,3.0,4.0,5.0,6.0};
String[] stringObject = {"kk", "mm", "ll", "pp"};
printElement(integerObject);
printElement(doubleObject);
printElement(stringObject);
}
}
七.泛型类
与泛型方法类似,我们在类名后面加类型参数声明部分。
package com.sdnu.generics;
/**
* @author Beyong
* @Description genericsTest
* @date 2021/07/07 12:27
*/
public class Test1<T> {
public void methodTest (T temp) {
System.out.println(temp);
}
public static void main(String[] args) {
Test1<String> object = new Test1<>();
object.methodTest("kkkkk");
}
}
八.泛型接口
既然类可以使用泛型,那么接口当然也可以使用泛型。
package com.sdnu.generics;
/**
* @author Beyong
* @Description genericsInterface
* @date 2021/07/07 16:30
*/
public class Test2 {
public static void main(String[] args) {
Cat object = new Cat();
String s = object.move("myCat");
System.out.println(s);
}
}
interface Animal <T>{
T move(T t);
}
class Cat implements Animal<String>{
public String move(String s){
return s + "catch mouse";
}
}
九.边界限定
类型的上界,格式为:<? extends T>,即类型必须为T类型或者T子类
如下面的例子
类型的下界,格式为:<? super T>,即类型必须为T类型或者T的父类
如下面的例子
作者:台北的雨
出处:Beyong博客
github地址:https://github.com/beyong2019
本博客中未标明转载的文章归作者Beyong所有有,欢迎转载,但未经作者同意必须保留此段声明,且在文章明显位置给出原文连接,否则保留追究法律责任的权利。