泛型进阶plus

目录

一、泛型

1.区分泛型方法。

2.泛型接口

二、内部类

1.成员内部类能否拥有静态域? 

2.成员内部类能否访问外部类的成员方法和静态域?

3.静态内部类(除了套在一个类的内部以外和其他类没任何区别)

 三、泛型的通配符

1.案例引入

2.细化通配符

3.类型擦除


一、泛型

<>钻石操作符,表示泛型

<T>T称为类型参数,可以用任意字符来表示,一般用单个的大写字母来表示。

1.区分泛型方法。

泛型方法始终以自己的类型参数为准,与类中的泛型无关,

一般如果声明泛型方法,我们使用不同的类型参数来区分

 public void setT1(T t1) {
        this.t1 = t1;
    }

    public <T> void fun(T t){
        //这个才是泛型方法
    }
    public static void main(String[] args) {
        MyClass<String> myClass = new MyClass<>();
        myClass.setT1("123");
        myClass.fun(123);
    }

2.泛型接口

在实现接口的时候,有两种选择

<1>继续保留泛型

<2>在实现时规定类型参数

interface IMessage<T>{
    void printMsg(T t);
}
//1,继续保留泛型,是一个泛型类 
class MessageImpl1<T> implements IMessage<T>{

    @Override
    public void printMsg(T t) {
        System.out.println(t);
        System.out.println("仍然是泛型类");
    }
}

//2.就是一个普通类,实现接口的时候规定好参数的类型就是整形
class MessageImpl2 implements IMessage<Integer>{

    @Override
    public void printMsg(Integer integer) {
        System.out.println(integer);
        System.out.println("类型为Integer的普通类");
    }

二、内部类

 

内部类:将一个类嵌套到另一个类的内部。

内部类属于封装的一种,保护内部类。

发动机和汽车这两个类的关系,发动机就是汽车的内部类

心脏就是人体的内部类

一共有几种内部类呢?

4种 成员、静态、方法、匿名内部类

成员内部类实际上JVM会传入一个隐藏的外部对象Outter.this

1.成员内部类能否拥有静态域? 

不能,成员内部类必须有外部类的对象才能产生

2.成员内部类能否访问外部类的成员方法和静态域?

可以,外部类的静态域没有外部类对象都能访问,更何况现在成员内部类已经有一个外部类的对象了。

3.静态内部类(除了套在一个类的内部以外和其他类没任何区别)

静态内部类能拥有成员域

不能访问外部类的成员域(静态内部类不需要依赖外部类的对象,此时没有传入外部类对象,当然无法访问外部类的成员域)

成员内部类静态内部类
是否复用外部类的泛型参数不会

这里规定了类型是String,必须使用相同类型,否则会出现错误。

 三、泛型的通配符

1.案例引入

 在fun方法中,方法参数中规定了形参的接收类型为Message<String>,,但是msg1提供的是一个Integer类型的变量。

由于泛型的强类型校验,不同的类型完全不能通过校验,要匹配不用类型的Message对象就得冲在很多fun方法。

这样就本末倒置,变得更加复杂了~

<?> :一般用在方法参数,表示可以接受该类所有类型的变量。但是不能用在类的名称上

      只能调用对象的get方法来获取属性,不能set(由于此时根本无法确定传入对象的类型,因此无法调用对象的setter来设置值)

 

 此时使用了通配符,就不会报错了,可以接受任意类型的参数。

2.细化通配符

1.设置类型的上限

<? extends类> 表示? 可以指代任意类型,但是该类型必须是后面类的子类

<? extends Number>此时表示? <= Number

此时?可以是Number本身,或者是Number的子类,除此之外的其他类型都不可以

?表示可以接收Number及其子类,但是子类之间是不能互相转换的(比如Int和double)

泛型的上限通配符仍然不能set具体值,只能Getter取得

 T可以指代任意Number及其子类的类型,T仅限于Number及其子类的类型

2.设置类型的下限

<? super String>此时?表示必须是String及其父类

此时?只能指代String或者Object

只能用子啊方法参数,不能作用于类的类型参数

 public static void fun(Message<? super String> msg){
        //设置了通配符下限,可以是String或者Object
        //此时就可以使用
        msg.setMsg("hehe");
        System.out.println(msg.getMsg());
    }

下限通配符可以调用对象的setter方法设置一个具体的属性值(下限类型的)

3.类型擦除

泛型典型的“语法糖”(只在编译生效,属于我们为了方便程序开发引入的一种机制)

实际上泛型通过Javac编译之后,泛型就不见了~

所有泛型的类型参数,如果没有设置上限,则编译之后统一擦除为Object

如果设置了泛型上限,则编译之后统一擦除为相应的泛型上限

 Message<Integer> msg1 = new Message();
        Message<Double> msg2 = new Message<>();
        Field field = msg.getClass().getDeclaredField("msg");
        Field field1 = msg1.getClass().getDeclaredField("msg");
        Field field2 = msg2.getClass().getDeclaredField("msg");
        //field使用应该通过对象调用方法,我第一次写代码将name变为msg1,导致编译器无法找出,报错没有这个变量
        System.out.println(field.getType());
        System.out.println(field1.getType());
        System.out.println(field2.getType());
}
    public static void fun(Message<? super String> msg){
        //设置了通配符下限,可以是String或者Object
        //此时就可以使用
        msg.setMsg("hehe");
        System.out.println(msg.getMsg());
    }

这就是上面说的,如果设置了泛型上限,统一擦除为相应的泛型上限

 

 此时有两个变量一个是integer,一个是doublel类型的,都擦除为相应的泛型上限Number。

更多基础在往期的泛型博客中。泛型 -- 学会它,好处多多_mmmenxj的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值