接着上篇文章来,我们先来看如何声明和调用一个 void 方法。下面的例子声明了一个名为 printGrade 的方法,并且调用它来打印给定的分数:
public class TestVoidMethod {
public static void main(String[] args) {
printGrade(78.5);
}
public static void printGrade(double score) {
if (score >= 90.0) {
System.out.println('A');
}
else if (score >= 80.0) {
System.out.println('B');
}
else if (score >= 70.0) {
System.out.println('C');
}
else if (score >= 60.0) {
System.out.println('D');
}
else {
System.out.println('F');
}
}
}
运行结果大家可以动手试试看下。不过这里printGrade方法是一个void类型方法,它不返回值。一个void方法的调用一定是一个语句。 所以,它被在main方法第三行以语句形式调用。就像任何以分号结束的语句一样。
然后我们来看如何通过值传递参数。调用一个方法时候需要提供参数,你必须按照参数列表指定的顺序提供。例如,下面的方法连续n次打印一个消息:
public static void nPrintln(String message, int n) {
for (int i = 0; i < n; i++) {
System.out.println(message);
}
}
下面的例子演示按值传递的效果,该程序创建一个方法,该方法用于交换两个变量:
public class TestPassByValue {
public static void main(String[] args) {
int num1 = 1;
int num2 = 2;
System.out.println("交换前 num1 的值为:" +
num1 + " ,num2 的值为:" + num2);
// 调用swap方法
swap(num1, num2);
System.out.println("交换后 num1 的值为:" +
num1 + " ,num2 的值为:" + num2);
}
/** 交换两个变量的方法 */
public static void swap(int n1, int n2) {
System.out.println("\t进入 swap 方法");
System.out.println("\t\t交换前 n1 的值为:" + n1
+ ",n2 的值:" + n2);
// 交换 n1 与 n2的值
int temp = n1;
n1 = n2;
n2 = temp;
System.out.println("\t\t交换后 n1 的值为 " + n1
+ ",n2 的值:" + n2);
}
}
运行结果为:
交换前 num1 的值为:1 ,num2 的值为:2 进入 swap 方法 交换前 n1 的值为:1,n2 的值:2 交换后 n1 的值为 2,n2 的值:1 交换后 num1 的值为:1 ,num2 的值为:2
传递两个参数调用swap方法。有趣的是,方法被调用后,实参的值并没有改变。
这个完事了之后,再来看下方法的重载。首先,上面使用的max方法仅仅适用于int型数据。但如果你想得到两个浮点类型数据的最大值呢?解决方法是创建另一个有相同名字但参数不同的方法,如下面代码所示:
public static double max(double num1, double num2) {
if (num1 > num2)
return num1;
else
return num2;
}
如果你调用max方法时传递的是int型参数,则 int型参数的max方法就会被调用。如果传递的是double型参数,则double类型的max方法体会被调用,这叫做方法重载。就是说一个类的两个方法拥有相同的名字,但是有不同的参数列表。Java编译器根据方法签名判断哪个方法应该被调用。方法重载可以让程序更清晰易读。执行密切相关任务的方法应该使用相同的名字。重载的方法必须拥有不同的参数列表。你不能仅仅依据修饰符或者返回类型的不同来重载方法。
完事就来看下变量的作用域。变量的范围是程序中该变量可以被引用的部分。方法内定义的变量被称为局部变量。局部变量的作用范围从声明开始,直到包含它的块结束。局部变量必须声明才可以使用。方法的参数范围涵盖整个方法。参数实际上是一个局部变量。for循环的初始化部分声明的变量,其作用范围在整个循环。但循环体内声明的变量其适用范围是从它声明到循环体结束。它包含如下所示的变量声明:
你可以在一个方法里,不同的非嵌套块中多次声明一个具有相同的名称局部变量,但你不能在嵌套块内两次声明局部变量。大概了解了之后,咱们就来看命令行参数的使用。
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。命令行参数是在执行程序时候紧跟在程序名字后面的信息。下面的程序打印所有的命令行参数:
public class CommandLine {
public static void main(String args[]){
for(int i=0; i<args.length; i++){
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
如下所示 ,我们来运行这个程序:
$ javac CommandLine.java $ java CommandLine this is a command line 200 -100 args[0]: this args[1]: is args[2]: a args[3]: command args[4]: line args[5]: 200 args[6]: -100
我们再来看构造方法,当一个对象被创建时候,构造方法用来初始化该对象。构造方法和它所在类的名字相同,但构造方法没有返回值。通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。不管你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个默认构造方法,它把所有成员初始化为0。一旦你定义了自己的构造方法,默认构造方法就会失效。下面是一个使用构造方法的例子:
// 一个简单的构造函数
class MyClass {
int x;
// 以下是构造函数
MyClass() {
x = 10;
}
}
我们可以像下面这样调用构造方法来初始化一个对象:
public class ConsDemo {
public static void main(String args[]) {
MyClass t1 = new MyClass();
MyClass t2 = new MyClass();
System.out.println(t1.x + " " + t2.x);
}
}
不过大多时候需要一个有参数的构造方法。下面是一个使用构造方法的例子:
// 一个简单的构造函数
class MyClass {
int x;
// 以下是构造函数
MyClass(int i ) {
x = i;
}
}
我们可以像下面这样调用构造方法来初始化一个对象:
public class ConsDemo {
public static void main(String args[]) {
MyClass t1 = new MyClass( 10 );
MyClass t2 = new MyClass( 20 );
System.out.println(t1.x + " " + t2.x);
}
}
运行结果为:
10 20
那么参数可不可以改变呢?答案是可以。JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。方法的可变参数的声明如下所示:
在方法声明中,在指定参数类型后加一个省略号(...)。一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明:
public class VarargsDemo {
public static void main(String args[]) {
// 调用可变参数的方法
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
}
public static void printMax( double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return;
}
double result = numbers[0];
for (int i = 1; i < numbers.length; i++){
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("The max value is " + result);
}
}
运行结果为:
The max value is 56.5 The max value is 3.0
然后呢,再来看finalize()方法。Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象。例如,你可以使用 finalize() 来确保一个对象打开的文件被关闭了。在 finalize() 方法里,你必须指定在对象销毁时候要执行的操作。finalize() 一般格式是:
protected void finalize()
{
// 在这里终结代码
}
关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。当然,Java 的内存回收可以由 JVM 来自动完成。如果你手动使用,则可以使用上面的方法。我们来看个实例:
public class FinalizationDemo {
public static void main(String[] args) {
Cake c1 = new Cake(1);
Cake c2 = new Cake(2);
Cake c3 = new Cake(3);
c2 = c3 = null;
System.gc(); //调用Java垃圾收集器
}
}
class Cake extends Object {
private int id;
public Cake(int id) {
this.id = id;
System.out.println("Cake Object " + id + "is created");
}
protected void finalize() throws java.lang.Throwable {
super.finalize();
System.out.println("Cake Object " + id + "is disposed");
}
}
运行下看看:
$ javac FinalizationDemo.java $ java FinalizationDemo Cake Object 1is created Cake Object 2is created Cake Object 3is created Cake Object 3is disposed Cake Object 2is disposed
再来补充下构造方法。当一个对象被创建时候,构造方法用来初始化该对象。构造方法和它所在类的名字相同,但构造方法没有返回值。通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。不管你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个默认构造方法,它把所有成员初始化为0。一旦你定义了自己的构造方法,默认构造方法就会失效。当创建对象时,系统会自动调用构造方法:
- 没有自定义构造方法时,系统会调用默认构造方法
- 构造方法可以重载,不同的构造方法名字相同,参数列表不同,参数列表是其识别的依据、标志,类似不同人可能有相同的名字,但有不同的身份证号。
- 当自定义构造方法时,系统依据传入的参数类型、数量,自动匹配构造方法初始化对象