- 浏览: 516144 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (114)
- C基础 (1)
- C指针 (0)
- C语言库函数相关 (1)
- Linux (2)
- Linux网络编程 (1)
- PostgreSQL (0)
- Redis (2)
- Java Web (2)
- JAVA基础 (35)
- Ubuntu (8)
- Android (2)
- MySQL (3)
- 日志 (1)
- 书虫 (1)
- 数据结构 (0)
- 算法 (0)
- 开发工具 (1)
- 转载 (13)
- 英语 (18)
- tomcat启动脚本分析 (3)
- Oracle基础 (4)
- tomcat源码分析 (3)
- tomcat (1)
- Java相关 (1)
- Oracle基本原理--Oracle体系结构 (0)
- Oracle基本原理--表 (0)
- Oracle基本原理--索引 (0)
- Oracle基本原理--事务 (0)
- Oracle开发--SQL (1)
- Oracle基本原理--PL/SQL (0)
- Oracle基本原理--常用函数 (0)
- Oralce管理--用户及权限管理 (0)
- Oracle管理--安装调试 (0)
- Oracle管理--备份恢复 (0)
- Oralce管理--数据迁移 (0)
- Oracle管理--闪回 (0)
- Oracle管理--故障处理 (0)
- Oracle优化原理--统计信息 (0)
- Oracle优化原理--执行计划 (0)
- Oracle优化原理--诊断工具 (0)
- Oracle优化原理--深入理解表 (0)
- Oracle优化原理--深入理解索引 (0)
- Oracle优化原理--表连接原理 (0)
- Java--OOP (0)
- Java--异常 (0)
- Java--泛型 (0)
- Java--集合 (0)
- Java--IO (0)
- Java--枚举类型 (0)
- Java--注释 (0)
- Java--多线程 (0)
- Java--XML (0)
- Java--JDBC (3)
- Servlet (0)
- JSP (0)
- JSTL (0)
- 设计模式 (0)
- DAO与MVC (0)
- Javascript (2)
- Ajax (0)
- JQuery (0)
- HTML/CSS (0)
- 前端相关 (1)
- HTTP (0)
- TCP/IP (0)
- GO基础 (0)
最新评论
-
jsonmong:
推荐一个开发平台,采用的是插件化的设计思想,效果很不错的。ht ...
构建Java Web开发环境 -
wxm198427:
首先表示辛苦了!我想问个问题:我的是windows 7 x64 ...
Oracle 11g R2 for Win7旗舰版(64位)的安装步骤 -
握着橄榄枝的人:
我之前按照你的update mysql.user set pa ...
Windows7下MySQL5.5.20免安装版的配置 -
confident_f:
安装了32的客户端后,用plsql导入导出表有问题,生成不了d ...
Oracle 11g R2 for Win7旗舰版(64位)的安装步骤 -
confident_f:
安装数据库的时候第9步卡住了 是怎么回事呢?
Oracle 11g R2 for Win7旗舰版(64位)的安装步骤
泛型(core java 笔记)
- 博客分类:
- JAVA基础
1.为什么引入泛型
结果:
以上的测试,可以看出Java SE 5.0之前,对ArrayList的使用存在两个问题:
(1)当获取一个值(使用get()方法)时,必须进行强制类型转换
(2)没有错误检查,可以添加任何对象。
泛型提供了一个更好的解决方案:类型参数(type parameters)
ArrayList类有一个类型参数用来指示元素的类型:
ArrayList<String> al = new ArrayList<String>();
当调用get方法时不需要强制类型转换;使用add方法时,编译器将检查元素的类型。
结果:
2.简单泛型类的定义
一个泛型类(generic class)就是具有一个或多个类型变量(type variables)的类。
例如:Pair<T>泛型类型
Pair类引入了一个类型变量T,用尖括号(<>)括起来,并放在类名后面。
泛型类可以有多个类型变量:
public class Pair<T, U>{...}
类定义中的类型变量可指定方法的返回值以及域和局部变量的类型:
public T getFirst(){}
praivate T first;
public void setFirst(T newValue){}
注释:类型变量使用大写形式,且比较短,这是很常见的。在Java库中,使用变量E表示集合的元素类型,K和V表示表的关键字与值的类型。T(需要时还可以用临时的字母U和S)表示“任何类型”。
用具体的类型替换类型变量就可以实例化泛型类型,例如:
Pair<String>
可以将结果(Pair<String>)想象成带有构造器的普通类:
Pair<String>()
Pair<String>(String, String)
和方法:
String getFirst()
String getSecond()
void setFirst(String)
void setSecond(String)
使用Pair类:
计算静态的minmax方法遍历数组,并计算出最小值和最大值,用一个Pair对象返回这两个结果。
结果:
3.泛型方法
前面已经介绍了如何定义一个泛型类,下面介绍定义一个带有类型参数的方法:
这是一个泛型方法。
泛型方法的格式:
泛型方法可以定义在普通方法中,也可以定义在泛型类中。
当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型:
在这种情况下(实际也是大多数情况)下,方法调用中可以省略<String>类型参数。编译器有足够的信息能够推断出所调用的方法。它用names的类型(即String[])与泛型类型T[]进行匹配并推断出T一定是String。也就是说,可以调用
大多数情况下,对于泛型方法的类型引用没有问题。偶尔,编译器也会提示错误,此时需要编译错误报告。
4.类型变量的限定(Bounds for Type Variables)
有时候,类或方法需要对类型变量加以约束。
计算数组中最小的元素:
这里存在一个问题。方法min中,变量smallest的类型为T,这意味着其可以是任何一个类型的对象,由此便不能确定T所属的类型是否有compareTo方法。因此此处会提示编译错误:
解决方案:将T限制为实现了Comparable接口(只含一个方法compareTo的标准接口)的类。可以通过对类型变量设置限定(bound)实现这一点:
实际上Comparable接口本身就是一个泛型类型。目前,我们忽略其复杂性以及编译器产生的警告。
现在,泛型的min方法只能被实现了Comparable接口的类(如String、Date等)的数组调用。
表示T应该是绑定类型(bounding type)的子类型(subtype)。T和绑定类型可以是类,也可以是接口。
一个类型变量或通配符可以有多个限定(multiple bounds),例如
限定类型(bounding types)用“&”分隔,而逗号用来分隔类型变量(type variables)。
在Java的继承中,可以有任意多个接口超类型,但最多只有一个限定是类。如果有一个类作为限定,它必须是限定列表中的第一个。
(As with Java inheritance, you can have as many interface supertypes as you like, but at most one of the bounds can be a class. If you have a class as a bound, it must be the first one in the bounds list. )
例子:重新编写一个泛型方法minmax,该方法计算出泛型数字中的最小值和最大值,并返回Pair<T>。
5.泛型代码与虚拟机
虚拟机没有泛型类型对象——所有对象都属于普通类。
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型(raw type)。原始类型的名字就是移除类型参数(type parameters)后的泛型类型名。类型变量(type variables)被擦除(erased),并且被替换为它的限定类型(bounding types)(或者是Object对于无限定的变量)。
例如,Pair<T>的原始类型如下;
因为T是一个无限定的变量(unbounded type variable),所以直接使用Object替换。
结果是一个普通的类,就好像泛型引入Java语言之前已经实现的那样。
在程序中可以包含不同类型的Pair,例如,Pair<String>或Pair<Integer>。而擦除类型后就变成原始的Pair类型了。
package generic; import java.util.ArrayList; public class ArrayListTest{ public static void main(String[] args){ ArrayList al = new ArrayList(); al.add(1); System.out.println(al); Integer i1 = (Integer)al.get(0); System.out.println(i1); al.add("hello"); /* * 下面的代码编译正确,运行时报错 * Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer * */ Integer i2 = (Integer)al.get(1); System.out.println(i2); } }
结果:
[1] 1 Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at generic.ArrayListTest.main(ArrayListTest.java:18)
以上的测试,可以看出Java SE 5.0之前,对ArrayList的使用存在两个问题:
(1)当获取一个值(使用get()方法)时,必须进行强制类型转换
(2)没有错误检查,可以添加任何对象。
泛型提供了一个更好的解决方案:类型参数(type parameters)
ArrayList类有一个类型参数用来指示元素的类型:
ArrayList<String> al = new ArrayList<String>();
当调用get方法时不需要强制类型转换;使用add方法时,编译器将检查元素的类型。
package generic; import java.util.ArrayList; public class ArrayListTest2{ public static void main(String[] args){ ArrayList<Integer> al = new ArrayList<Integer>(); al.add(1); System.out.println(al); Integer i1 = (Integer)al.get(0); System.out.println(i1);//(1) /* 下面的代码编译时报错 * The method add(Integer) in the type ArrayList<Integer> is not applicable for the arguments (String) * */ //al.add("hello"); //Integer i2 = (Integer)al.get(1); //System.out.println(i2); } }
结果:
[1] 1
2.简单泛型类的定义
一个泛型类(generic class)就是具有一个或多个类型变量(type variables)的类。
例如:Pair<T>泛型类型
package generic; public class Pair<T>{ private T first; private T second; public Pair(){ this.first = null; this.second = null; } public Pair(T first, T second){ this.first = first; this.second = second; } public void setFirst(T newValue){ this.first = newValue; } public T getFirst(){ return this.first; } public void setSecond(T newValue){ this.second = newValue; } public T getSecond(){ return this.second; } }
Pair类引入了一个类型变量T,用尖括号(<>)括起来,并放在类名后面。
泛型类可以有多个类型变量:
public class Pair<T, U>{...}
类定义中的类型变量可指定方法的返回值以及域和局部变量的类型:
public T getFirst(){}
praivate T first;
public void setFirst(T newValue){}
注释:类型变量使用大写形式,且比较短,这是很常见的。在Java库中,使用变量E表示集合的元素类型,K和V表示表的关键字与值的类型。T(需要时还可以用临时的字母U和S)表示“任何类型”。
用具体的类型替换类型变量就可以实例化泛型类型,例如:
Pair<String>
可以将结果(Pair<String>)想象成带有构造器的普通类:
Pair<String>()
Pair<String>(String, String)
和方法:
String getFirst()
String getSecond()
void setFirst(String)
void setSecond(String)
使用Pair类:
计算静态的minmax方法遍历数组,并计算出最小值和最大值,用一个Pair对象返回这两个结果。
package generic; public class ArrayAlg{ public static Pair<String> minmax(String[] a){ if(a == null || a.length == 0) return null; String min = a[0]; String max = a[0]; for(int i = 1; i < a.length; i++){ if(min.compareTo(a[i]) > 0){ min = a[i]; } if(max.compareTo(a[i]) < 0){ max = a[i]; } } return new Pair<String>(min, max); } //test public static void main(String[] args){ String[] words = {"Hello", "World", "very", "good"}; Pair<String> mm = ArrayAlg.minmax(words); System.out.println("min = " + mm.getFirst()); System.out.println("max = " + mm.getSecond()); } }
结果:
min = Hello max = very
3.泛型方法
前面已经介绍了如何定义一个泛型类,下面介绍定义一个带有类型参数的方法:
public class ArrayAlg{ public static <T> T getMiddle(T[] a){ return a[a.length / 2]; } }
这是一个泛型方法。
泛型方法的格式:
修饰符 <类型变量1, 类型变量2, ...> 返回值类型 方法名(参数列表){ //方法体 ...... }
泛型方法可以定义在普通方法中,也可以定义在泛型类中。
当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型:
String[] names = {"John", "Q", "Public"}; String middle = ArrayAlg.<String>getMiddle(names); System.out.println(middle);//Q
在这种情况下(实际也是大多数情况)下,方法调用中可以省略<String>类型参数。编译器有足够的信息能够推断出所调用的方法。它用names的类型(即String[])与泛型类型T[]进行匹配并推断出T一定是String。也就是说,可以调用
String middle = ArrayAlg.getMiddle(names);
大多数情况下,对于泛型方法的类型引用没有问题。偶尔,编译器也会提示错误,此时需要编译错误报告。
4.类型变量的限定(Bounds for Type Variables)
有时候,类或方法需要对类型变量加以约束。
计算数组中最小的元素:
public class ArrayAlg{ public static <T> T min(T[] a){ if(a == null && a.length == 0){ return null; } T smallest = a[0]; for(int i = 0; i < a.length; i++){ if(smallest.compareTo(a[i]) > 0){ smallest = a[i]; } } return smallest; } }
这里存在一个问题。方法min中,变量smallest的类型为T,这意味着其可以是任何一个类型的对象,由此便不能确定T所属的类型是否有compareTo方法。因此此处会提示编译错误:
The method compareTo(T) is undefined for the type T
解决方案:将T限制为实现了Comparable接口(只含一个方法compareTo的标准接口)的类。可以通过对类型变量设置限定(bound)实现这一点:
public static <T extends Comparable> T min(T[] a){...}
实际上Comparable接口本身就是一个泛型类型。目前,我们忽略其复杂性以及编译器产生的警告。
现在,泛型的min方法只能被实现了Comparable接口的类(如String、Date等)的数组调用。
<T extends Bounding Type>
表示T应该是绑定类型(bounding type)的子类型(subtype)。T和绑定类型可以是类,也可以是接口。
一个类型变量或通配符可以有多个限定(multiple bounds),例如
T extrnds Comparable & Serializable
限定类型(bounding types)用“&”分隔,而逗号用来分隔类型变量(type variables)。
在Java的继承中,可以有任意多个接口超类型,但最多只有一个限定是类。如果有一个类作为限定,它必须是限定列表中的第一个。
(As with Java inheritance, you can have as many interface supertypes as you like, but at most one of the bounds can be a class. If you have a class as a bound, it must be the first one in the bounds list. )
例子:重新编写一个泛型方法minmax,该方法计算出泛型数字中的最小值和最大值,并返回Pair<T>。
package generic; public class ArrayAlg1{ public static <T extends Comparable> Pair<T> minmax(T[] a){ if(a == null || a.length == 0 ){ return null; } T min = a[0]; T max = a[0]; for(int i = 0; i < a.length; i++){ if(min.compareTo(a[i]) > 0){ min = a[i]; } if(max.compareTo(a[i]) < 0){ max = a[i]; } } return new Pair<T>(min, max); } //test public static void main(String[] args){ String[] words = {"Hello", "World", "very", "good"}; Pair<String> mm = ArrayAlg1.minmax(words); System.out.println("min = " + mm.getFirst()); System.out.println("max = " + mm.getSecond()); } }
5.泛型代码与虚拟机
虚拟机没有泛型类型对象——所有对象都属于普通类。
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型(raw type)。原始类型的名字就是移除类型参数(type parameters)后的泛型类型名。类型变量(type variables)被擦除(erased),并且被替换为它的限定类型(bounding types)(或者是Object对于无限定的变量)。
例如,Pair<T>的原始类型如下;
public class Pair{ private Object first; private Object second; public Pair(Obejct first, Object second){ this.first = first; this.second = second; } public Object getFirst(){ return this.first; } public void setFirst(Object newValue){ this.first = first; } public Object getSecond(){ return this.second; } public void setSecond(Object newValue){ this.second = newValue; } }
因为T是一个无限定的变量(unbounded type variable),所以直接使用Object替换。
结果是一个普通的类,就好像泛型引入Java语言之前已经实现的那样。
在程序中可以包含不同类型的Pair,例如,Pair<String>或Pair<Integer>。而擦除类型后就变成原始的Pair类型了。
发表评论
-
foreach循环
2013-06-24 16:15 1439从JDK1.5开始,Java提供了一个更简单的循环:forea ... -
可变参数
2013-06-24 15:38 1201从JDK1.5开始,Java允许使用可变参数为方法指定数量不确 ... -
两个程序的说明
2010-10-19 09:26 11351、程序1的结果是: clas ... -
构造器初始化
2010-10-18 14:42 1484可以用构造器来进行初始化。在运行时刻,可以调用方法或执行某些动 ... -
成员初始化
2010-10-18 07:55 1205Java尽力保证:所有变量在使用前都能得到恰当的初始化。 对 ... -
线程的死锁
2010-10-11 19:21 1470当两个线程相互等待对方释放同步监视器时就会发生死锁,Java虚 ... -
线程的同步
2010-10-11 19:00 1253一个经典的关于线程安全性的问题:银行取钱问题。 银行取钱的基 ... -
java网站收集
2010-10-10 18:13 1232JAVA开发者最常去的25个英文网站:http://www.i ... -
控制线程
2010-10-10 16:06 19951、线程睡眠:sleep 如果我们需要让当前正在执行的线程暂 ... -
线程的状态
2010-09-28 19:00 1006线程从创建到执行完毕的整个过程称为线程的生命周期,在整个生命周 ... -
Java中Thread类的start()和run()的区别
2010-09-27 15:33 40871、start()方法来启动线程,真正实现了多线程运行,这时无 ... -
Java中创建线程的两种方法
2010-09-26 10:18 5617在Java中创建线程有两种方法:继承Thread类和实现Run ... -
创建String对象过程的内存分配小结
2010-09-23 20:32 2752常量池(Constant Pool):指的是在编译期被确定,并 ... -
Java堆和栈的区别 经典总结(转载)
2010-09-18 16:48 1247栈与堆都是Java用来在Ram中存放数据的地方。 与C++不 ... -
Java初学者都必须理解的七大问题
2010-09-18 10:36 1102问题一:我声明了什么 ... -
关于计算java程序运行时间(转载)
2010-09-18 09:22 1097//第一种,伪代码 long startTime= ... -
for循环的优化
2010-09-17 20:29 2118在程序中经常用到for循环,当一些算法实时性要求非常高时,对f ... -
详细解析Java中抽象类和接口的区别(转载)
2010-09-17 10:16 1082在Java语言中,abstract class和inter ... -
集合类(四):Map集合
2010-09-16 20:26 21265、Map集合 Map集合为映射类型,映射与集和列表有明显的区 ... -
集合类(三):Set集合
2010-09-16 19:43 28784、Set集合 Set集合为集类型,集是最简单的一种集合,存放 ...
相关推荐
Java Generics and Collections 英文版,详细描述java 泛型技术
java泛型集合 java集合 集合 java Collection 排序 集合排序
Java 实现泛型List的源码,基本实现了List接口的全部所有方法。欢迎大家发表自己的观点和建议。
java泛型详解java泛型详解
Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战...
Java泛型编程指南.pdf 此文章译自SUN的泛型编程指南
Java中的泛型结构请大家指教并指导有不足的地方给予赐教。
Java 运行时如何获取泛型参数的类型 Java类型Type 之 ParameterizedType,GenericArrayType,TypeVariabl,WildcardType 从实现的接口获取泛型参数 定义一个泛型父类: public interface SuperClass { String ...
jdk新东东,java泛型知识学习。 jdk新东东,java泛型知识学习。 jdk新东东,java泛型知识学习。
java 带两个类型参数的泛型 java 带两个类型参数的泛型
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
JAVA泛型笔记.pdf
详细的介绍了Java是伪泛型的原因,介绍了类型擦除的内容等。
java中的泛型应用度极广,每一个web应用都有它的身影,可见泛型重要性!
Java中的泛型,在运行时刻其具体类型是被擦除的,这样我们就不能用new T(),instanceof等关操作,特别是对泛型类型的类的实例化问题,在此根据《Thinking in Java》中所讲的对类型擦除所带来问题的三种解决方案,比较...
day02【Collection、泛型】-笔记.md
深入理解java泛型,包括类名泛型的定义,方法泛型定义,泛型的返回
基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码....
第8章 泛型与Java集合
Java泛型学习笔记.pdf