跳转到内容

方法

100% developed
来自维基教科书,开放世界中的开放书籍

导航 语言基础 主题:v  d  e )


方法是与对象沟通的方式。当我们调用或执行方法时,意味着请求对象执行一项任务。可以说,方法实现了对象的“行为”。对于每个方法,都需要给定名称、定义输入参数和返回值类型。此外,还需要设置其 可见性(私有、受保护或公共)。如果方法抛出检查型异常,也需要进行声明。这被称为“方法定义”。方法定义的语法如下:

MyClass {
  ...
  public ReturnType methodName(ParamOneType parameter1, ParamTwoType parameter2) {
      ...
      return returnValue;
  }
  ...
}

可以使用 Java 关键字 void 声明方法不返回任何值。例如:

Example 代码段 3.67:无返回值的方法。
private void methodName(String parameter1, String parameter2) {
  ...
  return;
}

当方法不返回任何值时,方法结尾处的 return 关键字是可选的。当执行流程到达 return 关键字时,方法执行停止,执行流程返回到调用者方法。只要有办法执行下面的指令, return 关键字可以在方法中的任何位置使用

Warning 代码段 3.68:return 关键字位置。
private void aMethod(int a, int b) {
  int c = 0;
  if (a > 0) {
    c = a;
    return;
  }
  int c = c + b;
  return;
  int c = c * 2;
}

代码段 3.68 中,第 5 行的 return 关键字放置正确,因为当 a 为负数或等于 0 时,可以到达下面的指令。但是,第 8 行的 return 关键字放置错误,因为无法到达下面的指令。

测试您的知识

问题 3.9:考虑以下代码

Example 问题 3.9:编译器错误。
private int myMethod(int a, int b, boolean c) {
  b = b + 2;
  if (a > 0) {
    a = a + b;
    return a;
  } else {
    a = 0;
  }
}

上面的代码将返回编译器错误。为什么?

答案
Example 答案 3.9:编译器错误。
private int myMethod(int a, int b, boolean c) {
  b = b + 2;
  if (a > 0) {
    a = a + b;
    return a;
  } else {
    a = 0;
  }
}

该方法应该返回一个 int 类型的值,但当 a 为负数或等于 0 时,它什么也不返回。

参数传递

[edit | edit source]

可以将任何 基本数据类型 或引用数据类型传递给方法。

基本类型参数

[edit | edit source]

基本类型是“按值传递”的。这意味着,一旦基本类型被传递进去,方法内部的值与源变量之间就再没有联系了

Example 代码段 3.69:修改变量的方法。
private void modifyValue(int number) {
  number += 1;
}
Example 代码段 3.70:传递基本值给方法。
int i = 0;
modifyValue(i);
System.out.println(i);
Standard input or output 代码段 3.70 的输出
0  

正如在 代码段 3.70 中所看到的, modifyValue() 方法并没有修改 i 的值。

引用类型参数

[edit | edit source]

对象引用是“按值传递”的。这意味着:

  • 方法内部的引用与源引用之间不再有联系,
  • 源对象本身和方法内部的对象本身仍然是同一个对象。

必须理解对象引用和对象本身之间的区别。对象引用是变量名与对象实例之间的链接

Object objectnew Object()

对象引用是一个指针,指向对象实例的地址。

对象本身是对象实例内属性的值

object.firstName "James"
object.lastName "Gosling"
object.birthDay "May 19"

查看上面的示例

Example 代码段 3.71:修改对象的方法。
private void modifyObject(FirstClass anObject) {
  anObject.setName("Susan");
}
Example 代码段 3.72:传递引用值给方法。
FirstClass object = new FirstClass();
object.setName("Christin");

modifyObject(object);

System.out.println(object.getName());
Standard input or output 代码段 3.72 的输出
Susan

姓名发生了变化,因为该方法修改了对象本身,而不是引用。现在,再看一下另一个示例

Example 代码段 3.73:修改对象引用的方法。
private void modifyObject(FirstClass anObject) {
  anObject = new FirstClass();
  anObject.setName("Susan");
}
Example 代码段 3.74:传递引用值给方法。
FirstClass object = new FirstClass();
object.setName("Christin");

modifyObject(object);

System.out.println(object.getName());
Standard input or output 代码段 3.74 的输出
Christin

姓名没有发生变化,因为该方法修改了引用,而不是对象本身。该行为与方法被内联并且参数被分配给新的变量名时的行为相同

Example 代码段 3.75:内联方法。
FirstClass object = new FirstClass();
object.setName("Christin");

// Start of the method
FirstClass anObject = object;
anObject = new FirstClass();
anObject.setName("Susan");
// End of the method

System.out.println(object.getName());
Standard input or output 代码段 3.75 的输出
Christin

可变参数列表

[edit | edit source]

Java SE 5.0 添加了对 可变参数列表 方法的语法支持,这简化了需要可变数量参数的方法的类型安全使用。非正式地说,这些参数被称为“varargs[1]。可变参数的类型必须后跟 ...,Java 会将所有参数打包成一个数组

Example 代码段 3.76:使用 vararg 参数的方法。
public void drawPolygon(Point... points) {
  //…
}

调用方法时,程序员只需用逗号分隔各个点,而无需显式创建 Point 对象的 数组。在方法内部,可以将各个点引用为 points[0]points[1] 等。如果没有传递任何点,则数组的长度为零。

一个方法既可以有普通参数,也可以有可变参数,但可变参数必须始终是最后一个参数。例如,如果程序员需要使用最小数量的参数,则这些参数可以在可变参数之前指定

Example 代码段 3.77:可变参数。
// A polygon needs at least three points.
public void drawPolygon(Point p1, Point p2, Point p3, Point... otherPoints) {
  //…
}

返回值参数

[edit | edit source]

方法可以返回一个值(可以是基本类型或对象引用)。如果方法不返回值,则使用 Java 关键字 void

但是,一个方法只能返回一个值,那么如果要从一个方法中返回多个值怎么办?可以将一个对象引用传递给方法,让方法修改对象的属性,这样修改后的值就可以被视为方法的输出值。还可以创建方法内部的 Object 数组,将返回值分配给数组,并将数组返回给调用者。但是,如果要将基本数据类型和对象引用混合作为方法的输出值,这种方法就会产生问题。

有一个更好的方法,定义一个包含所需返回值的特殊返回值对象。在方法内部创建该对象,分配值,并将对该对象的引用返回给调用者。这个特殊对象“绑定”到这个方法,只用于返回值,所以不要使用公共类。最好的方法是使用嵌套类,请看下面的示例

Computer code 代码清单 3.12:多个返回值变量。
public class MyObject {
  ...
 
  /** Nested object is for return values from getPersonInfoById method */
  private static class ReturnObject {
      private int age;
      private String name;

      public void setAge(int age) {
          this.age = age;
      }
 
      public int getAge() {
          return age;
      }

      public void setName(String name) {
          name = name;
      }
 
      public String getName() {
          return name;
      }
  } // End of nested class definition

  /** Method using the nested class to return values */
  public ReturnObject getPersonInfoById(int id) {
    int    age;
    String name;
    ...
    // Get the name and age based on the ID from the database
    ...
    ReturnObject result = new ReturnObject();
    result.setAge(age);
    result.setName(name);

    return result;
  }
}

在上面的示例中, getPersonInfoById 方法返回一个对象引用,其中包含姓名和年龄的两个值。请看下面如何使用该对象

Example 代码段 3.78:检索值。
MyObject object = new MyObject();
MyObject.ReturnObject person = object.getPersonInfoById(102);

System.out.println("Person Name=" + person.getName());
System.out.println("Person Age =" + person.getAge());
测试您的知识

问题 3.10:考虑以下代码

Example 问题 3.10:编译器错误。
private int myMethod(int a, int b, String c) {
  if (a > 0) {
    c = "";
    return c;
  }
  int b = b + 2;
  return b;
}

上面的代码将返回编译器错误。为什么?

答案
Example 答案 3.10:编译器错误。
private int myMethod(int a, int b, String c) {
  if (a > 0) {
    c = "";
    return c;
  }
  int b = b + 2;
  return b;
}

该方法应该返回一个 int 类型的值,但在第 4 行,它返回了 c,这是一个字符串。

特殊方法,构造函数

[edit | edit source]

构造函数是一个特殊方法,当使用 new 关键字创建对象时,它会自动调用。构造函数没有返回值,它的名称与类名相同。每个类都必须有一个构造函数。如果我们没有定义构造函数,编译器会自动创建一个称为“空构造函数”的默认构造函数。

Computer code 代码清单 3.13:自动创建的构造函数。
public class MyClass {
  /**
  * MyClass Empty Constructor
  */
  public MyClass() {
  }
}

静态方法

[edit | edit source]

静态方法是一种无需对象实例即可调用的方法。它可以直接在类上调用。例如,Integer 类的 valueOf(String) 方法就是一个静态方法

Example 代码段 3.79:静态方法。
Integer i = Integer.valueOf("10");

static 关键字使属性与实例无关。这意味着无法引用单个对象的静态属性(因为这种特定对象的属性不存在)。相反,无论 JVM 中存在一个对象还是一百个对象,静态属性只有一个实例。以下是在静态方法中使用静态属性的示例

Example 代码段 3.80:静态属性。
private static int count = 0;

public static int getNewInteger() {
  return count++;
}

您可以注意到,当您使用 `System.out.println()` 时,`out` 是 `System` 类的一个静态属性。静态属性与类相关,而不是与任何对象实例相关。这就是 Java 实现一个通用输出流的方式,我们可以使用它来打印输出。以下是一个更复杂的用例

Computer code 代码清单 3.14:静态属性。
public class MyProgram {

    public static int count = 0;

    public static void main (String[] args) {
        MyProgram.count++;

        MyProgram program1 = new MyProgram();
        program1.count++;

        MyProgram program2 = new MyProgram();
        program2.count++;

        new MyProgram().count++;
        System.out.println(MyProgram.count);
    }
}
Standard input or output 代码清单 3.14 的输出
4
测试您的知识

问题 3.11:访问 Oracle 的 `java.lang.Integer` 类 JavaDoc

这个类有多少个静态字段?

答案

4.

  • int MAX_VALUE,
  • int MIN_VALUE,
  • int SIZE
  • Class<Integer> TYPE.
要了解如何重载和覆盖方法,请参阅 重载方法和构造函数


华夏公益教科书