1、定义:泛型的本质是参数化类型,就是将类型由原来的具体的类型参数化,这种参数类型可以用在类、接口、方法中,分别称为泛型类、泛型接口、泛型方法;

2、泛型类:泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分,最典型的就是各种容器类,List、Set、Map;

 public class Box<T>{
private T t; public T getT() {
return t;
} public void setT(T t) {
this.t = t;
}
}

a、泛型的类型参数只能是引用型类型<Integer>、<Double>(包括自定义类)等,不能是原始类型<int>、<double>等;

b、实例化泛型类时,必须指定 T 的具体类型;

c、参数化类型 T 可以写成任意字符,常用的 T 、E、K、V等表示泛型;

3、泛型接口:泛型接口与泛型类的定义及使用基本相同;

 public interface Box<T> {
public T next();
}

a、实现泛型接口的类未传入泛型实参时,在声明此类的时候,需将泛型的声明也加到类中;

 class B<T> implements Box<T>{
@Override
public T next() {
return null;
}
}

b、实现泛型接口的类传入泛型实参时,需将所有使用泛型的地方都要换成实参类型;

 public class B implements Box<String> {

     private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

     @Override
public String next() {
return null;
}
}

4、泛型方法:调用方法的时候,指明泛型的具体类型;

 // 泛型类
class Box<T> {
/**
* 在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型,可以类型与T相同,也可以不同。
* 由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,编译器也能够正确识别泛型方法中识别的泛型。
*/
public <E> void B_1(E t) {
System.out.println(t.toString());
} /**
* 在泛型类中声明了一个泛型方法,使用泛型T,注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。
*
*/
public <T> void B_2(T t) {
System.out.println(t.toString());
} // 不是泛型方法
public void B_3(T t){
System.out.println(t.toString());
}
}

a、所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在上面例子中的<E>、<T>);

b、只有声明了<T>、<E>的方法才是泛型方法(B_1、B_2),泛型类中使用泛型的成员方法不是泛型方法(B_3);

c、<T>、<E>表明该方法将使用泛型类型T、E,此时才可以在方法中使用泛型类型T、E;

d、泛型方法体的声明和其他方法一样,只能是引用型类型,不能是原始类型(int、double,char等);

5、泛型上下边界:在使用泛型的时候,我们还可以为传入的泛型类型实参进行上下边界的限制,如:类型实参只准传入某种类型的父类或某种类型的子类;为泛型添加上边界,即传入的类型实参必须是指定类型的子类型;

 // 泛型类
class Box<T extends Number> {
private T t;
public Box(T t){
this.t = t;
}
public T getT(){
return t;
}
}
Box<Integer> b = new Box<Integer>(1000);// Integer类型是Number类型的子类————正确
Box<String> s = new Box<String>("1000");// String类型不是Number类型的子类————错误

6、类型通配符:一般是使用 ?代替具体的类型参数,?是类型实参,和Integer、Number一样都是一种实际的类型,?可以看成所有的类型的父类(List<?> 在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类);

 public static void main(String[] args) {
Box b = new Box();
List<String> sLst = new ArrayList<String>();
sLst.add("100");
List<Integer> iLst = new ArrayList<Integer>();
iLst.add(100);
List<Number> nLst = new ArrayList<Number>();
nLst.add(1000);
b.BPrint(sLst);
b.BPrint(iLst);
b.BPrint(nLst);
} /**
* <? extends T>表示该通配符所代表的类型是T类型的子类
* <? super T>表示该通配符所代表的类型是T类型的父类
*/
class Box {
public void BPrint(List<?> lst) {
System.out.println(lst);
}
}

最新文章

  1. SpringMVC基础入门
  2. 成员变量NSString类型指针的属性为什么用copy(属性)
  3. PAT-乙级-1036. 跟奥巴马一起编程(15)
  4. nginx错误日志error_log日志级别
  5. 磁盘阵列RAID
  6. AudioServicesPlaySystemSound音频服务—b
  7. return break continue 的区别
  8. [置顶] 小伙伴们来自己实现LinkedList
  9. redmine的邮件配置
  10. UILabel设定行间距方法
  11. 【English】十四、英语
  12. .net core高性能通讯开源组件BeetleX
  13. 基于React-Native0.55.4的语音识别项目全栈方案
  14. java课堂笔记
  15. JavaScript中 return; 、return false; 与return true的区别
  16. ChibiOS/RT 2.6.9 CAN Low Level Driver for STM32
  17. codevs 2292 图灵机游戏
  18. VMware 克隆网卡无法启动
  19. 回顾经典问题算法:LIS, LCS-(DP类别)
  20. 负margin应用案例几则(转载+总结)

热门文章

  1. 2016集训测试赛(二十四)Problem C: 棋盘控制
  2. workflow engine Ruote初体验之三(条件与美元符号)
  3. mysql之group by,order by
  4. 解决vagrant不能正常挂载目录的问题
  5. Scut游戏服务器引擎6.1.5.6发布,直接可运行,支持热更新
  6. NVIDIA&#174; Quadro&#174; 四路缓冲 3D立体方案
  7. CentOS6.5环境配置笔记
  8. 【Salvation】—— 项目策划&amp;市场分析
  9. 2017.2.28 activiti实战--第六章--任务表单(二)外置表单
  10. C#网络编程:Socket编程