java 泛型

本文详细介绍了Java泛型的概念,包括泛型类、方法、接口的设计与使用,以及泛型的类型限定、协变和逆变等高级特性。通过实例讲解了泛型的本质和约束,帮助读者理解泛型在代码复用和类型安全方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型概念

泛型: Generic Programming:编写的代码可以被很多不同类型的对象使用。

泛型类:ArrayList, HashSet, HashMap等。
泛型方法:Collections.binarySearch, Arrays.sort等。
泛型接口:List, Iterator等。

泛型的本质:参数化类型,避免类型的转化,代码可以重复使用。

自定义泛型设计

  1. 泛型类:具有泛型变量的类,在类名后用< T>代替引入类型,直到创建对象的时候,确定具体的类型。

泛型类的定义
整个类都被泛化,包括变量和方法。

public class Interval<T>{
    private T upper;
    private T lower;

    public Interval(T upper, T lower){
        this.upper = upper;
        this.lower = lower;
    }
    public T getLower(){
        return lower;
    }
    public T getUpper(){
        return upper;
    }
}

泛型类调用:
传入具体的类和参数。

public static void main(String[] args){
    Interval<Integer> v1 = new Interval<>(1, 2);
    int lower = v1.getLower();
    int upper = v1.getUpper();
    System,out.println(lower + ", " + upper);

    Interval<Integer> v2 = new Integer<>(2, 3);
    Interval<Integer> v3 = getReverse(v2);
    System.out.println(v3.getLower() + ", " + v3.getUpper());
}

//该方法为泛型方法:方法被泛化,包括返回值和参数。
//第一个<T>为规定了后面的类型均为T,Interval<T> 为返回值类型。
public static <T> Interval<T> GetReverse(Interval<T> interval){
    return new Interval<T>(interval.getLower(), interval.getUpper());
}
  1. 泛型接口:T 可以再是一个泛型类。
public class Interval<T>{
    private T lower;
    private T upper;

    public Interval(T lower, T  upper){
        this.lower = lower;
        this.upper = upper;
    }
    public T getLower(){
        return lower;
    }
    public T getUpper(){
        return upper;
    }
}

public interface Caculator<T>{
    public T add(T o1, T o2);
}


public class IntervalCaculator implements Caculator<Interval<Integer>>{
    public static void main(String[] args){
       Caculator<Interval<Integer>> c = new IntervalCaculator();
        
        Interval<Integer> o1 = new Interval<>(1, 2);
        Interval<Integer> o2 = new Interval<>(2, 3);
        Interval<Integer> o3 = c.add(o1, o2);
        System.out.println(o3.getLower() + ", " + o3.getUpper());
    }
    public Interval<Integer> add(Interval<Integer> o1, Interval<Integer> o2){
    int lower = o1.getLower() + o2.getLower();
    int upper = o1.getUpper() + o2.getUpper();
    return new Interval<Integer>(lower, upper);
    }     
}

范型类型限定

泛型限定

  1. T 必须是Comparable的子类。extends是固定的,后面可以有多个,用 & 来拼接。
    extends限定可以限定多个接口,但是只能是一个类。且类必须在开头。
    使用逗号分隔参数,<T extends File & Cloneable, U extends Serializable>。

  2. 泛型的继承原则:Pair 和Pair< S> 没有任何关系,即使T和S存在关系。

泛型通配符

  1. 上限界定符:Pair<? extends S>。
    Pair能接收的参数类型:S本身及其子类。
    如果有Apple类和Orange类均继承于Fruit类。
    则:
    Pair<? extends Fruit> 代表Pair< Fruit>, Pair< Apple>, Pair< Orange>。
    (子类型可以转为父类型)。
    只能get,不能set,只能确定get得到的类型一定可以转型为Fruit类型。不可保证放进去的是什么类型。

  2. 下限界定符:Pair<? supper S>。
    Pair能够接收的类型,S本身及其超类。
    如果有:
    GreenApple继承于Apple,
    Apple继承于Fruit,
    Fruit继承于Object。
    则:
    Pair<? supper Apple>可表示:Pair< Object>, Pair< Fruit>, Pair< Apple>。

Pair<? supper Apple> fruits = new Pair<Fruit>();
//可以,因为Fruit类在 ?supper Apple内。

fruits.setFirst(new Apple(3));//Apple可以转型为Fruit类
fruits.setSecond(new GreenApple(2));//GreenApple可以转型为Fruit。
fruits.setSecond(new Object());//出问题,Object不可以向下转型为Fruit。

注意,下限界定符:只能set,不可get。可以放进去Apple及其子类。

泛型PECS原则
(Productor Extends Consumer Supper)
要从泛型类中读数据不写入,使用? extends S;要写数据不读,使用 ? supper S。既要读又要写,不使用通配符。

范型的本质和约束

泛型是JDK1.5引入的新特性。JDK版本是向后兼容的。
JVM里面没有泛型对象,而是在编译采用类型擦除技术,将泛型转为限定类型。

  1. 擦除泛型变量,替换为原始类型,无限定类型时为Object。
public class Pair<T>{
    private T first;
    private T second;

    public Pair(T first, T second){
        this.first = first;
        this.second = second;
    }
    public T getFirst(){
        return first;
    }
    public void setFirst(T first){
        this.first = first;
    }
}

转为

public class Pair<Object>{
    private Object first;
    private Object second;

    public Pair(Object first, Object second){
        this.first = first;
        this.second = second;
    }
    public Object getFirst(){
        return first;
    }
    public void setFirst(Object first){
        this.first = first;
    }
}
  1. 擦除泛型变量,替换为原始类型,有限定为第一个类型。

  2. 重载泛型方法翻译:采用自动桥的方法;使得子类重载父类方法后,调用时,还是调用子类的方法。

java 类型的协变和逆变

类型变化关系(Type Variance):
A, B 是两个类型,f(*)表示类型转换,<=表示继承,如A<=B,表示A继承于B。
在这里插入图片描述

  1. java 数组是协变的。
    如:String 是Object的子类,则,String[] 也是Object[]的子类。
  2. Java泛型是不变的。
    如:String是Object的子类,但是List和List没有关系。
    但是,泛型可采用通配符,支持协变和逆变(PECS原则)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值