JDK1.5的一个重要主题就是通过新增一些特性来简化开发,这些特性包括静态导入,可变参数,增强For循环,自动装箱/拆箱,枚举,泛型,注解。使用这些新特性有助于我们编写更加清晰,精悍,安全的代码。
新特性简介:
import static java.lang.Math.max;//静态导入
public class StaticImport {
public static void main(String[] args){
System.out.println(max(3, 6));//不必写成Math.max(3,6)
System.out.println(Math.abs(3 - 6));
}
}
利:简化代码 弊:过度使用会降低代码阅读性
util.write(obj1);
util.write(obj1,obj2);
util.write(obj1,obj2,obj3);
在JDK1.5之前,我们可以用重载Overload来实现,但是这样就需要写很多的重载函数,显然效率会降低。如果使用可变参数的话我们只需要一个函数就行了。
public void write(Object... objs) {
for (int i=0;i<objs.length;i++)
System.out.println(objs[i]);
}
增强For循环的加入简化了实现Iterable接口集合的遍历。假设我们要遍历一个集合对其中的元素进行一些处理,典型的代码为:
void processAll(Collection c){
for(Iterator i=c.iterator(); i.hasNext();){
MyClass myObject = (MyClass)i.next();
myObject.process();
}
}
使用增强For循环后,代码改写为:
void processAll(Collection<MyClass> c){
for (MyClass myObject :c)
myObject.process();
}
这段代码要比上面清晰许多,并且避免了强制类型转换。这里有个小插曲,视频里张老师带我们看了java语言规范文档,意想不到的发现type前面可以加修饰符。
自动装箱:基本类型自动转为包装类.(int >> Integer)
自动拆箱:包装类自动转为基本类型.(Integer >> int)
举例说明:
Integer iObj = 3;//自动装箱
System.out.println(iObj + 5);//自动拆箱
这里老师还提到了享元模式(flyweight):一个事物中的部分状态是可以共享的话,就把这部分状态传递到一个共享区即享元,其他状态就放到外部数据结构中作为方法的参数传入。事例如下:
新特性简介:
1.静态导入(Static Imports)
要使用静态成员(方法和变量)我们必须给出提供这个方法的类。使用静态导入可以使被导入类的所有静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名。import static java.lang.Math.max;//静态导入
public class StaticImport {
public static void main(String[] args){
System.out.println(max(3, 6));//不必写成Math.max(3,6)
System.out.println(Math.abs(3 - 6));
}
}
利:简化代码 弊:过度使用会降低代码阅读性
2.可变参数(Varargs)
可变参数使程序员可以声明一个接受可变数目参数的方法。可变参数只能出现在参数列表的最后,“...”位于参数类型和参数名之间,前后有无空格都可以。调用可变参数的方法时,编译器为该可变参数隐含创建一个数组创建一个数组创建一个数组创建一个数组,在方法体中以数组的形式访问可变参数。假设写一个简单的打印方法:util.write(obj1);
util.write(obj1,obj2);
util.write(obj1,obj2,obj3);
在JDK1.5之前,我们可以用重载Overload来实现,但是这样就需要写很多的重载函数,显然效率会降低。如果使用可变参数的话我们只需要一个函数就行了。
public void write(Object... objs) {
for (int i=0;i<objs.length;i++)
System.out.println(objs[i]);
}
3.增强For循环(For-Each)
语法:for(type 变量名:集合变量名){...}增强For循环的加入简化了实现Iterable接口集合的遍历。假设我们要遍历一个集合对其中的元素进行一些处理,典型的代码为:
void processAll(Collection c){
for(Iterator i=c.iterator(); i.hasNext();){
MyClass myObject = (MyClass)i.next();
myObject.process();
}
}
使用增强For循环后,代码改写为:
void processAll(Collection<MyClass> c){
for (MyClass myObject :c)
myObject.process();
}
这段代码要比上面清晰许多,并且避免了强制类型转换。这里有个小插曲,视频里张老师带我们看了java语言规范文档,意想不到的发现type前面可以加修饰符。
4.自动装箱/拆箱(Autoboxing/unboxing)
自动装箱/拆箱大大方便了基本数据类型和它们包装类地使用。自动装箱:基本类型自动转为包装类.(int >> Integer)
自动拆箱:包装类自动转为基本类型.(Integer >> int)
举例说明:
Integer iObj = 3;//自动装箱
System.out.println(iObj + 5);//自动拆箱
这里老师还提到了享元模式(flyweight):一个事物中的部分状态是可以共享的话,就把这部分状态传递到一个共享区即享元,其他状态就放到外部数据结构中作为方法的参数传入。事例如下:
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 130;
Integer i4 = 130;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//false
因为基本数据类型要装箱成包装类的时候,会判断基本数据是否在给定的字节范围内,是的话就装箱成包装类并缓存到一个地方,下次再有一样的动作就从缓存区直接取,所以结果为true。
5.枚举(Enums)
枚举是一个全新类型的“类”,关键字为enmu。我们可以这样来定义一个枚举类型:public enum Color
{
Red(1){public void nextColor(){}},
White(2){public void nextColor(){}},
Blue(3){public void nextColor(){}};
private Color(Object obj){}
public abstract void nextColor();
}
Color myColor = Color.Red;
注意:枚举的构造函数是private,每个元素都是该类的一个实例对象,元素是public static,在一个枚举类中可以有多个抽象或公有方法。它的作用就是让某种类型的变量取值范围固定在一个或多个内。现实中的星期天数、性别等都可通过枚举实现。
Collection<String> c = new ArrayList();
c.add(new Date());
编译器会给出一个错误:
add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)
java提供了3个基本的注解类型Deprecated(方法是否过时)、Override(重写)、SuppressWarnings(取消警告),注解相当于一种标记,加了注解后javac编译器,开发工具和其他程序可以用反射来了解你的类的各种元素上有无何种标记,看你有什么样的标记就去干什么事。标记可以加在包、类、字段、方法、方法的参数、局部变量上。
Blue(3){public void nextColor(){}};
private Color(Object obj){}
public abstract void nextColor();
}
Color myColor = Color.Red;
注意:枚举的构造函数是private,每个元素都是该类的一个实例对象,元素是public static,在一个枚举类中可以有多个抽象或公有方法。它的作用就是让某种类型的变量取值范围固定在一个或多个内。现实中的星期天数、性别等都可通过枚举实现。
6.泛型(Generic)
C++通过模板技术可以指定集合的元素类型,而Java在1.5之前一直没有相对应的功能。一个集合可以放任何类型的对象,相应地从集合里面拿对象的时候我们也不得不对他们进行强制得类型转换。1.5引入了泛型,它允许指定集合里元素的类型,这样你可以得到强类型在编译时刻进行类型检查的好处。Collection<String> c = new ArrayList();
c.add(new Date());
编译器会给出一个错误:
add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)
7.注解(Annotation)
语法:@interface ClassName{} 应用格式:@ClassNamejava提供了3个基本的注解类型Deprecated(方法是否过时)、Override(重写)、SuppressWarnings(取消警告),注解相当于一种标记,加了注解后javac编译器,开发工具和其他程序可以用反射来了解你的类的各种元素上有无何种标记,看你有什么样的标记就去干什么事。标记可以加在包、类、字段、方法、方法的参数、局部变量上。
注解也可以应用于注解上称为元注解,如@Retention标记该注解的生命周期(
CLASS、RUNTIME、SOURCE
),@Targetb标记该注解应用于类的哪个成分,不声明默认作用于所有成分。自定义注解也可添加属性。
实例如下:
@Retention(RetentionPolicy.RUNTIME)//使注解 ItcastAnnotation保留到运行时期
@Target(ElementType.METHOD)//使注解ItcastAnnotation只能作用于类的方法上
public @interface ItcastAnnotation {
String color() default "Red";//指定String类型属性,默认值为Red
String value();
int[] arrayAttr() default {3,4,3}; //指定一个数组属性
EnumSex sex() default EnumSex.MAN;//指定一个枚举属性
MetaAnnotation annotationAttr() default @MetaAnnotation("123");//指定一个注解属性
Class clazz();//指定一个Class类属性
}
在应用类中调用以上注解:
public class Xxx {
@ItcastAnnotation(color="blue",value="123",arrayAttr={1,2,3},sex=EnumSex.WOMEN,annotationAttr=@MetaAnnotation("123"),clazz=String.class)
public void method(){}
}
通过反射得到注解,可以用注解对象调用方法(属性名+())得到该属性,并且可继续操作该属性内部方法。