------- android培训、java培训、期待与您交流! ----------
JDK1.5 新特性总结
JDK5中新增了很多新的java特性,利用这些新特性可以帮助开发人员编写出更加高效、清晰,安全的代码,具体有以下几种:
1.静态导入
2.自动装箱/拆箱
3.增强for循环
4.可变参数
5.枚举
6.泛型
7.注解
一、静态导入
JDK 1.5 增加的静态导入语法用于导入类的某个静态属性或方法。使用静态导入可以简化程序对类静态属性和方法的调用。
语法:
import static 包名.类名.静态属性|静态方法 |*
(1) 普通import语句导入一个类或某个包中的所有类。
(2) import static语句导入一个类中的某个静态方法或所有静态方法。
(3) 例如:语句Math.max(3,6);当导入一个import static java.lang.Math.max;时,语句可写成max(3,6); 。
示例:
package cn.itcast.day1;
//import static java.lang.Math.max;
import static java.lang.Math.*;
import cn.itcast.day2.AnnotationTest;
public class StaticImport {
public static void main(String[] args){
AnnotationTest.sayHello();
int x = 1;
try {
x++;
} finally {
System.out.println("template");
}
System.out.println(x);
System.out.println(max(3, 6));
System.out.println(abs(3 - 6));
//System.out.println(Math.abs(3 - 6));
}
}
二、 基本数据的自动拆装箱及享元设计模式
JDK5.0 的语法允许开发人员把一个基本数据类型直接赋给对应的包装类变量 , 或者赋给 Object 类型的变量,这个过程称之为自动装箱。
自动拆箱与自动装箱与之相反,即把包装类对象直接赋给一个对应的基本类型变量。
(1) Integer iobj = 3;// 装箱 将基本数据类型装成 Integer 对象在赋给 iobj 引用变量。
System.out.println(iobj +12);// 拆箱
(2) String s1 = new String("abc");
String s2 = new String("abc");
Integer i1 = 137;
Integer i2 = 137;//-128~127 之间的数字是 true
System.out.println(i1== i2);
System.out.println(s1== s2);// 会分配不同空间
(3) 享元模式— flyweight :就是很多个小的对象,他们有很多属性相同,把他们变成一个对象,称之为内部状态。那些不同的属性,把他们变成方法的参数,称之为外部状态。
示例:
package cn.itcast.day1;
public class AutoBox {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Integer iObj = 3; //自动装箱
System. out .println(iObj + 12); //integer 不支持加法,会自动转成int基本数据类型
//这就是拆箱
String s1 = new String( "abc" );
String s2 = new String( "abc" );
Integer i1 = 13;
Integer i2 = 13;
//数字在一个字节之内-128~127。。如果封装成integer对象之后就放在一个池里边,
//以后的数据直接拿来用,节省内存空间
//享元模式 flyweight
//都在使用一个对象,只是出现的位置不一样作为外部属性
//就是有很多个小的对象,他们有很多属性相同,
//把他们作为一个对象,作为内部状态;那些不同的属性变成方法的参数,成为外部状态---享元模式
//i.display(int x,int y)对象的位置不一样 xy表示位置
System. out .println(i1 == i2);
System. out .println(s1 == s2);
}
三、 增强for循环
(1) 语法格式:
for(变量类型 变量 :需迭代的数组或集合){}
(2) 注意事项:1)迭代变量必须在()中定义!集合变量可以是数组或实现了Iterable的集合类
2)向集合中取元素时同时加元素,需要使用迭代器来完成,即需要传统的for循环。
示例:将上面的for循环改成增强for的写法
for(int arg:args){
sum+=arg;
}
引入增强for循环的原因:
在JDK5以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!
因此JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组、或实现Iterator接口的集合类上
四、可变参数
从 JDK 5 开始 , Java 允许为方法定义长度可变的参数。语法:}
public void foo(int … args){
}
注意事项:
调用可变参数的方法时 , 编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以
在方法体中以数组的形式访问可变参数可变参数只能处于参数列表的最后 , 所以一个方法最多只能有
一个可变参数
可变参数总结:
1) 可以使用传统方式传入一个数组,或直接传入单个元素
2) 编译器会将可变传数看成一个一维数组
3) 可变参数只能放置在参数的最后
4) 可变参数只能在参数中有一个
示例:
package cn.itcast.day1;
public class VarableParameter {
public static void main(String[] args){
System. out .println(add(2,3));
System. out .println(add(2,3,5));
}
public static int add( int x, int ... args){ //可变参数
int sum = x;
/*for(int i=0;i<args.length;i++){
sum+= args[i];
}*/
for ( int arg : args){
sum+=arg;
}
return sum;
}
五、枚举类
1 :为什么需要枚举?}
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在 JDK5 以前
采用自定义带有枚举功能的类解决, Java5 以后可以直接使用枚举予以解决。
JDK 5 新增的 enum 关键字用于定义一个枚举类。
2 :枚举类具有如下特性:
1. 枚举类是一种特殊形式的 Java 类。
2. 枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
3:与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数
必须为私有的(这点不难理解)。
4. 枚举类也可以实现接口、或继承抽象类。
5.JDK5 中扩展了 switch 语句,它除了可以接收 int, byte, char, short 外,还可以接收一个枚举类型。
6. 若枚举类只有一个枚举值,则可以当作单例设计模式使用。
Java 中声明的枚举类,均是 java.lang.Enum 类的孩子,它继承了 Enum 类的所有方法。常用方法:
name()
ordinal()
valueOf(Class enumClass, String name)
values() 此方法虽然在 JDK 文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值
非常方便。
示例:
package cn.itcast.day1;
public class EnumTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
WeekDay1 weekDay = WeekDay1. MON ;
System. out .println(weekDay.nextDay());
WeekDay weekDay2 = WeekDay. FRI ;
System. out .println(weekDay2);
System. out .println(weekDay2.name());
System. out .println(weekDay2.ordinal());
System. out .println(WeekDay.valueOf( "SUN" )); //比较重要的
System. out .println(WeekDay.values(). length ); //得到所有枚举元素的一个数组
//new Date(300){} ;
}
public enum WeekDay{
//public WeekDay();所有信息必须放在元素列表之后
SUN (2), MON (), TUE , WED , THI , FRI , SAT ; //可以设置初始化使用哪个构造方法
private WeekDay(){System. out .println( "1" );} //必须是私有的
private WeekDay( int day ){System. out .println( "2" );}
}
//复杂的枚举 -------------不能运行的这段 只是个例子
public enum TrafficLamp{
RED (30){ //元素由子类实现
public TrafficLamp nextLamp(){
return GREEN ;
}
},
GREEN (45){
public TrafficLamp nextLamp(){
return YELLOW ;
}
},
YELLOW (5){
public TrafficLamp nextLamp(){
return RED ;
}
};
public abstract TrafficLamp nextLamp();
private int time ;
private TrafficLamp( int time){ //构造方法写成私有的
this . time = time;
}
}
六、泛型(Generic)
泛型是 java1.5 出现的新特性,泛型的出现把很多的 ClassCastException 即运行时异常转为编译时异常, 可以说极大的提高了程序的健壮性。
泛型是跟编译器配套使用的。但是泛型的技术并没有像 C++ 做的那么的好,在编译的时候也写进 class 文件中。在 Java 中,在编译为 class 文件的时候,把泛型类型去掉了(泛型的擦除,主要是为了兼容类加载器),即在 class 文件中没有泛型的踪影。但是在程序运行的时候, Java 会读取元素的类型并进行一系列的转换。
泛型的好处
1 :把运行时的异常转到了编译阶段
2 :避免了强制类型的转换
泛形的基本术语,以 ArrayList<E> 为例: <> 念着 typeof
ArrayList<E> 中的 E 称为类型参数变量
ArrayList<Integer> 中的 Integer 称为实际类型参数
整个称为 ArrayList<E> 泛型类型
整个 ArrayList<Integer> 称为参数化的类型
典型应用
1. 使用迭代器迭代泛形集合中的元素。
2. 使用增强 for 循环迭代泛形集合中的元素。
3. 存取 HashMap 中的元素。
在什么时候定义泛型?
当我们定义方法的时候,由于不知道调用者会传入什么样的参数,这时候我们就可以定义泛型,但是当调用者在使用方法的时候,肯定知道自己需要传入什么样类型的参数,所以当调用者调用的时候,必须传入具体的引用数据类型
使用泛形时的几个常见问题:
使用泛形时,泛形类型须为引用类型,不能是基本数据类型。 Java 中保存什么内容,由其变量决定。
ArrayList<String> list = new ArrayList<Object>();// 错,只能一边指定泛型或二边相同
ArrayList<Object> list = new ArrayList<String>();// 错,只能一边指定泛型或二边相同
ArrayList<String> list = new ArrayList (); 兼容 1.4// 对
ArrayList list = new ArrayList<String>(); 兼容 1.4// 对
自定义泛形 --- 泛型方法
Java 程序中的普通方法、构造方法和静态方法中都可以使用泛型。方法使用泛形前,必须对泛形进行声
明,语法: <T> , T 可以是任意字母,但通常必须要大写。 <T> 通常需放在方法的返回值声明之前。例
如:
public static <T> void doxx(T t);
泛型类
如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如
下:
public class BaseDao<T> {
private T field1;
public void save(T obj){}
public T getId(int id){}
}
注意,静态方法不能使用类定义的泛形,而应单独定义泛形。
泛型的通配符:
?就是通配符,什么意思呢?当我们定义类,方法(参数)不确定的时候,可以用?来表示
比如:
public void show ( <?> a ) {}
由于在方法中,传入的数据类型不确定,所以用到了泛型,但是在调用的时候,调用者肯定知道
如:
int a=3 ;
show(a);
String b="dfd";
show(b);
这个方法可以接受任意类型的参数
但是在说泛型定义的时候,自己有没有觉得不合适呢?
开始感觉有,但是现在没有了
为什么呢?
因为泛型就是在数据不确定的时候才使用的,所以是未知的。之前一直认为在定义的时候就应该知道
泛型中是什么类型。
但是呢,有时候我们需要的是把一个体系全部的纳入到泛型之中,这时候该怎么做呢?
不知道是否还记得?通配符,我们可以通过继承来实现
<? extends Collection> 这被我们村称之为上边界,因为只能作用到其最顶层(父类),通过这样的定义,可以把其子类当做参数来传递,这主要使用在添加的。
因为在取出的时候方便,不用再进行类型的判断。
既然有了上边界:那么自然的就会有下边界
具体如下:
<? super comparable> 这就是下边界,通常用来进行比较。比较的时候既可以使用自己的比较器,
也可以使用父类的比较器
七、注解(Annotation)
1.注解相当于一种标记,在程序中加了注解就等于为程序打上可某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无任何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
2.@SuppressWarning :压缩警告
@SuppressWarnings("deprecation")
public static void main(String[] args) {
System.runFinalizersOnExit(true);
}
2.@Deprecated :标记某个方法过时。
@Deprecated
public static void sayHello(){
System.out.println("hi, 传智播客 ");
}
3.@Override :子类覆盖父类方法。
@Override
public boolean equals(Object obj)