JDK5.0新特性
虽然JDK已经到了1.8但是1.5(5.0)的变化是最大的
1.增强for循环
foreach语句foreach简化了迭代器
作用: 对存储对象的容器进行迭代 (数组, collection, map)
1> 格式
增强for循环括号里写两个参数第一个是声明一个变量第二个就是需要迭代的容器
for( 元素类型变量名: Collection集合& 数组) {
...
}
2> 增强for循环和传统for循环的区别
a. 增强for循环在使用时必须要明确被遍历的目标这个目标可以是Collection集合或者数组如果遍历Collection集合在遍历过程中还需要对元素进行操作比如删除需要使用迭代器
b. 如果遍历数组还需要对数组元素进行操作建议用传统for循环因为可以定义角标通过角标操作元素如果只为遍历获取可以简化成增强for循环它的出现为了简化书写
3>增强for循环迭代数组
String[] arr= {"a", "b", "c"}; //数组的静态定义方式 只适用于数组首次定义的时候
for(String s : arr) {
System.out.println(s);
}4>增强for循环迭代单列集合 Collection
List list= newArrayList();
list.add("aaa");//增强for循环 没有使用泛型的集合也能使用增强for循环迭代
for(Object obj : list) {
String s=(String) obj;
System.out.println(s);
}5>增强for循环迭代双列集合 Map
注意: 增强for循环不可以直接遍历map集合 但是可以将map转成set后再使用foreach语句
Map map= newHashMap();
map.put("a", "aaa");//传统方式
Set entrys = map.entrySet(); //获得所有的键值对Entry对象
iter = entrys.iterator(); //迭代出所有的entry
while(iter.hasNext()) {
Map.Entry entry=(Entry) iter.next();
String key= (String) entry.getKey(); //分别获得key和value
String value =(String) entry.getValue();
System.out.println(key+ "=" +value);
}//增强for循环迭代 原则上map集合是无法使用增强for循环来迭代的 因为增强for循环只能针对实现了Iterable接口的集合进行迭代 Iterable是jdk5中新定义的接口 就一个方法iterator方法 只有实现了Iterable接口的类 才能保证一定有iterator方法 java有这样的限定是因为增强for循环内部还是用迭代器实现的 而实际上 我们可以通过某种方式来使用增强for循环
for(Object obj : map.entrySet()) {
Map.Entry entry= (Entry) obj; //obj 依次表示Entry
System.out.println(entry.getKey() + "=" +entry.getValue());
}
6> 集合迭代注意问题
在迭代集合的过程中不能对集合进行增删操作(会报并发访问异常) 可以用迭代器的方法进行操作(子类listIterator 有增删的方法)
7> 增强for循环注意问题
在使用增强for循环时不能对元素进行赋值
int[] arr = {1, 2, 3};
for(intnum : arr) {
num = 0; //不能改变数组的值
}
System.out.println(arr[1]); //2 还是原来的值
2.可变参数(...)
用到函数的参数上当要操作的同一个类型元素个数不确定的时候可是用这个方式这个参数可以接受任意个数的同一类型的数据
和以前接收数组不一样的是
以前定义数组类型需要先创建一个数组对象再将这个数组对象作为参数传递给函数现在直接将数组中的元素作为参数传递即可底层其实是将这些元素进行数组的封装而这个封装动作是在底层完成的被隐藏了所以简化了用户的书写少了调用者定义数组的动作
如果在参数列表中使用了可变参数可变参数必须定义在参数列表结尾(也就是必须是最后一个参数否则编译会失败)
如果要获取多个int数的和可以使用将多个int数封装到数组中直接对数组求和即可
3.静态导入
导入了类中的所有静态成员简化静态成员的书写
importstaticjava.util.Collections.*; //导入了Collections类中的所有静态成员
4.枚举enum
问题: 对象的某个属性的值不能是任意的必须为固定的一组取值其中的某一个
解决办法: (使用枚举)
1> 在setGrade方法中做判断不符合格式要求就抛出异常
2> 直接限定用户的选择通过自定义类模拟枚举的方式来限定用户的输入写一个Grade类私有构造函数对外提供5个静态的常量表示类的实例
3> jdk5中新定义了枚举类型专门用于解决此类问题
4> 枚举就是一个特殊的java类可以定义属性, 方法, 构造函数, 实现接口, 继承类
5.自动拆装箱
java中数据类型分为两种: 基本数据类型, 引用数据类型(对象)
在java程序中所有的数据都需要当做对象来处理针对8种基本数据类型提供了包装类如下
int--> Integer
byte--> Byte
short--> Short
long--> Long
char--> Character
double--> Double
float--> Float
boolean--> Boolean
jdk5以前基本数据类型和包装类之间需要互转
基本---引用Integer x = newInteger(x);
引用---基本intnum = x.intValue();
1> Integer x = 1; x = x + 1; 装箱---> 拆箱---> 装箱
2> 为了优化虚拟机为包装类提供了缓冲池Integer池的大小-128~127一个字节的大小
3> String池Java为了优化字符串操作提供了一个缓冲池
6.泛型
jdk1.5版本以后出现的一个安全机制表现格式: < >
只要带有<>的类或者接口都属于带有类型参数的类或者接口在使用这些类或者接口时必须给<>中传递一个具体的引用数据类型
1> 好处
a. 将运行时期的问题ClassCastException问题转换成了编译失败体现在编译时期程序员就可以解决问题
b. 避免了强制转换的麻烦
2> 泛型技术的本质
其实是应用在编译时期给编译器使用的技术到了运行时期泛型就不存在了
泛型的擦除: 也就是说编辑器检查了泛型的类型正确后在生成的类文件中是没有泛型的
泛型的补偿: 因为存储的时候类型已经确定了是同一个类型的元素所以在运行时只要获取到该元素的类型在内部进行一次转换即可所以使用者不用再做转换动作了
3> 什么时候用泛型类呢?
当类中的操作的引用数据类型不确定的时候以前用的Object来进行扩展的现在可以用泛型来表示这样可以避免强转的麻烦而且将运行问题转移到的编译时期
4> 泛型在程序定义上的体现
//泛型类 将泛型定义在类上
class Tool{privateQ obj;public voidsetObject(Q obj) {this.obj =obj;
}publicQ getObject() {returnobj;
}
}//当方法操作的引用数据类型不确定的时候 可以将泛型定义在方法上
public voidmethod(W w) {
System.out.println("method:" +w);
}//静态方法上的泛型 静态方法无法访问类上定义的泛型 如果静态方法操作的引用数据类型不确定的时候 必须要将泛型定义在方法上
public static voidfunction(Q t) {
System.out.println("function:" +t);
}//泛型接口
interface Inter{voidshow(T t);
}class InterImpl implements Inter{public voidshow(R r) {
System.out.println("show:" +r);
}
}
5> 泛型中的通配符
可以解决当具体类型不确定的时候这个通配符就是? 当操作类型时不需要使用类型的具体功能时只使用Object类中的功能那么可以用? 通配符来表未知类型
6> 泛型限定
上限: ?extendsE 可以接收E类型或者E的子类型对象
下限: ?superE 可以接收E类型或者E的父类型对象
上限什么时候用: 往集合中添加元素时既可以添加E类型对象又可以添加E的子类型对象因为取的时候E类型既可以接收E类对象又可以接收E的子类型对象
下限什么时候用: 当从集合中获取元素进行操作的时候可以用当前元素的类型接收也可以用当前元素的父类型接收
7> 泛型的细节
a. 泛型到底代表什么类型取决于调用者传入的类型如果没传默认是Object类型
b. 使用带泛型的类创建对象时等式两边指定的泛型必须一致因为编译器检查对象调用方法时只看变量然而程序运行期间调用方法时就要考虑对象具体类型了
c. 等式两边可以在任意一边使用泛型在另一边不使用(考虑向后兼容)
ArrayList al = newArrayList(); //错要保证左右两边的泛型具体类型一致就可以了这样不容易出错
ArrayList extendsObject> al = newArrayList();
al.add("aa"); //错因为集合具体对象中既可存储String 也可以存储Object的其他子类所以添加具体的类型对象不合适类型检查会出现安全问题?extends Object 代表Object的子类型不确定不能添加具体类型的对象
publicstaticvoidmethod(ArrayList extendsObject> al) {
al.add("abc"); //错只能对al集合中的元素调用Object类中的方法具体子类型的方法都不能用因为子类型不确定
}