Java – 泛型

简介

泛型是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查

泛型的格式: <数据类型>

注意:泛型只能支持引用数据类型

 

泛型的细节

1.统一数据类型

2.把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来。

3.泛型中不能写基本数据类型

4.指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型

5.如果不写泛型,类型默认是Object

 

泛型类

当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类

修饰符 class 类名<类型>{}
public class ArrayList<E>{}

此处E可以理解为变量,但是不是用来记录数据的,而是记录类据类型的,可以为任意名。

举例:定义一个泛型类

// 增加方法,使用泛型定义,这样当传入什么类型的数据时,它就是什么类型的
  public boolean add(E e){
    elementObjects[size] = e;
    return true;
  }
  
  // 取出数据时,也会返回这个类型的数据
  public E get(int index){
    // 因为存储数据时使用的是 Object[] 保存的,所以取出时也是 Object[] 的
    // 因此需要在传出时做一个类型强转,强转为泛型数据
    return (E) elementObjects[index];
  }

 

泛型方法

当我们只在类方法中需要使用泛型类型的时候,我们可以把类作为一个泛型类,泛型类可以在类的所有地方都使用泛型,但当我们只想在某个方法中使用泛型时,我们可以只在方法中单独定义泛型,我们只在方法中定义的泛型叫泛型方法。

修饰符 <E> 返回值 方法名(){}
public static <E> int get(){}
public static <E> boolean set(E e){}
注意,泛型 <E> 要在 修饰符后面,public 和 static 都是修饰符。

 

举例:定义一个泛型方法

// 增加方法,使用泛型定义,这样当传入什么类型的数据时,它就是什么类型的
 public <E> boolean add(E e){
  elementObjects[size] = e;
  return true;
 }

 // 取出数据时,也会返回这个类型的数据
 public <E> E get(int index){
  // 因为存储数据时使用的是 Object[] 保存的,所以取出时也是 Object[] 的
  // 因此需要在传出时做一个类型强转,强转为泛型数据
  return (E) elementObjects[index];
 }

 

泛型接口

当这个接口的类型是不明确的,可以定义泛型接口

修饰符 interface 接口名<类型> {}
public interface List<E>{}

 

泛型接口应用-实现类明确

当接口定义了泛型时,实现类可以明确的实现类型方法,可以在实现接口时明确传递接口类型

实现类明确表示会实现类型为 String 的接口方法
通过定义明确的类型方法后,所有重写接口方法上用到的泛型都变成明确类型
public class ArrayList implements Line<String> {
    public void add(String e)
}

 

泛型接口应用-实现类不明确

如果实现类中,依然对泛型接口中的类型不明确时,实现类可以继承接口中的泛型,这样在接口中需要使用到泛型类型中的方法,依然会采用泛型定义

如果实现类的类型依然不确定,可以在实现类中继续定义泛型就可以
后面的重写方法依然会使用泛型类进行计算
public class ArrayList<E> implements Line<E> {
     public void add(E e)
}

 

 

泛型继承性

对于泛型来说,泛型是不具备继承性的,但数据具备继承性,比如

定义三个类,Zi 类 继承 Fu 类,Fu 类 继承 Ye 类
class Ye {}
class Fu extends Ye {}
class Zi1 extends Fu {}

定义一个需要传入指定泛型的方法
public static void method(ArrayList<Ye> list){ }

定义两个对象,一个实例 Ye类,一个实例 Fu类
ArrayList<Ye> ye = new ArrayList<>();
ArrayList<Fu> fu = new ArrayList<>();

此时调用method传入 Ye 类 的对象是被允许的
method(ye);

但是调用method传入 fu 类 的对象是不被允许的
method(fu);

method 中定义了传入的泛型类要求是 <Ye> 时,就只允许传入 <Ye> 的对象,即使是它的子类 Fu 类也是不被允许的。

 

但是当传入子类时可以具备继承性,比如下面

创建一个存储 Ye 类 的集合
ArrayList<Ye> ye = new ArrayList<>();

// 创建两个 Ye类 的子类 Fu 和 Zi
Fu f = new Fu();
Zi z = new Zi();

// 此时,Ye 类集合允许传入其子类的数据
ye.add(f);
ye.add(z);

总结:如果需要传入子类型的泛型类到带有 父类型的泛型类,是不被允许的,但如果把 子类 传递 父类 是被允许的(和多态一样)

 

泛型通配符

泛型可以传递任意类型,那当一些无关类也能被传入。

那我要如何限制,只允许某些类型能传入呢?

 

<?> 不限制类型

<?> 通配符和 <E> 是同样的功能, <E> 指的是任意类型,而 <?> 指的是通配类型,带有通配符功能,但是不写任部通配条件时,则和 <E> 是一样的

public <E> void method(ArrayList<E> e){}
等同于
public void method2(ArrayList<?> e){}

 

<? extends E> 限制继承子类

<? extends E> 表示可以传递 E类型 或者 E 所有的子类类型

public static void method(ArrayList<? extends Ye> e){ }

表示如果要调用 method 方法时,可以传入 Ye 类型的和所有其子类,即 Fu类和Zi 类都可以被传入,非 Ye 类子类的就不允许传入

 

当类是泛型类时,定义了泛型 E,此时方法中定义了 <? extends E> 表示,方法中只允许传入类型的子类或传入类本身的对象
public static void method(ArrayList<? extends E> e){ }

XXX<Fu> x = new XXX<>();
s.method(Fu类和Zi类)
s.method(不允许Ye类)

 

<? super E> 限制父类

<? super E> 表示可以传递 E类型 或者 E 所有的父类类型

public static  void method(ArrayList<? super Fu> e){ }

表示如果要调用 method 方法时,可以传入 Fu类型的所有父类,即 Ye 类 ,非Fu 类的父类不允许传入,如Zi类是Fu类的子类,就不允许被传入

当类是泛型类时,定义了泛型 E,此时方法中定义了 <? super E> 表示,方法中只允许传入类型的父类或传入类本身的对象
public static void method(ArrayList<? super E> e){ }

XXX<Fu> x = new XXX<>();
s.method(Fu类和Ye类)
s.method(不允许Zi类)

 

应用场景

1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口

2.如果类型不确定,但是能知道以后只能传递某个继承体系中的类,就可以泛型的通配符。

如果您喜欢本站,点击这儿不花一分钱捐赠本站

这些信息可能会帮助到你: 下载帮助 | 报毒说明 | 进站必看

修改版本安卓软件,加群提示为修改者自留,非本站信息,注意鉴别

THE END
分享
二维码
打赏
海报
Java – 泛型
简介 泛型是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查 泛型的格式: <数据类型> 注意:泛型只能支持引用数据类型   泛型的细节 1.统一数据类型 2.把运行时……
<<上一篇
下一篇>>