1. 泛型的简单运 用和意义
2. 泛型的上限与下限
3. 泛型和 子类继承的限制
4. 泛型类和泛型 方法
5. 泛型嵌套和泛型擦除
泛型(Generic)
什 么是泛型:
•java5开始出现的 一种对Java语 言类型的 一种拓 展,以 支持创建可以按类型进 行 参数化的类.可以把类型参数看作是使 用参数类型时指定的类型占位符,就好 比 方法的形式参数是实际参数的占位符 一样.
•泛型能保证 大型应 用程序的类型安全和良好的维护性;使 用泛型的优势:
•类型安全,使编译器 对泛型定义的类型做判断限制.如保证TreeSet 里 的元素类型
必须 一致;
•消除强制类型的转换,如,使 用Comparable 比较时每次都需要类型强转;
泛型类
在类声明时通过 一个标识符表示类中某个字段的类型或者某个 方法的返回值或参数的类型,这样在类声明或实例 化的时候只要指定 自 己需要的类型就ok。
声明带泛型的类: class 类名<泛型类型1,泛型类型2……>{
泛型类型 变量 名;泛型类型 方法名(){}
返回值类型 方法名(泛型类型 变量 名){}
}
使 用带泛型的类:
类名<具体类> 对象名 = new 类名<具体类>();
注意:
类型参数规范:推荐使 用规范-常 见的泛型,泛型只保存在源 文件中,class 文件中不 存在;也就是说在编译阶段就会丢失,基本数据类型不 能作为泛型类型;
K 键, 比如映射的键 key的类型
V 值, 比如Map的值 value类型
E 元素, 比如Set<E> Element表示元素,元素的类型
T 泛型,Type的意思
思考List<Object> l 和 List<String> l 是否可以运 行
通配符
在进 行 引 用传递的时候泛型类型必须匹配才可以传递,否则编译不 通过;使 用 ? ,表示未知类型的泛型对象:
•List<?> 表示未知元素的List集合;
•这种带通配符的List仅表示各种泛型List的 父类,并不 能把元素添加 入集合中;
•List<?> list = new ArrayList<>(); list.add(1);//ERROR 编译器 无法基于信息作类型推断
public void show(List<?> list){}
•//表示可接受任意类型的List集合
泛型的上限与下限
设置泛型对象的上限使 用extends,表示参数类型只能是该类型或该类型的 子类:
•声明对象:类名<? extends 类> 对象名
•定义类:类名<泛型标签 extends 类>{}
设置泛型对象的下限使 用super,表示参数类型只能是该类型或该类型的 父类:
•声明对象:类名<? super 类> 对象名称
•定义类:类名<泛型标签 extends类>{}
public static void show(List<? extends Number> l){
}
public static void show(List<? super String> l){
}
public static void main(String[] args) { Person<Integer> p1 = new Person<>(); p1.setVal(99);
Person<Double> p2 = new Person<>(); p2.setVal(3.14);
Person<String> p3 = new Person<>(); p3.setVal("007");
show(p1);//√ show(p2);//√ show(p3);//×
}
public static void show(Person<? extends Number> p){ System.out.println(p.getVal());
}
public static void main(String[] args) { Person<Integer> p1 = new Person<>(); p1.setVal(99);//Integer Person<Double> p2 = new Person<>(); p2.setVal(3.14);//Double
Person<String> p3 = new Person<>(); p3.setVal("007");//String Person<Object> p4 = new Person<>(); p4.setVal(new Object());//Object show(p1);//×
show(p2);//× show(p3);//√ show(p4);//√
}
public static void show(Person<? super String> p){ System.out.println(p.getVal());
}
泛型接 口
java5后,可以声明泛型接 口,声明 方式和声明泛型类是 一样的。
•public interface IDAO<T>{}
泛型接 口 子类有两种 方式:
•直接在 子类后申明泛型;
•在 子类实现的接 口中给出具体的泛型类型
public class DaoImpl<T> implements IDAO<T>{
}
public class DaoImpl implements IDAO<String> {
}
泛型 方法
方法中可定义泛型参数,形参的参数类型就是实参的类型。格式:
•<泛型标签> 返回值类型 方法名([泛型标签 参数]...)
public static <T> T show(T param){ return param;
}
.....main.....{ System.out.println(show(new Date())); System.out.println(show("cditcast"));
}
泛型使 用
通过泛型 方法返回泛型对象
•此时必须在 方法返回类型处明确给出具体类型统 一传 入的参数类型泛型数组
public <T> T[] show(T[] ts) {
}
public <T> void show(T ... ts){
}
泛型的嵌套
可以从 一个类的泛型中指向另 一个类的泛型:
public class Demo1 {
public static void main(String[] args) { Map<String,String> map = new HashMap<>(); map.put("1", "A");
map.put("2", "B"); map.put("3", "C"); map.put("4", "D");
Set<Map.Entry<String, String>> set = map.entrySet(); Iterator<Map.Entry<String, String>> it = set.iterator(); while(it.hasNext()) {
Map.Entry<String, String> entry = it.next(); System.out.println(entry.getKey() +"-->" + entry.getValue());
}
}
}
泛型的擦除
在严格的泛型代码 里 ,带泛型声明的类总应该带着类型参数。但是为了 和 老 的Java代码保持 一致,也允许在使 用带泛型声明的类时不 指定类型参数,若没有为这个泛型类指定类型参数则该类型参数被称做 一个原始类型,默认是该声明参数时指定的最上限类型;
当把 一个具有泛型信息的对象赋给另 一个没有泛型信息的变量 时,则所有在尖括号之间的类型信息都被扔掉。
• 比如List<String> 类型转换成List,则该List对集合元素的类型检查变成了 变量 的上限即Object。
泛型的擦除和转换
class Num<T extends Number>{
private T t;
public Num(T t) {
this.t= t;
}
。。。。 getter/setter。。。。
}
public class Demo{
public static void main(String[] args) {
Num<Integer> n= new Num<>(5);
Integer i= n.getT();
Num n2 = n;//会丢掉泛型信息
Number num= n2.getT();
//Integer i= n2.getT();
}
}
public class Demo{
public static void main(String[] args) {
List<Integer> li= new ArrayList<>();
li.add(1);
List<String> ls= null;
//ls= li;不能转换
List list= li;
ls= list;//不会报错,只有未经检查警告,此时l ist实际引用的是List<Integer>
System.out.println("-->" + ls.get(0));//企图当做String类型对象取出
}
}
- 面向对象(java菜鸟的课堂笔记)
类:相同的东西放在一起 分为属性和动作: 把一组或多组事物相同的特性的描述==>类 属性和动作被称为成员: //声明类的属性信息 public class **{ String name: ...
- java中的一些规则(菜鸟的课堂笔记)
ls 查看目录下文件 java规则 代码都定义在类中,用class定义 禁止一个源文件写两个类: 一个源文件中,只能有一个类文件是pubic: 一个源文件中如果有多个类,编译完之后会产生多个class ...
- java GUI (课堂笔记)
关于java GUI Swing组件: JFrame 窗口组件 JLabel 标签 JButton 按钮组件 JTextField 单行文本框 系统控件(JDK自带) 自定义控件(模仿系统控件): 继 ...
- 线程(java课堂笔记)
1.两种方式的差异 2.线程的生命周期 3.线程控制(线程的方法) 4.线程同步 5.线程同步锁 一. 两种方式的差异 A extends Thread :简单 不能再继承其他类了(Java单继承)同 ...
- Java课堂笔记(零):内容索引
回想自己学习和使用Java的时间也是很长了.本科期间课堂上浅尝辄止地学习了点皮毛,后来也是搁置不用,未曾深入研究.研究生期间因为项目和实习的原因,基本算是重新拾起Java这门语言,并且接触到了Spri ...
- Java基础进阶:内部类lambda重点摘要,详细讲解成员内部类,局部内部类,匿名内部类,Lambda表达式,Lambda表达式和匿名内部类的区别,附重难点,代码实现源码,课堂笔记,课后扩展及答案
内部类lambda重点摘要 内部类特点: 内部类可以直接访问外部类,包括私有 外部类访问内部类必须创建对象 创建内部对象格式: 外部类.内部类 对象名=new外部类().new内部类(); 静态内部类 ...
- Java基础进阶:多态与接口重点摘要,类和接口,接口特点,接口详解,多态详解,多态中的成员访问特点,多态的好处和弊端,多态的转型,多态存在的问题,附重难点,代码实现源码,课堂笔记,课后扩展及答案
多态与接口重点摘要 接口特点: 接口用interface修饰 interface 接口名{} 类实现接口用implements表示 class 类名 implements接口名{} 接口不能实例化,可 ...
- Android菜鸟的成长笔记(13)——异步任务(Async Task)
原文:[置顶] Android菜鸟的成长笔记(13)——异步任务(Async Task) Android的UI线程主要负责处理用户的事件及图形显示,因此主线程UI不能阻塞,否则会弹出一个ANR(App ...
- 九章算法系列(#3 Binary Tree & Divide Conquer)-课堂笔记
前言 第一天的算法都还没有缓过来,直接就进入了第二天的算法学习.前一天一直在整理Binary Search的笔记,也没有提前预习一下,好在Binary Tree算是自己最熟的地方了吧(LeetCode ...
随机推荐
- 用 parseInt()解决的 小 bug
在做轮播模块的时候遇到问题是:你在 连续指示小按钮 时候再去 只有 点击 下一张按钮,出现bug: 指示小按钮的 className 当前显示的 calssName 为 undefined ! // ...
- servlet:从入门到实战学习(1)---全·环境配置
最近公司忙加班学习,学校忙助教工作,博客鸽了好久,后端学习工作过程中学了好多东西,趁着工作之余得空补补博客,算是整理下学习的东西. javaweb的后端研发需要学习的是tomcat+servlet+j ...
- three.js提供的几何体
1.简单几何体 three.js提供的稍微简单点的几何体包括有:PlaneGeometry(平面).CircleGeometry(圆形).ShapeGeometry(塑性).CubeGeometry( ...
- JS的内置对象以及JQuery中的部分内容
[js中的数组] 1 数组的概念:可以再内存中连续存储的多个有序元素的结构 元素的顺序:称为下标,通过下标查找对应元素. ...
- 解决Javascript大数据列表引起的网页加载慢/卡死问题。
在一些网页应用中,有时会碰到一个超级巨大的列表,成千上万行,这时大部份浏览器解析起来就非常痛苦了(有可能直接卡死). 也许你们会说可以分页或动态加载啊?但是有可能需求不允许分页,动态加载?网络的延迟也 ...
- Android之AIDL知识总结
1.AIDL介绍 AIDL是一个缩写,全称是Android Interface Definition Language,翻译为Android接口定义语言.主要用于线程之间的通信,本文主要以不同应用之间 ...
- JS作用域就这么几句话
JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...
- Springmvc的工作流程
1.向服务器发送http请求,请求被前端控制器DispatcherServlet捕获. 2.DispatcherServlet根据servlet.xml中的配置进行URL解析后,得到(URL),然后根 ...
- (函数封装)获取class名称
使用原生JavaScript,获取类操作符时:即使使用getElementByClassName,在Firefox和IE9以下是不兼容的.Firefox下是可以用它获取的到元素而IE不行,一般框架都会 ...
- Docker 打包 部署
Docker 打包 部署 一贯的开场白,大家好: 开始学习Spring Boot ,同时也再学习 Maven 自动化构建. 项目的部署环境是 Linux 服务器,Docker容器. 之所以写这篇博客 ...