1.  泛型类

public class Pair<T>
{
private T first;
private T second; public void setSecond(T second){...}
....
}

2.  泛型方法

class ArrAlg{
public static <T> T getMiddle(T... a){
return a[a.length/2];
}
}

3.   类型变量的限定

public static <T extends BoundingType1 & BoundingType2 ...> T min(T[] a)....

这表示T应该是BoundingType类型的子类型。T和绑定类型可以是类,也可以是接口 。一个类型变量或通配符可以有多个限定,但限定中之多只有一个类,这是因为单继承,当有多个限定时,基类要写在第一个,接口写在后面。

4.  原始类型,任何一个泛型类型,都自动提供一个原始类型,原始类型的名字就是删去类型参数后的类型名。例如Pair<T>, 原始类型就是Pair。

5.  泛型转换

  •   虚拟机中没有泛型,只有普通的类和方法
  • 所有的类型参数都用它们的第一个限定类型替换,没有写明限定类型就用Object
  • 合成桥方法保持多态。
  • 为保持类型安全性,必要时插入强制类型转换(例如调用泛型方法返回值)

5.  桥方法

假设有下列类继承了Pair<Date>,

class DateInterval extends Pair<Date>
{
public void setSecond(Date second){
.... }
}

实际擦除类型之后

class DateInterval extends Pair
{
public void setSecond(Date second){...} //因为类型擦除,实际还存在一个继承于Pair类的方法,显然这是两个方法
public void setSecond(Object second){
//实际生成桥方法,这里会调用setSecond(Date seconde);即:
setSecond((Date)second);
}
}

当如下调用时 Pair<Date> pair = new DateInterval(...);  pair.setSecond(aDate);。Pair类型只有一个方法setSecond(Object)。实际引用DateInterval类,因而将会调用DateInterval.setSecond(Object)。编译器为了调用最合适的方法,实际上生成了一个桥方法,如下 public void setSecond(Object second){  setSecond((Date) second)  } 。

6.  约束与局限性

  • 不能用基本类型实例化类型参数
  • 运行时类型查询只适用于原始类型
  • 不能创建参数化类型的数组,即不能 new Pair<String> [10]
  • 不能实例化类型变量,即不能使用 new T(...), new T[] 或T.class这类的表达式。可以通过反射实例化T但不能T.class.newInstance(); 可以如下设计API来实现。
public static <T> Pair<T> makePair(Class<T> cl){
try{
return new Pair<>(cl.newInstance(), cl.newInstance())
}catch(Exception e){return null;}
}
  • 泛型类的静态上下文中不能引用类型变量,例如 private static T aData; 或者 public static T fun(){}都是错误的。
  • 不能抛出或捕获泛型类的实例

7.  通配符

  • 通配符限定: extends 、super

例:Pair<? extends Person>表示泛型Pair类型,它的参数是Person的子类。

在这种情况下,getter和setter区别,getter可以正常调用,但是setter不行,会产生编译错误,因为编译器不能确定要传入参数的类型,也没法代替。

?extends Person getFirst()
void setFirst(? extends Person)

反之,通配符的超类型限定: ?super Student

void setFirst(? super Student);
? super Student getFirst();

编译器虽然不知道setFirst的确切类型,但是可以用任意Student对象调用,而不能用Person对象调用。如果调用getFirst,返回的对象不能保证,只能赋给Object。

  • 无限定通配符 Pair<?>
? getFirst();
void setFirst(?);

getFirst的返回值只能赋给一个Object, setFirst不能调用除非setFirst(null),对于一些简单操作非常有用,例如判定是否为null  getFirst() == null

  • 通配符捕获   可以通过泛型方法捕获通配符 

最新文章

  1. 在Centos中部署redis运行状态图形化监控工具 — RedisLive
  2. Servlet和JSP学习指导与实践(二):Session追踪
  3. mybatis generator配置生成代码的问题
  4. C#开发规范总结(个人建议)
  5. Group Shifted Strings
  6. 在AngularJS应用中实现认证授权
  7. C#程序实现动态调用DLL的研究
  8. Centos部署nagios+apache实现服务器监控
  9. Unity光照图UV显示
  10. 编写优质嵌入式C程序
  11. iOS之AFN错误代码1016(Error Domain=com.alamofire.error.serialization.response Code=-1016 &quot;Request failed: unacceptable)
  12. cookie、session、sessionid的区别
  13. CSS设置一行文字,超出部分自动隐藏
  14. SpringMVC之处理流程
  15. css3的动画
  16. Linux DMA Engine framework(3)_dma controller驱动
  17. STM32固件库详解
  18. C++图形开发相关
  19. Jmeter(十八)Logic Controllers 之 Random Controller and Random order Controller
  20. java 日期工具类DateUtils

热门文章

  1. 5-2 Nacos注册中心
  2. HBase学习(二) 基本命令 Java api
  3. 基于ABP实现DDD--领域服务、应用服务和DTO实践
  4. SP96 SHOP-Shopping 题解
  5. while练习题_1到100之间的偶数和
  6. 重写并自定义依赖的原生的Bean方法
  7. 2. 组复制技术架构 | 深入浅出MGR
  8. Reader和Writer区别final.finally.finalize区别
  9. Excel 数学函数(二):ISODD 和 ISEVEN
  10. Taurus.MVC 微服务框架 入门开发教程:项目部署:4、微服务应用程序发布到Docker部署(上)。