黑马程序员--Java基础加强(2)-- JDK1.5新特性之可变参数,增强for,自动拆装箱,枚举

时间:2023-02-16 12:53:40
------------------ android培训java培训、期待与您交流! ---------------------

JDK1.5新特性之可变参数,增强for,自动拆装箱,枚举

一、 可变参数

1、当一个方法,需要的参数不确定时,可以使用可变参数,比如add方法,希望传入几个参数就让这几个参数相加,声明形式:

public int add(int x, int … args){}

这里int … args就是可变参数的声明格式:前面的int表示可变参数的类型,args代表这些传入的参数存入的数组名。…省略号前后有无空格均可。

2、注意,可变参数只能定义在函数参数列表的末尾。

3、在调用可变参数时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。例如:

public int add(int x,int ... args)
{
int sum = x;
for(int i = 0,i<args.length;i++){sum += args[i]; }
return sum;
}

4、没有可变参数之前,都是将数组作为参数来实现可变参数的效果,但是需要传入一个相应的数组,而可变参数只是将他们封装了,使用户使用更加方便。

 二、增强for循环(高级for循环)

1、格式:

for(数据类型 变量名:被遍历的集合或数组){...}

增强for循环一般用于遍历集合或数组。例如;

public class Test {
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<String>();
arr.add("abd");
arr.add("loi");
arr.add("ftjh");
for(String s: arr) {
System.out.println(s);
}
}
}

2、优点:简便快捷,不需要长度。

3、缺点:

*增强for循环存在一个局限性:必须有遍历的目标,像for(int i=0;i<10;i++){}这种循环,增强for循环做不了。另外,普通for循环还有脚标,比较方便。

*增强for循环只能遍历查询,不能遍历修改!比如遍历ArrayList集合,如果用迭代器遍历,就可以对集合中的元素进行修改,而用增强for循环就无法修改。

三、 基本数据的自动拆装箱,享元设计模式

1、每一个基本数据类型都有对应的类,总共有八个基本数据类型,他们对应的类如下:

基本数据类型  引用数据类型(类类型)

  byte  ----  Byte

  short  ----  Short

  int  ----  Integer

  long  ----  Long

  boolean  ----  Boolean

  float  ----  Float

  double  ----  Double

  char  ----  Character

2装箱:将基本数据类型封装成相应的类。

      拆箱:将类转换成相应的基本数据类型。

      自动拆装箱:就是java虚拟机在需要(比如Integer类型的变量是不能直接参加计算的,需要拆箱变成int型)的时候自动给你完成这些转换动作,快捷方便。这是JDK1.5的新特性,之前的版本是不行的。

举个例子:

Integer i = 4;//将int型的4自动封装成了Integer型,赋值给了i
Integer x = 8+i;//将Integer型的i自动拆箱,变成基本数据类型int型,然后参与运算,最后又将结果装箱变成Integer型
System.out.println(x.hashCode());

3、注意,当Integer值在-128~127之间,即只有一个字节时,相同值的对象,是同一个对象。这是为了节省内存空间,只要值相同就不再新生成一个对象了。当超出这个范围,就会生成新的对象,例如:

Integer i1 = 13;
Integer i2 = 13;
System.out.println(i1==i2);//结果为true,如果i1和i2均为超出范围的数,比如200,结果为false;

4享元设计模式:flyweight

       如果有很多很小的对象,他们有很多相同的地方,那就把他们作为同一个对象,将不同的部分作为外部属性,作为方法的参数传入。相同的属性,称之为内部状态。

       比如上面提到的Integer,在-128~127之间,相同值看做同一个对象,就是享元设计模式。

四、 枚举及其代码举例

1、什么是枚举?

(1)枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。

(2)枚举可以让编译器在编译时就可以识别源程序中填写的非法值,而普通变量的方式在开发阶段无法实现这一目标。

(3)枚举是JDK1.5的新特性。枚举和类是一个级别的。

2、使用枚举

(1)创建:创建一个枚举的关键词是enumpublic enum WeekDay{}就创建了一个枚举WeekDay。枚举的成员变量(即枚举常量)定义在该枚举的开始部分,不能定义在后面,枚举常量之间用逗号’,’隔开,如果枚举常量后面还有其他成员,例如构造方法,抽象方法或者其他变量,那么枚举常量要以分号’;’结束。每一个枚举常量都是该枚举的一个实例对象。枚举常量的修饰前缀可以省略,默认为public final static 枚举名,如枚举WeekDay的枚举常量的默认前缀是public final static WeekDay

 (2)枚举的构造函数:枚举的构造函数必须是私有的private。一般系统会默认生成一个空参数的构造函数。你也可以自定义空参数的和有参数的构造函数,如果想调用带有参数的构造函数,只需要在枚举常量后面加一个括号,括号中添加构造函数的参数列表类型的参数,例如,想调用参数类型int的构造函数,枚举常量可以是SUN(1)

另外,正是由于枚举的构造函数是私有的,所以当枚举只有一个枚举常量时,就相当于一个单例设计模式。

 (3)枚举的抽象方法:枚举可以有自己的方法,当然也包括抽象方法,那么这时枚举常量就相当于该枚举子类的实例对象(因为抽象枚举就像抽象类不能有自己的实例对象),需要在每个枚举常量的后面添加{}实现该抽象方法,相当于匿名内部类。

3、注意

(1)所有的枚举都继承自Enum类,所以枚举不可以再继承其他类,但是可以实现接口。

(2)枚举,重写了继承自ObjecttoString方法,使打印结果为枚举常量的内容,而不是哈希地址值。   

4、枚举中自带常用方法:

*String  name() 返回此枚举常量的名称,在其枚举声明中对其进行声明.
*int ordinal() 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
*Static Object valueOf("字符串");该类的静态方法valueOf方法将会把传入的字符串转化成一个该枚举的对象。
*values();返回一个该枚举类型的所有枚举常量的数组。

5、枚举的使用代码举例

public class MyEnumTest {
// 演示枚举自带常用方法
public static void main(String[] args){
WeekDay sun = WeekDay.SUN;
System.out.println(sun);//重写了toString方法,使得打印结果为对象内容
System.out.println(sun.ordinal());//ordinal()方法获得枚举常量在枚举声明中的位置,初始位置为0.
System.out.println(sun.name());//name()方法,打印该对象的名字
WeekDay fri = WeekDay.valueOf("FRI");//如果写入的字符串没有对应的枚举常量,将会报异常,说找不到。
System.out.println(fri);
WeekDay[] days = WeekDay.values();//values()方法获得该枚举的所有枚举常量的数组。
for(WeekDay day:days){//增强for循环将每个枚举常量遍历打印
System.out.println(day);
}


TrafficEnum t = TrafficEnum.RED;
System.out.println(t+":"+t.time+",下一个灯是"+t.nextLamp());
}
/*
* 下面是一个简单的枚举,为了简便,也可以将if else方法去掉,把方法内容加在枚举常量后面如SUN{public WeekDay nextDay(){return MON;}},
* */
public enum WeekDay{
SUN,MON,TUE,WED,THI,FRI,STA;
//SUN{public WeekDay nextDay(){return MON;}}
//自定义的方法nextDay()
public WeekDay nextDay(){
if(this == SUN){return MON;}
else if(this == MON){return TUE;}
else if(this == TUE){return WED;}
else if(this == WED){return THI;}
else if(this == THI){return FRI;}
else if(this ==FRI){return STA;}
else
return SUN;
}

}

//下面是一个含有参数的构造函数的枚举,且带有抽象方法。
public enum TrafficEnum{

RED(45){public TrafficEnum nextLamp(){return YELLOW;}},
GREEN(45){public TrafficEnum nextLamp(){return RED;}},
YELLOW(5){public TrafficEnum nextLamp(){return GREEN;}},;

private int time;
private TrafficEnum(){}
private TrafficEnum(int time){
this.time = time;
}
public abstract TrafficEnum nextLamp();
}
}