泛型概念及其语法

一.什么是泛型?为什么需要泛型?

早期的Object类型可以接受任意的对象类型,但是在实际的使用中,会有类型转换的问题.也就存在了隐患.因此java提供了泛型来解决这个问题.

泛型,即**参数化类型.**也就是把类型当做参数传递,在创建类的对象的时候,可以传入任意类型.

泛型是jdk5之后的语法,泛型提供了编译时类型安全检测机制.

二.泛型类

泛型类用于类的定义中,被称为泛型类.通过泛型类可以完成对一组类的操作对外开放相同的接口.

比如,一个最简单的泛型类:

//T为任意标识符,常见的如T,E,K,V等形式的参数都用于表示泛型
public class FXDemo <T>{

    //num这个成员变量的类型为T,T的类型由外部指定
    private T num;

    //构造方法的参数类型也是T,T类型由外部指定
    public FXDemo(T num) {
        this.num = num;
    }

    //getNum() 方法的参数类型也为T
    public T getNum() {
        return num;
    }

    public static void main(String[] args) {

        //在这里我们传入的实参类型必须与泛型的类型参数类型相同
        FXDemo<Integer> fxDemo = new FXDemo<>(36);
        /*
            有三个点我们需要注意一下
            1.泛型的类型参数只能是类类型,,也就是引用类型
            2.泛型的参数类型可以有多个
            3.如果没有具体的定义泛型类型,默认是Object
         */
        System.out.println(fxDemo.getNum());//输出36
    }
}

从泛型类派生子类

1.如果子类也是泛型类,子类要和父类的泛型类型一致

public class FXDemo2<T> extends FXDemo<T>{

    public FXDemo2(T num) {
        super(num);
    }

    public static void main(String[] args) {
        //当我们使用构造方法时要先传入泛型的类型,然后构造方法调用父类的,就只能传入我们泛型的类型
        FXDemo2<String> fxDemo2 = new FXDemo2<>("22");
    }
}

2.如果子类不是泛型类,父类要明确泛型的数据类型

public class FXDemo1 extends FXDemo<Integer>{

    public FXDemo1(Integer num) {
        super(num);
    }

    public static void main(String[] args) {
        //在类创建时已经声明了泛型类型,使用构造方法传入数据就要传入指定类型
        FXDemo1 fxDemo1 = new FXDemo1(23);
    }
}

上面就介绍了两种泛型类派生子类的情况

三.泛型接口

泛型接口与泛型类的定义及使用基本相同.这里就不再具体演示了,我只说语法.

public interface Demo { //定义一个泛型接口}

如果子类也是泛型类,子类要和父类的泛型类型一致

class A implements Demo { }

如果子类不是泛型类,父类要明确泛型的数据类型.

public class A implements Demo { }

四.泛型通配符

泛型通配符(也叫无界通配符)**一般是使用"?"代替具体的类型实参.

比如我们在前面的FXDemo类中添加一个这样的方法

//这个就表示我们传入的参数类型可以是任意的
    public void show(FXDemo<?> fxDemo){

    }

接着我们进行测试

       public class FXTest {

    public static void main(String[] args) {


        FXDemo<Integer> fxDemo1 = new FXDemo<>(32);
        FXDemo<String> fxDemo2 = new FXDemo<>("33");
        FXDemo<Number> fxDemo3 = new FXDemo<>(36);

        FXDemo fxDemo = new FXDemo(36);
        //这里我们show方法传入的参数无论是什么类型都可以,就是因为前面是"?"
        fxDemo.show(fxDemo1);
        fxDemo.show(fxDemo2);
        fxDemo.show(fxDemo3);
    }
}

如果我们把show方法改变一下

public void show(FXDemo<?  extends  T> fxDemo){

    }

其次再继续在FXTest类中测试一下

FXDemo<Number> fxDemo = new FXDemo(36);
                fxDemo.show(fxDemo1);
                fxDemo.show(fxDemo2);//这行代码就会报错,因为String没有继承Number
                fxDemo.show(fxDemo3);

这个就叫做**类型通配符上限.**类/接口<?extends 实参类型>

我们传入的参数应该继承于提前定义好的实参类型或者就是这种类型.

那既然有类型通配符上限,就会有类型通配符下限.它的语法是:类/接口<?super 实参类型>

那这种的话,我们传入的参数应该是提前定义好的实参类型的父类或者就是这种类型.

继续测试,我们修改show方法

public void show(FXDemo<?  super   T> fxDemo)

然后继续在FXTest类中进行测试

FXDemo<Integer> fxDemo = new FXDemo(36);
                fxDemo.show(fxDemo1);
                fxDemo.show(fxDemo2);//依然是这行代码报错,因为String类不是Integer的父类
                fxDemo.show(fxDemo3);

五.类型擦除

泛型是java1.5版本才引入的概念,在这之前是没有泛型的.但是,泛型代码能够很好地和之前版本的代码兼容。那是因为,泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为一类型擦除.

也就是说,泛型只是为了让我们传入的类型是一个相同的类型.(这里注意,必须是引用类型)在运行的时候相应的类型就被替换成 Object 类型或者上限类型.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值