续《JAVA编程思想》学习备忘(第155页:Initialization & Cleanup)-6
Variable argument lists
自从所有的类最终继承于根类Object,你可以创建一个带有Object数组的方法,并且这样调用:
例1:
//:initialization/VarArgs.java
//Using array syntax to create variable argument lists.
class A{}
public class VarArgs{
static void printArray(Object[] args){
for(Object obj:args)
System.out.print(obj+" ");
System.out.println();
}
public static void main(String[] args){
printArray(new Object[]{
new Integer(47),new Float(3.14),new Double(11.11)
});
printArray(new Object[]{"one","two","three"});
printArray(new Object[]{new A(),new A(),new A()});
}
}
输出结果:(样本)
47 3.14 11.11
one two three
A@1a46e30 A@3e25a5 A@19821f
例1:
//:initialization/VarArgs.java
//Using array syntax to create variable argument lists.
class A{}
public class VarArgs{
static void printArray(Object[] args){
for(Object obj:args)
System.out.print(obj+" ");
System.out.println();
}
public static void main(String[] args){
printArray(new Object[]{
new Integer(47),new Float(3.14),new Double(11.11)
});
printArray(new Object[]{"one","two","three"});
printArray(new Object[]{new A(),new A(),new A()});
}
}
输出结果:(样本)
47 3.14 11.11
one two three
A@1a46e30 A@3e25a5 A@19821f
用省略号定义一个变量参数列表:
例2:
//:initialization/NewVarArgs.java
//Using array syntax to create variable argument lists.
public class NewVarArgs{
static void printArray(Object... args){
for(Object obj : args)
System.out.print(obj+" ");
System.out.println();
}
public static void main(String[] args){
//Can take individual elements:
printArray(new Integer(47),new Float(3.14),new Double(11.11));
printArray(47,3.14F,11.11);
printArray("one","two","three");
printArray(new A(),new A(),new A());
//Or an array:
printArray((Object[])new Integer[]{1,2,3,4});
printArray();//Empty list is OK
}
}
输出结果:
47 3.14 11.11
47 3.14 11.11
one two three
A@1bab50a A@c3c749 A@150bd4d
1 2 3 4
例2:
//:initialization/NewVarArgs.java
//Using array syntax to create variable argument lists.
public class NewVarArgs{
static void printArray(Object... args){
for(Object obj : args)
System.out.print(obj+" ");
System.out.println();
}
public static void main(String[] args){
//Can take individual elements:
printArray(new Integer(47),new Float(3.14),new Double(11.11));
printArray(47,3.14F,11.11);
printArray("one","two","three");
printArray(new A(),new A(),new A());
//Or an array:
printArray((Object[])new Integer[]{1,2,3,4});
printArray();//Empty list is OK
}
}
输出结果:
47 3.14 11.11
47 3.14 11.11
one two three
A@1bab50a A@c3c749 A@150bd4d
1 2 3 4
上例程序最后一行显示传递一个零参数给一个vararg列表是可能的,这是非常有用的当你有可选的拖拽参数时:
例3
//:initialization/OptionalTrailingArguments.java
public class OptionalTrailingArguments{
static void f(int required,String...trailing){
System.out.print("required: " + required + " ");
for(String s : trailing)
System.out.print(s + " ");
System.out.println();
}
public static void main(String[] args){
f(1,"one");
f(2,"two","three");
f(0);
}
}
输出结果:
required:1 one
required:2 two three
required:0
例3
//:initialization/OptionalTrailingArguments.java
public class OptionalTrailingArguments{
static void f(int required,String...trailing){
System.out.print("required: " + required + " ");
for(String s : trailing)
System.out.print(s + " ");
System.out.println();
}
public static void main(String[] args){
f(1,"one");
f(2,"two","three");
f(0);
}
}
输出结果:
required:1 one
required:2 two three
required:0
在varargs中可用任意参数类型,包括原始数据类型。看下例:
例4:
例4:
//initialization/VarargType.java
public class VarargType{
public void f(Character...args){
System.out.print(args.getClass());
System.out.println(" length " + args.lenght);
}
static void g(int ... args){
System.out.print(args.getClass());
System.out.println(" length " + args.length);
}
public static void main(String[] args){
public class VarargType{
public void f(Character...args){
System.out.print(args.getClass());
System.out.println(" length " + args.lenght);
}
static void g(int ... args){
System.out.print(args.getClass());
System.out.println(" length " + args.length);
}
public static void main(String[] args){
VarargType vt = new VarargType();
vt.f('a');
vt.f();
g(1);
g();
System.out.println("int[]: " + new int[0].getClass());
}
}
输出结果:
class [Ljava.lang.Character;length 1
class [Ljava.lang.Character;length 0
class [I length 1
class [I length 0
int[]: class [I
vt.f('a');
vt.f();
g(1);
g();
System.out.println("int[]: " + new int[0].getClass());
}
}
输出结果:
class [Ljava.lang.Character;length 1
class [Ljava.lang.Character;length 0
class [I length 1
class [I length 0
int[]: class [I
Varargs do work in harmony with autoboxing,however.For example:
例5:
//:initialization/AutoboxingVarargs.java
public class AutoboxingVarargs{
public static void f(Integer...args){
for(Integer i : args)
System.out.print(i + " ");
System.out.println();
}
public static void main(String[] args){
f(new Integer(1),new Integer(2));
f(4,5,6,7,8,9);
f(10,new Integer(11),12);
}
}
输出结果:
1 2
4 5 6 7 8 9
10 11 12
注意上例,你可以在一个单一参数列表中混用类型,自动转换类型将int参数有选择地提升到Integer.
例5:
//:initialization/AutoboxingVarargs.java
public class AutoboxingVarargs{
public static void f(Integer...args){
for(Integer i : args)
System.out.print(i + " ");
System.out.println();
}
public static void main(String[] args){
f(new Integer(1),new Integer(2));
f(4,5,6,7,8,9);
f(10,new Integer(11),12);
}
}
输出结果:
1 2
4 5 6 7 8 9
10 11 12
注意上例,你可以在一个单一参数列表中混用类型,自动转换类型将int参数有选择地提升到Integer.
Varargs complicate the process of overloading,although it seems safe enough at first:
例6:
//:initialization/OverloadingVarargs.java
public class OverloadingVarargs{
static void f(Character...args){
System.out.print("first");
for(Character c : args)
System.out.print(" " + c);
System.out.println();
}
static void f(Integer...args){
System.out.print("second");
for(Integer i : args)
System.out.print(" " + i);
例6:
//:initialization/OverloadingVarargs.java
public class OverloadingVarargs{
static void f(Character...args){
System.out.print("first");
for(Character c : args)
System.out.print(" " + c);
System.out.println();
}
static void f(Integer...args){
System.out.print("second");
for(Integer i : args)
System.out.print(" " + i);
System.out.println();
}
static void f(Long...args){
System.out.println("third");
}
public static void main(String[] args){
f('a','b','c');
f(1);
f(2,1);
f(0);
f(0L);
//! f();//Won't compile -- ambiguous
}
}
输出结果:
first a b c
second 1
second 2 1
second 0
third
}
static void f(Long...args){
System.out.println("third");
}
public static void main(String[] args){
f('a','b','c');
f(1);
f(2,1);
f(0);
f(0L);
//! f();//Won't compile -- ambiguous
}
}
输出结果:
first a b c
second 1
second 2 1
second 0
third
例7:
//:initialization/OverloadingVarargs2.java
//{CompileTimeError}(Won't compile)
public class OverloadingVarargs2{
static void f(float i,Character... args){
System.out.println("first");
}
static void f(Character... args){
System.out.println("second");
}
public static void main(String args){
f(1,'a');
f('a','b');
}
}
编译错误:参数模梭两可。
上例修改后的例子:
例8:
//:initialization/OverloadingVarargs3.java
public class OverloadingVarags3{
static void f(float i,Character... args){
System.out.println("first");
}
static void f(char c,Character... args){
System.out.println("second");
}
public static void main(String[] args){
f(1,'a');
f('a','b');
}
}
输出结果:
first
second
Enumerated types
简单的例子:
//:intialization/Spiciness.java
public enum Spiciness{
NOT,MILD,MEDIUM,HOT,FLAMING
}
使用一个enum,你创建一个此类型参数并且将它付值于一个实例:
//:initialization/SimpleEnumUse.java
public class SimpleEnumUse{
public static void main(String[] args){
Spiciness howHot = Spiciness.MEDIUM;
System.out.println(howHot);
}
}
输出结果:
MEDIUM
例8:
//:initialization/OverloadingVarargs3.java
public class OverloadingVarags3{
static void f(float i,Character... args){
System.out.println("first");
}
static void f(char c,Character... args){
System.out.println("second");
}
public static void main(String[] args){
f(1,'a');
f('a','b');
}
}
输出结果:
first
second
Enumerated types
简单的例子:
//:intialization/Spiciness.java
public enum Spiciness{
NOT,MILD,MEDIUM,HOT,FLAMING
}
使用一个enum,你创建一个此类型参数并且将它付值于一个实例:
//:initialization/SimpleEnumUse.java
public class SimpleEnumUse{
public static void main(String[] args){
Spiciness howHot = Spiciness.MEDIUM;
System.out.println(howHot);
}
}
输出结果:
MEDIUM
当你创建一个enum时,编译器自动地增加有用的特征。举例,它创建一个toString()方法,这样你就可容易地展现一个enum实例的名字,这就是上例如何产生它的输出。编译器同时也创建一个ordinal()方法来指示enum实例的声明顺序,还有一个静态的values()方法,它产生按声明顺序enum实例的值的数组:
//:initialization/EnumOrder.java
public class EnumOrder{
public static void main(String[] args){
for(Spiciness s : Spiciness.values())
System.out.println(s + ", ordinal " + s.ordinal());
}
}
输出结果:
NOT,ordinal 0
MILD,ordinal 1
MEDIUM,ordinal 2
HOT,ordinal 3
FLAMING,ordinal 4
尽管enums显现成为一个新的数据类型,这个关键字仅仅当为enum产生一个类时产生一些编译行为,这样在很多时刻你可对待一个enum象其它任何类。事实上,enums是类并且具有它们自己的方法。
一个特别好的特点是enums可被用在switch语句中:
//:initialization/Burrito.java
public class Burrito{
Spiciness degree;
public Burrito(Spiciness degree){this.degree = degree;}
public void describe(){
System.out.print("This burrito is");
switch(degree){
case NOT: System.out.println("not spicy at all.");
break;
case MILD:
case MEDIUM: System.out.println("a little hot.");
break;
case HOT:
case FLAMING:
default: System.out.println("maybe too hot.");
}
}
public static void main(String[] args){
Burrito
plain = new Burrito(Spiciness.NOT),
greenChile = new Burrito(Spiciness.MEDIUM),
jalapeno = new Burrito(Spiciness.HOT);
plain.describe();
greenChile.describe();
jalapeno.describe();
}
}
This burrito is not spicy at all.
This burrito is a little hot.
This burrito is maybe too hot.
//:initialization/EnumOrder.java
public class EnumOrder{
public static void main(String[] args){
for(Spiciness s : Spiciness.values())
System.out.println(s + ", ordinal " + s.ordinal());
}
}
输出结果:
NOT,ordinal 0
MILD,ordinal 1
MEDIUM,ordinal 2
HOT,ordinal 3
FLAMING,ordinal 4
尽管enums显现成为一个新的数据类型,这个关键字仅仅当为enum产生一个类时产生一些编译行为,这样在很多时刻你可对待一个enum象其它任何类。事实上,enums是类并且具有它们自己的方法。
一个特别好的特点是enums可被用在switch语句中:
//:initialization/Burrito.java
public class Burrito{
Spiciness degree;
public Burrito(Spiciness degree){this.degree = degree;}
public void describe(){
System.out.print("This burrito is");
switch(degree){
case NOT: System.out.println("not spicy at all.");
break;
case MILD:
case MEDIUM: System.out.println("a little hot.");
break;
case HOT:
case FLAMING:
default: System.out.println("maybe too hot.");
}
}
public static void main(String[] args){
Burrito
plain = new Burrito(Spiciness.NOT),
greenChile = new Burrito(Spiciness.MEDIUM),
jalapeno = new Burrito(Spiciness.HOT);
plain.describe();
greenChile.describe();
jalapeno.describe();
}
}
This burrito is not spicy at all.
This burrito is a little hot.
This burrito is maybe too hot.
In general you can use an enum as if it were another way to create a date type,and then just put the results to work.That's the point,so you don't have to think too hard about them.Before the introduction of enum in Java SE5,you had to go to a lot of effort to make an equivalent enumerated type that was safe to use.
(本章完)