Java泛型

泛型类

package generic;

/**
 * @author pangjian
 * @ClassName Generic
 * @Description 泛型类定义,T创建对象时指定具体的数据类型,外部指定
 * @date 2021/8/25 13:12
 */

public class Generic<T> {
    
    /**
     * @Description:外部指定属性类型
    */
    private T key;

    /**
     * @Description:外部指定返回类型
    */
    public T getKey() {
        return key;
    }

    /**
     * @Description:外部指定参数类型
    */
    public void setKey(T key) {
        this.key = key;
    }

    public static void main(String[] args) {
        Generic<String> stringGeneric = new Generic<>();
        stringGeneric.setKey("hello world");
        System.out.println(stringGeneric.getKey());
    }

}

泛型类在创建对象没有指定类型时按照Object类型来操作,泛型不支持基本数据类型

public class Parent<E> {
}
/**
 * @author pangjian
 * @Description 泛型类派生子类,子类也是泛型类,
 * 那么子类的泛型标识要和父类一致。并且可以拓展
 */

public class Son<E, T> extends Parent<E> {
}
/**
 * @author pangjian
 * @Description 泛型类派生子类,子类不是泛型类,那么要指定父类泛型
 */
public class Son extends Parent<Integer> {
}

泛型接口

public interface Buy<T> {
    T buyGoods();
}
/**
 * @author pangjian
 * @Description 如果实现类也是泛型,那要有一个和接口一样的,
 * 如果实现类不是泛型类,要明确泛型,不然按Object类型处理
 */

public class People<T> implements Buy<T> {
    @Override
    public T buyGoods() {
        return null;
    }
}

泛型方法

/**
 * @author pangjian
 * @Description 泛型类和泛型方法理解
 */

public class Girl<T> {

    private T name;

    /**
     * @Description: 同一个方法处理不同类型的数据输出,而且是在方法调用时候确定泛型,不是由泛型类创建时候去确定的
     * @Param e:不同类型的参数
     * @Param <E> 表示方法泛型,由调用传参的时候去确定,定义在返回值前面
    */
    public static <E> E say(E e){
        System.out.println(e);
        return e;
    }

    /**
     * @Description: 泛型成员方法
     * @Param k: 
     * @return K表示返回值,返回值类型是你调用方法时候由传递的参数去决定
    */
    public <K> K action(K k){
        System.out.println(k);
        return k;
    }

    public static void main(String[] args) {
        Girl.say(1); // 处理数字类型输出
        Girl.say("hello world"); // 处理字符串类型输出
        Girl<String> girl = new Girl<>();
        Integer i = girl.action(111);
    }
}

类型通配符

一般是使用 ? 代替具体的类型实参,所以类型通配符是类型实参,不是形参

问题产生,泛型失去了继承,由于编译阶段的特性是不能当成两个不同的类去处理,而是始终是一个Boy类,也不能使用重载,因为参数列表是一样的,虽然Boy指定的是不同类型,但 jvm 并不是我们想像的那么理性

public class Boy<T> {

    private T key;

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }
}

class Test {

    public static void main(String[] args) {
        Boy<Integer> box = new Boy<>();
        // showBoy(box);
    }
    
    public static void showBoy(Boy<Number> boy){
    }
    
}

通配符解决问题,? 代表任意类型实参

public static void showBoy(Boy<?> boy){
		// 现在还不是最完美的状态,用了泛型了还是得指定成Object
    	Object key = boy.getKey();
        System.out.println(key);
}

类型通配符上限和下限

  • 上限
// 这样也是没有异常的
public static void main(String[] args) {
    Boy<Integer> boy = new Boy<>();
    boy.setKey(50);
    showBoy(boy);
}

/**
 * @Description:重新绑定泛型的继承关系,
 * 要求只能是Number实参类型或者它的子类型,子类型也就包括了Integer,这就是 ? 的上限
*/
public static void showBoy(Boy<? extends Number> boy){
    Number key = boy.getKey();
    System.out.println(key);
}
  • 下限
public static void main(String[] args) {
    Boy<Throwable> boy = new Boy<>();
    boy.setKey(new RuntimeException());
    showBoy(boy);
}

/**
 * @Description:重新绑定泛型的继承关系,
 * 要求只能是Exception实参类型或者它的父类型,父类型也就包括了Throwable,这就是 ? 的下限
*/
public static void showBoy(Boy<? super Exception> boy){
    Object key = boy.getKey();
    System.out.println(key);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值