泛型及其通配符

本文详细介绍了Java中的泛型概念,包括泛型类、泛型方法和泛型接口的使用,以及内部类如何处理泛型。此外,还讨论了通配符在泛型中的作用,如无限制的<?>、上限限定<? extends T>和下限限定<? super T>。最后,解释了泛型的擦除机制,即在编译后泛型如何转化为Object或其指定边界类型。
摘要由CSDN通过智能技术生成

一.泛型

·定义:守门员,主要用于参数的校验

·<>钻石操作符,表示泛型,在一个类或者方法上看到<>,表示使用了泛型

< T > T为类型参数,可以用任意字符来表示,一般用大写字母表示。例如:K,V E等等

·泛型方法中的<T>和泛型类中<T>是否是一个东西

泛型方法始终以自己的类型参数为基准,和类中的泛型无关,声明泛型方法,一般与类使用不同的类型参数。

public class MyClass <T>{
    private T t1;
    //返回值为T的普通函数
    public T getT1(){
        return t1;
    }
    //参数为T的普通函数
    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);
    }
}

·泛型接口:

//泛型接口,带一个类型参数
interface Imessage<T>{
    void printMsg(T t);
}
//子类实现接口时,要么继续保留泛型,要么规定类型参数
class MessageImp1<T> implements Imessage<T> {

    @Override
    public void printMsg(T t) {
        System.out.println(t);
        System.out.println("仍然是泛型类");
    }
}
//为普通类
class MessageImp2 implements Imessage<Number>{

    @Override
    public void printMsg(Number number) {
        System.out.println(t);
        System.out.println("普通类");
    }

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

内部类分为:成员内部类;静态内部类;方法内部类;匿名内部类

成员内部类:直接定义在类的内部,不加static关键字-》成员方法,必须依附外部类的存在,产生对象必须先产生外部类对象;不能拥有静态域,可以访问外部类成员方法和静态域;

静态内部类:直接定义在类的内部,使用关键字static修饰,类比静态方法,和其他类没区别;

能够拥有成员域,不能访问外部类的成员域(没传入外部对象,无法访问)

public class MyOutter<T> {
    private class Inner{
        public void Test(T t2){
            System.out.println(t2);
        }
    }
    public static class Inner2<T>{
        public void fun(T t1){
            System.out.println(t1);
        }
    }

    public static void main(String[] args) {
        MyOutter<String> outter = new MyOutter<>();
        //成员内部类创建
        MyOutter<String>.Inner inner = outter.new Inner();
        inner.Test("123");
        //静态内部类的创建
        MyOutter.Inner2<Integer> inner2 = new Inner2<>();
        inner2.fun(123);
    }
}

·非静态内部类回复用外部类型参数,静态内部类不会复用外部类的泛型参数

public class Outter {
    public static void main(String[] args) {
        Outter outter = new Outter();
        outter.fun();
    }
    private int age = 18;
    private static String country = "china";
    public void fun(){
     Inner1 inner1 = new Inner1();
     inner1.test();
   
    }
    //内部成员类
    public class Inner1{
        public void test(){
            System.out.println(Outter.this.age);
            System.out.println(country);
        }
    }
    //静态内部类
    public static class Inner2{
        private int a = 10;
        private static double hehe = 10.0;
        public void fun(){
            System.out.println(country);
            //error
            //System.out.println(age);
        }
    }
}

二.通配符

由于泛型的强类型校验,不同的类型完全不能通过校验,要匹配不同的类型的对象,就得重载很多的方法,这样就本末倒置,搞复杂

因此采用通配符

<?>一般用在方法参数中,可以接受该类所有类型的泛型变量

public class Message<T> {
    private T msg;
    public T getMsg(){
        return msg;
    }
    public void setMsg(T msg){
        this.msg = msg;
    }

    public static void main(String[] args) {
        Message message = new Message();
        message.setMsg("string类型");
        fun(message);
        Message message1 = new Message();
        message1.setMsg(123);
        fun(message1);
    }
    public static void fun(Message <?> msg){
        System.out.println(msg.getMsg());
    }

<?>只能调用getter方法获取属性,由于根本无法确定传入对象的类型,因此无法调用对象的setter来设置值。

·设置泛型的上限

<? extends 类>

?表示任意类型,但是必须时后面类的子类

<? extends Number> ?可以是Number类本身,也可以是其子类,除此之外都不行。但是子类之间不能够相互转换;

extends 也可以用在泛型类的定义上

·设置泛型的下限

下限通配符

< ? super 类> 此时?可以代表任意后面类的父类,只能够用在方法参数中,不能够用于类的类型参数

public class Message<T extends String> {
    private T msg;
    public T getMsg(){
        return msg;
    }
    public void setMsg(T msg){
        this.msg = msg;
    }

    public static void main(String[] args) {
        Message message = new Message();
        message.setMsg("string类型");
        fun(message);
        Message message1 = new Message();
        message1.setMsg(123);
        fun(message1);
    }
    public static void fun(Message <? super String> msg){
        System.out.println(msg.getMsg());
    }
}

三.泛型擦除

泛型是典型的语法糖(只在编译期有效,属于我们为了方便程序开发引入的一种新的机制,在编译后消失),类似于我们c语言中的宏定义

·所有泛型类型参数,若没有设置泛型上限,则编译之后统一擦除为Object类型,若设置了类型上限,则编译器统一擦除为响应的泛型上限

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值