您的位置:首页 > 编程语言 > Java开发

java技术加强之其他1.5特性

2015-06-23 11:44 246 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

JDK5中新增了很多新的java特性,利用这些新语法可以帮助开发人员编写出更加高效、清晰,安全的代码。

①静态导入

②自动装箱/拆箱

③增强for循环

④可变参数

⑤枚举

⑥反射

⑦注解

⑧泛型

静态导入

JDK 1.5 增加的静态导入语法用于导入类的某个静态属性或方法。使用静态导入可以简化程序对类静态属性和方法的调用。它完全是为了便利而增加的新特性

语法:

Import static 包名.类名.静态属性|静态方法|*


例如:

import static java.lang.System.out //静态导入类成员
import static java.lang.Math.* //使用通配符


静态导入—小细节

import static java.util.Arrays.sort;
import static java.util.Collections.sort;


这是允许的,运行时会根据参数来自动找到对应的方法。

注:如果导入的两个静态方法的参数也是一样的话,由于不能确定是哪个方法,所有使用时需要小心

自动装箱/拆箱

Java中的基本类型不是对象,因此包装类用来当做对象版本的基本类型。当你要在两者之间来来回回转换时,事情就变得很讨厌了。如下所示:



自动装箱:指开发人员可以把一个基本数据类型直接赋值给对应的包装类。Autoboxing

自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型。Autounboxing

典型应用:



思考:

Integer i = null;

int j = i;

语法有无错误,能否运行?

i被赋值为null是合法的,然后i被拆箱给j,然而null对基本类型来说是不合法的,运行会抛出NullPointerException

自动装箱/拆箱—细节1

Java的规范指出:特定的基本类型一定得被box成相同的包装类型。这些对象会被高速缓存以重复使用,并且会被当做一般对象使用。这些特殊的值是boolean值的true和false、所有的byte值、介于-128至127的short与int值,以及介于\u0000与\u007F之间的任何一个char。



分别输出
true
true
false
false


自动装箱/拆箱—细节2

在一般的情况下,Java借由使用方法的名称来调用method。在方法有重载的情况下,需要检查方法的参数来决定调用哪个方法,如果没有找到符合的参数,会出现编译错误。

public void doSomething(double num);
public void doSomething(Integer num);
调用doSomething():
int foo = 1;
doSomething(foo);//结果调用哪个方法呢?


想知道答案吗?自己动手试一下。。。

*在5.0中的方法调用都会选出与在1.4中所选出的相同的方法。

也就是说编译器会试着不用任何的装箱/拆箱来定位方法。

编程时应尽可能地保持精确就可以避开这个问题。*

增强for循环

增强for循环又称为“foreach”或“enhanced for”循环

抛弃迭代:在JDK5以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!

因此JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组、或实现Iterable接口的子类上

语法格式:

for(变量类型 变量 :需迭代的数组或集合)
}


int arr[] = new int[5];
for(int num : arr){
num = 1;
}
System.out.println(arr[0]);
答案:0
List<String> list = new ArrayList<String>();
list.add("xxx");
for(String str : list){
str = "yyy";
}
System.out.println(list.get(0));

答案:xxx

解析:增强for循环只适合取数据,但是你要去修改是有办法的?想一想,什么的才可以使用增强for循环


可变参数

可变参数(variable argument)允许你指定可以采用多个同类型参数的方法,而不需要事先确定参数的数目。

可变参数。语法:
public void foo(int … args){
}


注意事项:

调用可变参数的方法时, 编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数

在一个方法参数中只能使用一个省略号;且省略号必须出现在方法中参数列表的最后一个位置。

思考一下:





不可变类

不可变类,是指当创建了这个类的实例后,就不允许修改它的属性值。在JDK的基本类库中,所有基本类型的包装类,如Integer和Long及String,都是不可变类。如果创建了他们的对象,在程序代码中无法再改变这些对象的值,因为他们没有提供修改属性的方法

注释:

*不可变类能是程序更加安全,不容易出错

不可变类是线程安全的,当多个线程访问不可变类的同一个实例时,无需进行线程同步。*

没有提供修改的方法,仅仅是读取,我怕你什么线程安不安全啊。

用户自定义不可变类

1、把属性private final类型

2、不对外公开修改属性的set方法,只提供get方法

3、在构造方法中初始化所有属性

4、覆盖Object类的equals和hashCode方法

在创建不可变类时,假如它的属性的类型是可变类型,在必要的情况下,必须提供保护性拷贝,否则,这个不可变类实例的属性仍然有可能被错误地修改。看以下代码:





尽管Schedule类的start和end属性是final类型的,但由于它们引用Date对象,在程序中可以修改所引用Date对象的属性。

不可变类—改进



通过采用保护性拷贝,其他程序无法获得与Schedule对象关联的Date对象的引用

如果Schedule类中被final修饰的属性所属的类是不可变类,就无需提供保护性拷贝,因为该属性所引用的实例值永远不会被改变

枚举类

为什么需要枚举?

一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,比如成绩Grade只能为ABCDE。此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。

JDK 5新增的 enum 关键字用于定义一个枚举类。

一个枚举也可以有构造函数、字段和方法



带抽象方法的枚举



枚举类具有如下特性:

①枚举类也是一种特殊形式的Java类。

②枚举类中声明的每一个枚举值代表枚举类的一个实例对象。

③与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的(这点不难理解)。

④枚举类也可以实现接口、或继承抽象类。

⑤JDK5中扩展了swith语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。

⑥若枚举类只有一个枚举值,则可以当作单态设计模式使用。



Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。常用方法:

name()

ordinal()

valueof(String name)此方法虽然在JDK文档中查找不到

values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便。

package cn.itcast.base.enumeration;

public enum WeekDay {
MON{
public String toLocaleString() {
return "星期一";
}

},TUE{
public String toLocaleString() {
return "星期二";
}

},WED{
public String toLocaleString() {
return "星期三";
}

},THU{
public String toLocaleString() {
return "星期四";
}

},FRI{
public String toLocaleString() {
return "星期五";
}

},SAT{
public String toLocaleString() {
return "星期六";
}

},SUN{
public String toLocaleString() {
return "星期日";
}

};
public abstract String toLocaleString();
}
//枚举中的常用方法:自定义的枚举类的爸爸是java.lang.Enum
@Test
public void test3(){
WeekDay wd = WeekDay.FRI;
String name = wd.name();//枚举类型对应的字符串名称
System.out.println(name);
答案:输出FRI
String str = "MON";
WeekDay wd1 = WeekDay.valueOf(str);
System.out.println(wd1.toLocaleString());

WeekDay wd2 = WeekDay.SUN;
System.out.println(wd2.ordinal());
答案:6//返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
}
@Test
//特殊的属性values:返回所有的枚举值。API中看不到的
public void test4(){
WeekDay [] wds = WeekDay.values();
for(WeekDay wd:wds){
System.out.println(wd.name());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: