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

【黑马程序员】javaJDK1.5新特性

2013-11-19 15:48 453 查看
-------
Windows Phone 7手机开发、.Net培训、期待与您交流! -------

javaJDK1.5新特性介绍:

1.增强for循环(Enhanced For loop)--减少迭代器(iterator)的潜在错误(error-proneness)

语法:for(type 变量名:集合变量名){...}

注意事项:迭代变量必须在for()的括号内定义,集合变量可以是数组或者实现了Iterable接口的集合类。

package test;

public class VarableParameter {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(add(1));
		System.out.println(add(1,2));
		System.out.println(add(1,2,3));
		System.out.println(add(1,2,3,4));
	}
	public static int add(int x,int ... args){
//		for(int i=0;i<args.length;i++){
//			x=x+args[i];
//		}
		
		for(int arg:args){
			x=x+arg;
			
		}
		return x;
	}
}


2.泛型(Generics)--为集合(collections)提供编译时类型安全,无需每刻从Collections取得一个对象就进行强制转换(cast)

在javaJDK1.5以前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的类型转换,而这种转换是要求开发者对实际类型参数了解的情况下进行的。对于强制类型转换,编译期间编译器并不会提示,只有在运行中才会出现异常,这是一个安全隐患。

泛型的规则和限制:

1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型(float double byte short int long char boolean)。

2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。

3、泛型的类型参数可以有多个。

4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”。

5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName("java.lang.String");

泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现同样的功能,一个使用了泛型,一个没有使用,通过对比,可以很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。

例一:下面代码,Gen类使用了泛型定义了他的成员变量,所以当对象在设置的类成员变量的时候就会严格按照泛型定义的类型来传值,否则在编译期间就会报错!这样我们就省略了强制转换啦!

class Gen<T> {
private T ob; //定义泛型成员变量
public Gen(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public void showType() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo {
public static void main(String[] args){
//定义泛型类Gen的一个Integer版本
Gen<Integer> intOb=new Gen<Integer>(88);
intOb.showType();
int i= intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
//定义泛型类Gen的一个String版本
Gen<String> strOb=new Gen<String>("Hello Gen!");
strOb.showType();
String s=strOb.getOb();
System.out.println("value= " + s);
}
}


例2.没有使用泛型

没有使用泛型的情况下,我们对传入参数类型不确定所以需要强制转换。

class Gen2 {
private Object ob; //定义一个通用类型成员
public Gen2(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void setOb(Object ob) {
this.ob = ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public class GenDemo2 {
public static void main(String[] args) {
//定义类Gen2的一个Integer版本
Gen2 intOb = new Gen2(new Integer(88));
intOb.showTyep();
int i = (Integer) intOb.getOb();
System.out.println("value= " + i);
System.out.println("---------------------------------");
//定义类Gen2的一个String版本
Gen2 strOb = new Gen2("Hello Gen!");
strOb.showTyep();
String s = (String) strOb.getOb();
System.out.println("value= " + s);
}
}


3。静态导入(static import ) :这一新特性使我们在写代码的时候更加简洁易读,无需在使用其他类的静态成员或方法时加上类名为前缀,如下代码。

package test;

	public class Test {
		public static void main(String[] args) {
			System.out.println(Math.abs(3 - 6));
			System.out.println(	Math.max(1,4 ));
		}
		
}


新特性后,使用import static 导入类的静态方法,即可在后续代码中省略类的后缀。

package test;
import static java.lang.Math.*;

	public class Test {
		public static void main(String[] args) {
			System.out.println(abs(3 - 6));
			System.out.println(max(1,4 ));
		}
		
}


4.可变参数(Var args):可变的参数只能出现在方法参数列表的最后。“...”位于变量类型和变量名之间,前后有无空格都行,调用可变参数方法时,编译器为该可变参数隐含创建一个数组,正方法体中以数组的形式访问可变参数。

package test;

public class VarableParameter {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(add(1));
		System.out.println(add(1,2));
		System.out.println(add(1,2,3));
		System.out.println(add(1,2,3,4));
	}
	public static int add(int x,int ... args){
		for(int i=0;i<args.length;i++){
			x=x+args[i];
		}
		return x;
	}
}


在调用可变参数方法的时候,可变参数的可以是0个参数,也可以是1个以上的参数。

5.自动装箱/自动拆箱

自动装箱:Integer num1=12;

这里的int类型的12被封装成了一个Integer对象。

自动拆墙:System.out.println(num1+12);

num1为Integer对象,对象不支持加法,这里java把num1转换成了int基本数据。

特别注意:Integer num1=12;

Integer num2=12;

这俩个对象num1和num2指向的是一个对象。他们相等,num1==num2 true;

-128-127这个范围内相同的俩个数包装为俩个Integer对象,那么这俩个对象相等。

6.枚举

1.为什么要有枚举?

问题:要定义星期几或性别变量时,该如何定义?建设分别用1-7分别来表示星期一到星期日,但有人可能会写成int weekday=0;

枚举就是要让某个类型的变量值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中的非法值,普通变量的方式在开发阶段无法实现这一目标。

/*  
 * 用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能。   
    1、私有的构造方法  
    2、每个元素分别用一个公有的静态成员变量表示  
    3、可以有若干公有方法或抽象方法。采用抽象方法定义nextDay就将大量的if.else语句转移成了一个个独立的类。  
  
*/    
    
package cn.itheima;    
    
public abstract class WeekDay {    
    private WeekDay(){}    
    
    public final static WeekDay SUN=new WeekDay(){    
        public WeekDay nextDay(){    
            return MON;    
        }    
    };    
        
    public final static WeekDay MON=new WeekDay(){    
        public WeekDay nextDay(){    
            return SUN;    
        }    
    };    
        
    public abstract WeekDay nextDay();    
    
    public String toString(){    
        return this==SUN?"SUM":"MON";    
    }    
}


2、枚举的基本应用

通过enum关键字定义枚举类,枚举类是一个特殊的类,每个元素都是该类的一个实例对象。

用枚举类规定值,如上面的WeekDay类。以后用此类型定义的值只能是这个类中规定好的那些值,若不是这些值,编译器不会通过。

好处:在编译时期就会发现错误,表明值不符合,减少了运行时期的错误。

如果调用者想打印枚举类中元素的信息,需由编写此类的人定义toString方法。

注:枚举类是一个class,而且是一个不可被继承的final类,其中的元素都是类静态常量。

常用方法:

构造器:

构造器只是在构造枚举值的时候被调用。

构造器只有私有private,绝不允许有public构造器。这样可以保证外部代码无法重新构造枚举类的实例。因为枚举值是public
static final的常量,但是枚举类的方法和数据域是可以被外部访问的。

构造器可以有多个,调用哪个即初始化相应的值。

非静态方法:(所有的枚举类都继承了Enum方法)

String toString() ;//返回枚举量的名称

int ordinal() ;//返回枚举值在枚举类中的顺序,按定义的顺序排

3)Class getClass() ;//获取对应的类名

4) String name();//返回此枚举常量的名称,在其枚举声明中对其进行声明。

静态方法:


valueOf(String e) ;//转为对应的枚举对象,即将字符串转为对象

values() ;//获取所有的枚举对象元素

示例:
package cn.itheima;    
    
public class EnumDemo {    
    public static void main(String[] args) {    
        WeekDay weekDay=WeekDay.MON;    
        System.out.println(weekDay);//输出枚举常量名    
        System.out.println(weekDay.name());//输出对象名    
        System.out.println(weekDay.getClass());//输出对应类    
        System.out.println(weekDay.toString());//输出枚举对象名    
        System.out.println(weekDay.ordinal());//输出此对象在枚举常量的次序    
        System.out.println(WeekDay.valueOf("WED"));//将字符串转化为枚举常量    
        System.out.println(WeekDay.values().length);//获取所以的枚举元素,并打印其长度    
    }    
    //定义枚举内部类    
    public enum WeekDay{    
        SUN(1),MON,TUE,WED,THI,FRI,SAT;//分号可有可无,但如果下面还有方法或其他成员时,分号不能省。    
        //而且当有其他方法时,必须在这些枚举变量的下方。    
    
        //无参构造器    
        private WeekDay(){    
            System.out.println("First");    
        }    
        //带参数的构造器    
        private WeekDay(int day){    
            System.out.println("Second");    
        }    
    }    
}


3、枚举的高级应用

枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。

枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔。把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。

带构造方法的枚举

构造方法必须定义成私有的

如果有多个构造方法,该如何选择哪个构造方法?

枚举元素MON和MON()的效果一样,都是调用默认的构造方法。

4、带方法的枚举

如:
/*  
 * 抽象的枚举方法  
 * 此时枚举中的常量需要子类来实现,这是可以利用内部类的方式来定义枚举常量  
 * 带方法的枚举  
    1)定义枚举TrafficLamp  
    2)实现普通的next方法  
    3)实现抽象的next方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类  
    4)用类似内部类的方式进行定义。  
    5)增加上表示时间的构造方法  
 * */    
    
package cn.itheima;    
    
public class EnumTest {    
    public enum TrafficLamp{    
        RED(30){    
            public TrafficLamp nextLamp(){    
                return GREEN;    
            }    
        },    
        GREEN(30){    
            public TrafficLamp nextLamp(){    
                return YELLOW;    
            }    
        },    
        YELLOW(5){    
            public TrafficLamp nextLamp(){    
                return RED;    
            }    
        };    
        private int time;    
        //构造器    
        private TrafficLamp(int time){    
            this.time=time;}    
        //抽象方法    
        public abstract TrafficLamp nextLamp();    
    }           
}


小结:

匿名内部类比较常用

类的方法返回的类型可以是本类的类型

类中可定义静态常量,常量的结果就是自己这个类型的实例对象

枚举只有一个成员时,就可以作为一种单例的实现方式。

注:

所有的枚举都继承自java.lang.Enum类。由于Java不支持多继承,所以枚举对象不能再继承其他类。

switch语句支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。

-------
Windows Phone 7手机开发、.Net培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: