java高级之泛型详解

定义:在java1.5之后推出的。
泛型又叫参数化类型或者类型参数化,在不创建新的类型的情况下,通过泛型指定不同类型来控制形参具体限制的类型,姑且把声明在类上的泛型也叫形参。

泛型应用的意义:

  1. 在编译期间确认类型,保证编译阶段时的类型不会出错。
  2. 避免强制转换逻辑。
  3. 可以提高代码的可重用性和增加程序的灵活性。

注意事项:
泛型的类型擦除:java的泛型只在编译阶段有效,泛型可以在逻辑上分成多种不同的类型,比如List<String> 与 List<Integer> 可以在逻辑上看作是不同的类型,但实质上是同一种类型List,因为java会在编译之后实施去泛型化操作。

证明:
在这里插入图片描述
在这里插入图片描述

泛型的使用:

  1. 泛型必须要先声明后才能使用。就像变量似的。
  2. 泛型采用一对尖括号声明<>。
  3. 声明一般采用单个大写字母表示,比如 <K,V>等。
  4. 泛型的声明和使用分为泛型类,泛型接口,泛型方法三种。
泛型类:

定义:声明在类上的泛型。

//泛型参数在类上声明了,可以在类中使用非静态元素使用。
public class TypeDemo<E,V> {
    
    public V  value;
    
    private E element;
    
    //这个是错误的,在类上定义的参数不能在静态变量上使用。
    // 因为静态变量是类级别的,而在类上定义的泛型参数是对象级别的。
    private static V value2;
    
    public E getElement(){
        return element;
    }

    /**
     * 这个也是错误的,因为静态方法是类级别的,
     * 而在类上定义的泛型参数是对象级别的。如果要在静态方法中使用泛型,
     * 可以定义泛型方法。
     * @return
     */
    public static V getValue(){
        return null;
    }

}


//也可以在继承时使用泛型参数。
public class TypeDemoImpl extends TypeDemo<String,Integer> {
}

//也可以在继承时继续声明参数
public class TypeDemoImpl<E,V> extends TypeDemo<E,V> {
}


泛型接口的使用:

例子:List Map<K,V>。
泛型接口与泛型类类似。

public interface TypeInterface<K,V> {
    K say();
    
    V goodBye();
}

public class TypeInterfaceImpl implements TypeInterface<String,Integer> {

    @Override
    public String say() {
        return null;
    }

    @Override
    public Integer goodBye() {
        return null;
    }
}

public class TypeInterfaceImpl<K,V> implements TypeInterface<K,V> {

    K key;
    
    @Override
    public K say() {
        return null;
    }

    @Override
    public V goodBye() {
        return null;
    }
}
}


泛型方法的使用:

成员方法可以直接使用类上声明的泛型参数,也可以在方法上自己声明泛型参数,但是静态方法要使用泛型就必须自己声明泛型参数。

public class TypeDemo<E,V> {

    public V  value;

    private E element;



    //这是使用类上声明的泛型参数E
    public E getElement(){
        return element;
    }

    //这是在成员方法上声明自定义泛型参数S
    public <S> void say(S s){

    }

    /**
     * 这是在静态方法上声明自定义的泛型参数R
     * @return
     */
    public  static <R> R getValue(R role){
        return role;
    }


    public static void main(String[] args) {
        //使用泛型
        TypeDemo<String,Integer> stringIntegerTypeDemo = new TypeDemo<>();

        
        String element = stringIntegerTypeDemo.getElement();

        Integer value = stringIntegerTypeDemo.value;

        stringIntegerTypeDemo.say(true);

        List<String> strings = TypeDemo.getValue(new ArrayList<>());

        List<String> strings1 = stringIntegerTypeDemo.getValue(new ArrayList<>());
    }
}

泛型通配符:

只能在定义方法时的形参使用,限制调用方法时实参的类型。

<?> //无边界,表示调用该方法时传递的实参可以是任意类型。
<? extends E> //上边界,表示调用该方法时传递的实参只能是E类型或者E类型的子类,E可以是真正的类型比如Number,也可以是已经声明好的泛型参数。
<? super E> //下边界,表示调用该方法时传递的实参只能是E类型获取E类型的父类或接口类,E可以是真正的类型比如Number,也可以是已经声明好的泛型参数。

这是Number类继承关系的类图:
在这里插入图片描述

public class TongPeiFuDemo<K,V> {

    //无边界。调用该方法传递的实参可以任意类型的List
    public void sayHello(List<?> list){

    }

    //上边界,调用该方法传递的实参只能是K或者K的子类的List
    public void sayHelloExtendsK(List<? extends K> list){

    }

    //上边界,调用该方法传递的实参只能是Number或者Number的子类的List
    public void sayHelloKExtendsNumber(List<? extends Number> list){

    }

    //下边界,调用该方法传递的实参只能是K或者K的父类或接口的List
    public void sayHelloSuperK(List<? super K> list){

    }

    //下边界,调用该方法传递的实参只能是Number或者Number的父类或接口的List
    public void sayHelloSuperNumber(List<? super Number> list){

    }

    public static void main(String[] args) {

        TongPeiFuDemo<Number,Object> stringObjectTongPeiFuDemo = new TongPeiFuDemo<>();

        //测试无边界:多种类型的List都可以。
        stringObjectTongPeiFuDemo.sayHello(new ArrayList<String>());
        stringObjectTongPeiFuDemo.sayHello(new ArrayList<Map<String,ObjectList>>());
        stringObjectTongPeiFuDemo.sayHello(new ArrayList<Integer>());


        //测试上边界,此时的K泛型参数被赋予了Number类型
        //因为上边界是number,所以Number型的List可以
        stringObjectTongPeiFuDemo.sayHelloExtendsK(new ArrayList<Number>());
        //因为Integer是Number的子类,所以可以
        stringObjectTongPeiFuDemo.sayHelloExtendsK(new ArrayList<Integer>());
        //因为String与Number没有继承关系,所以报错
        stringObjectTongPeiFuDemo.sayHelloExtendsK(new ArrayList<String>());
        //因为Object是Number的父类,超越了上边界,所以会报错
        stringObjectTongPeiFuDemo.sayHelloExtendsK(new ArrayList<Object>());


        //测试下边界
        //因为下边界是number,所以Number型的List可以
        stringObjectTongPeiFuDemo.sayHelloSuperNumber(new ArrayList<Number>());

        //因为Object是Number的父类。处于下边界之上,所以可以。
        stringObjectTongPeiFuDemo.sayHelloSuperNumber(new ArrayList<Object>());

        //因为String与Number没有继承关系,所以报错
        stringObjectTongPeiFuDemo.sayHelloSuperNumber(new ArrayList<String>());

        //因为Integer是Number的子类,超越了下边界,所以报错
        stringObjectTongPeiFuDemo.sayHelloSuperNumber(new ArrayList<Integer>());

    }
}

还可以在类或者接口上限制泛型参数类型,但是不能使用通配符。

public class ClassLimit<E extends Number> {
    
}

public interface InterfaceLimit<E extends Number>{

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值