Java之泛型

目录

泛型的引入

泛型类

泛型方法 

泛型接口 

通配符 

类型擦除 


泛型的引入

我们来看一个现象 如果我们想实现一对坐标x,y,能让这个x和y接收不同类型的数据,比如

x=10,y=10,x=10.1,y=11.1,x=”东经15度”,y=北纬39度",我们可以想到用Object来接收

class Point{
   private Object x;//用Object来接收不同的数据类型
   private Object y;
    public Object getX() {
        return x;
    }

    public Object getY() {
        return y;
    }

    public void setX(Object x) {
        this.x = x;
    }

    public void setY(Object y) {
        this.y = y;
    }
}

 我们发现如果数据对应正确,那没什么问题,那如果用户输入时,想要让用户输入int类型,他输成double类型,我们程序是中是让披着Object的Integer类型向下转换为Integer,但是用户导致是披着Obbject的Double向下转换为Integer就会发生类型转换错误

但是我们发现这种错误是运行时异常,一般我们要将错误提取暴露在编译阶段,就是程序还没有跑起来就报出错误 

泛型类

class 类名 <T>{
    T x;

}
class 类名 <T,E>{
    T x;
    E y;

}
  • 泛型类可以存在多个类型参数,成员变量的类型不一定一致
  • 泛型不能接收八大基本类型,只能接收它的包装类
  • T,E这种大写用来表示参数类型,可以使用任何字符,但是大写字母是规范
  • T表示任意类型 K表示键值对 V表示value值 E表示单个元素
  • 类的泛型就是在定义时没有确定参数类型,使用时明确类型
  • 守门员,在编译的阶段检查了类型是否一致

泛型类的使用

类名称 <具体的类> 对象名=new 类名称<>();

使用泛型之后的Point类

class Point<T>{
   private T x;//用Object来接收不同的数据类型
   private T y;

    public T getX() {
        return x;
    }

    public T getY() {
        return y;
    }

    public void setX(T x) {
        this.x = x;
    }

    public void setY(T y) {
        this.y = y;
    }
}

泛型方法 

普通类也可以定义泛型方法

  • <T>表示这个方法是泛型方法
  • T表示该函数的返回值是T类型
  • T t表示方法的参数是T类型

泛型类定义一个泛型方法

 

  •  因为泛型方法的泛型类型与传入泛型方法的类型为准,与泛型类的泛型类型无关,所以在定义的时候将泛型类和泛型方法的类型参数写成不一样的,防止操作异议
  • 注意要区分普通方法使用泛型和泛型方法的区别

泛型接口 

泛型还可以使用在接口中,一旦一个接口使用泛型,子类实现接口会存在两种选择

  • 子类继续保留泛型
  • 子类明确当前接口的泛型

 

 

 出现的问题

 

  • 我们使用多态来实现方法参数传入的多样性,用父类来接收所有子类的对象,但是我们发现msg1传入不进去,因为msg1确定的类型是Interger,但是我们父类确定的是String,所以传入不进去
  • 而且不能使用重载接近问题
  • 所以引入了通配符 

通配符 

1通配符,只能定义在方法中,表示可以接收所有类型的泛型类

package generic_paradigm;

public class MessageImpl1<T> implements IMessage<T>{
    private T msg;
    @Override
    public void print(T t) {
        System.out.println(t);
    }

    @Override
    public T getMsg() {
        return msg;
    }

    @Override
    public void setMsg(T t) {
        this.msg=t;
    }

    public static void main(String[] args) {
        IMessage<String> msg=new MessageImpl1();
        msg.setMsg("帅帅帅");
        IMessage<Integer> msg1=new MessageImpl1();
        msg1.setMsg(1111);
        fun(msg);
        fun(msg1);
    }
    public static void fun(IMessage<?> msg){//用父类来接收子类
        System.out.println(msg.getMsg());
    }
}

 

  •  用?通配符就可以对应在泛型类中不确定类型时,这个泛型类定义不同泛型对应的类型的对象,在方法中接收各种类型对象
  • 不能在fun方法中调用修改类型的方法:因为我们在定义fun方法的时候,根本不知道会传入什么类型的对象,我们就不能知道怎么设置值(因为不知道类型),所引只能调用接收方法,不能调用修改的方法

2 ?entends 类 设置泛型类的上限

  • 可以使用在类上或者方法上,明确此时泛型的上限是什么

  •  可以理解为天花板,我们只知道传入对象的父类是谁,但是我们不知道具体传入的子类
  • 不可以调用设置值的方法,因为我们只知道父类是什么 ,不知道其传入的子类,也不能进行向下转型,因为向下转型的条件是它本身就是这个子类,只是披着父类的皮

? super 类   规定泛型的下限

 

 

  • super只能用于方法,不能用于类型

  •  可以理解为地板,我们不知道其传入的到底什么类型的对象,但是肯定是String和String的父类
  • 可以在这个方法使用修改的方法,因为我们知道了这个传入的对象肯定是其String或者String的父类,因为向上转型的条件只要是其父类就行,没有其他任何条件,我们传入一个对象,都可以将设置的String值向上转型为其父类

类型擦除 

泛型信息其实只存在于编译阶段,进入JVM后,会将所有和泛型相关的信息擦除,泛型类进入JVM和普通类没有任何区别(javac->*.java编译为*.class之后,泛型就不存在了)

  • 若没有规定泛型的上限,则所有的泛型信息都会擦除为Object类
  • 若规定了泛型的上限,则擦除了相应泛型的上限类型
  • 泛型只是Java的语法糖

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

库里不会投三分

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值