说说泛型

引子

最近在重构代码,发现很多情况下,抽取基类,都离不开泛型这个知识点,用好泛型,是重构代码的第一步

子类限定和超类限定 看这里

什么是泛型

当你想要定义一个基类,或者是通用的类、接口、方法时,你还不知道以后的使用者要往里面传入什么类型的对象,这时候,你就不能把这个数据类型写死了,写死了就不具有扩展性、通用性,就不能称之为基(通用)了。这时候你就需要泛型了。

当然,你会问,我不知道要传入什么类型,我直接写个Object类型不就行了吗,这样不是不行,但是这样极易产生《强制转换异常》,

而且这个《强制转换异常》属于运行时异常,编译期间你不会发现错误,只有在运行时,才会报错,

泛型的经典定义:
泛型,就是,一种把 明确数据类型的工作,放在了创建对象,或者调用方法时候 进行的特殊类型。

泛型用(声明)在什么位置

  1. 方法上,在调用方法时候,明确数据类型 方法返回值之前
  2. 类上,在new 对象时候,明确数据类型 类名之后
  3. 接口上,在实现接口(或者在new 接口的实现类的)时候,明确数据类型接口名之后

< T >:表示声明泛型
T: 表示使用泛型
T:只能是引用类型,不能是基本类型(自动装包了int–>Integer)

方法上声明泛型

public class Tool {
    /**
     * 1.在方法上使用泛型
     * 这是一个输出语句的方法
     * 但是我们在定义这个方法时候,还不确定要输出什么类型的对象
     * 有可能要输出一个int类型,也有可能是String类型,或者是boolean类型
     * 那么这里我们就不能把这个类型定死了,应该用一个“泛型”
     * ok,我们在形参里面写(T t),就表明了,调用者可以输入任意类型的对象
     * 问题来了,你平白无故来了个T,谁知道这个T是什么呢
     * 就像是你直接来了个变量i,上来就i=0,这样是不行的,你应该先声明这个变量:int i;
     * 然后你才可以使用这个i,类比到泛型上
     * 你想使用泛型T,那么首先你应该声明这个泛型T,如何声明呢
     * 很简单,只要在方法返回值前面写一个T即可(这里说的是方法上使用泛型的情况)
     * @param t  形参的泛型对象
     * @param <T> 声明泛型在方法上
     */
    public <T> void show(T t) {
        System.out.println(t);
    }
}

在调用这个方法时,你可以传入任意的对象了

 Tool tool = new Tool();
/**
 *这时候数据类型是在使用方法时才明确的,
 *所以你传入什么数据类型,就使用什么数据类型,
 *是不是很方便,使用的时候在确定数据类型
**/
 tool.show(100);
 tool.show("hello");
 tool.show(true);
 tool.show(new Date());
 tool.show('A');
 tool.show(85.7);
 tool.show(new Byte("100"));
 tool.show(new Character('C'));

类上声明泛型


/**
 * 泛型声明在类上
 * @param <T> 声明泛型在类上
 */
public class Tool1 <T>{
//泛型T在类或者接口上声明过,就不需要在方法上声明了
    public  void show(T t) {
        System.out.println(t);
    }
}

使用这个泛型类


        Tool1<String> tool1=new Tool1<>();
//      因为你在new对象时就确定了要传入的数据类型是String,
//      所以你在这里传入Integer,就直接报错,
//      是不是把运行时异常提前到编译期间了
//        tool1.show(100);
        tool1.show("hello");
//      还是那个Tool1<T>泛型类,这次你new对象时候,指明了明确的数据类型Integer
        Tool1<Integer> tool11=new Tool1<>();
        tool11.show(100);//不能再传String

接口上声明泛型

接口上声明泛型有两种情况
1. 接口上声明了泛型,在创建该接口的实现类时,明确了泛型的具体类型
2. 接口上声明了泛型,在创建该接口的实现类时,还未明确泛型的具体类型,而是在new 实现类时,才明确泛型的具体类型

先定义一个泛型接口

/**
 * 泛型声明在接口上
 * @param <T> 声明泛型在接口上
 */

interface  ToolInter<T> {

    public void show(T t);
}
第一种情况

在创建该接口的实现类时,明确了泛型的具体类型
实现类

/**
 * 由于在创建实现类时,就明确了泛型的具体类型
 * 所以在该类下,所有使用该泛型的地方,都同时明确了数据类型
 * 注意:只需在接口名称后面跟上<具体的数据类型>
 */

public class ToolImpl implements ToolInter<String>{
    @Override
    public void show(String s) {
        System.out.println(s);

    }
}

使用之

       //由于ToolImpl已经明确了数据类型为String,这里就不需要再次指定数据类型了
        ToolImpl toolImpl = new ToolImpl();
        //而这个方法的泛型,也在ToolImpl里面就已经明确了,只能是String
        toolImpl.show("hello");
第二种情况

在创建该接口的实现类时,还未明确泛型的具体类型,而是在new 实现类时,才明确泛型的具体类型

实现类


/**
 * 由于在创建实现类时,还没有明确了泛型的具体类型
 * 所以在该类下,所有使用该泛型的地方,都还没有明确具体数据类型
 * 注意:
 * 1.在接口名称后面跟上<泛型T>
 * 2.在实现类名称后面跟上<泛型T>
 * 3.在方法上使用泛型T,泛型T在类或者接口上声明过,就不需要在方法上声明了
 */

public class ToolImpl1<T> implements ToolInter<T>{

    @Override
    public void show(T t) {
        System.out.println(t);

    }
}

使用之

   //由于ToolImpl1还没有明确了数据类型,所以在这里必须指定具体的数据类型
        ToolImpl1<String> toolImpl1 =new ToolImpl1<>();
        //而这个方法的泛型,也在上一步new ToolImpl1明确了是String,
        // 所以方法的具体类型只能是String
        toolImpl1.show("toolImpl1");

泛型的使用也就是以上的三种情况了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值