Java 泛型接口使用说明

什么是泛型接口

泛型接口是在接口类中有一个未知对象,一个可变的对象。

从Java 5开始,引入了参数化类型(Parameterized Type)的概念,改造了所有的Java集合,使之都实现泛型,允许程序在创建集合时就可以指定集合元素的类型,比如List就表名这是一个只能存放String类型的List;
泛型(Generic):就是指参数化类型,上面的List就是参数化类型,因此就是泛型,而String就是该List泛型的类型参数;

泛型的好处:

  1. 使集合可以记住元素类型,即取出元素的时候无需进行强制类型转化了,可以直接用原类型的引用接收;
  2. 一旦指定了性参数那么集合中元素的类型就确定了,不能添加其他类型的元素,否则会直接编译保存,这就可以避免了“不小心放入其他类型元素”的可能;
  3. 上述保证了如果在编译时没有发出警告,则在运行时就一定不会产生类型转化异常(ClassCastException);
  4. 显然,泛型使编程更加通用,并且代码也更加简洁,代码更加容易维护;

定义泛型类、接口:

不仅Java的集合都定义成了泛型,用户自己也可以定义任意泛型的类、接口,只要在定义它们时用<>来指定类型参数即可;

例如:public interface SqlInterFace<T> { ... }

其中指定了该泛型的类型参数,这个T是一个类型参数名,用户可以任意命名(就像方法参数的形参名一样),只有在定义该泛型的对象时将T替换成指定的具体类型从而产生一个实例化的泛型对象,一个泛型接口可以被多个类实现,可以减少接口的开发。
例如:

SqlInterFace<BondCode> interFace = new BondCodeService();
SqlInterFace<BondDeal> dealSqlInterFace = new BondDealService();
SqlInterFace<BondDealRecord> bondCodeService = new BondDealRecordService();

实现/继承泛型接口/泛型类:

  • 定义泛型和使用泛型的概念:主要区别就是定义和使用
  1. 那Java的方法做类比,Java的方法在定义的时候使用的都是形参(虚拟参数),但是在调用方法(使用方法)的时候必须传入实参;
  2. 同样泛型也有这个特点,泛型的类型参数和方法的参数一样,也是一种参数,只不过是一种特殊的参数,用来表示未知的类型罢了;
  3. 因此,泛型也是在定义的时候必须使用形参(虚拟参数,用户自己随意命名),但是在使用泛型的时候(比如定义泛型引用、继承泛型)就必须使用实参,而泛型的实参就是具体的类型,像String、Integer等具体的类型(当然也可以是自定义类型);
  4. 泛型定义的时候使用形参,例如:public class MyGeneric { … } // T就是一个自己随意命名的类型形参
  5. 使用泛型的时候必须传入实参:
  6. 定义引用(对象)的时候毫无疑问,肯定需要传实参:ArrayList list = …; // 必须用具体的类型,像这里就是String来代替形参,即实参
  • 实现/继承一个泛型接口/类的时候:
  1. 你在实现/继承一个接口/类的时候实际上是在使用该接口/类,比如:public class Son extends Father { … }中Father这个类就是正在被使用,毫无疑问,必定是在使用;
  2. 因此泛型其实无法继承/实现,因为在实现/继承的时候必须为泛型传入类型实参,给定实参后它就是一个具体的类型了,就不再是泛型了

示例:public class MyType extends MyGeneric { … } // implements、extends的时候必须传入类型实参,因为实在使用泛型!!

原则上,任何编程语言都不允许泛型模板层层继承!!

继承之后,父类/接口中的所有方法中的类型参数都将变成具体的类型,你在子类中覆盖这些方法的时候一定要用具体的类型,不能继续使用泛型的类型形参了

  • 泛型参数继承:
  1. 上面派生出来的类不是泛型,是一个实体类型,因为其继承的泛型是具有类型实参的,而Java还支持一种特殊的语法,可以让你从泛型继续派生出泛型,而泛型的类型参数可以继续传承下去;
  2. 语法如下:
class Father<T> { ... }class Son<T> extends Father<T> { ... }
  1. 即子泛型可以传承父泛型的泛型参数,那么在子类中泛型参数T就和父类的完全相同,还是照常使用(和父类一样正常使用);
  • 注意:
  1. 这里extends Father了,因此父类泛型Father就是被使用了,而按照之前讲的规则,使用给一个泛型是必须要指定类型实参的!因此这里的这个语法是一种特殊语法,Java专门为这种语法开了后门,这种语法只有在类型参数传承的时候才会用到(即上面这种应用);
  2. 一旦使用了这种语法,就表示要进行类型参数的传承了(即父类的T传递给子类继续使用,因此子类也是一个跟父类一样的泛型);
  3. 并且一旦使用了这种语法,那么子类定义中的Son和extends Father中的类型参数必须和定义父类时的类型参数名完全一样!!
    以下三种情况全部错误(全部发生编译报错):
class Father<T> { }
class Son<E> extends Father<T> { }
class Father<T> { }
class Son<T> extends Father<E> { }
class Father<T> { }
class Son<E> extends Father<E> { }

必须全部使用和父类定义相同的类型参数名(T)!才行,这是Java语法的特殊规定;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无奈的码农

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

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

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

打赏作者

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

抵扣说明:

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

余额充值