Documentation

The Java™ Tutorials
Hide TOC
Passing Information to a Method or a Constructor将信息传递给方法或构造函数
Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Classes

Passing Information to a Method or a Constructor将信息传递给方法或构造函数

The declaration for a method or a constructor declares the number and the type of the arguments for that method or constructor.方法或构造函数的声明声明了该方法或构造函数的参数数量和类型。For example, the following is a method that computes the monthly payments for a home loan, based on the amount of the loan, the interest rate, the length of the loan (the number of periods), and the future value of the loan:例如,以下是根据贷款金额、利率、贷款期限(周期数)和贷款未来价值计算住房贷款每月付款的方法:

public double computePayment(
                  double loanAmt,
                  double rate,
                  double futureValue,
                  int numPeriods) {
    double interest = rate / 100.0;
    double partial1 = Math.pow((1 + interest), 
                    - numPeriods);
    double denominator = (1 - partial1) / interest;
    double answer = (-loanAmt / denominator)
                    - ((futureValue * partial1) / denominator);
    return answer;
}

This method has four parameters: the loan amount, the interest rate, the future value and the number of periods.该方法有四个参数:贷款金额、利率、未来价值和期间数。The first three are double-precision floating point numbers, and the fourth is an integer.前三个是双精度浮点数,第四个是整数。The parameters are used in the method body and at runtime will take on the values of the arguments that are passed in.参数在方法体中使用,并且在运行时将采用传入的参数值。


Note: Parameters refers to the list of variables in a method declaration.形参是指方法声明中的变量列表。Arguments are the actual values that are passed in when the method is invoked.实参是调用方法时传入的实际值。When you invoke a method, the arguments used must match the declaration's parameters in type and order.调用方法时,使用的参数必须在类型和顺序上与声明的参数匹配。

Parameter Types参数类型

You can use any data type for a parameter of a method or a constructor.可以对方法或构造函数的参数使用任何数据类型。This includes primitive data types, such as doubles, floats, and integers, as you saw in the computePayment method, and reference data types, such as objects and arrays.这包括基本数据类型,如在computePayment方法中看到的DoubleFloatInteger,以及引用数据类型,如对象和数组。

Here's an example of a method that accepts an array as an argument.下面是一个接受数组作为参数的方法示例。In this example, the method creates a new Polygon object and initializes it from an array of Point objects (assume that Point is a class that represents an x, y coordinate):在本例中,该方法创建一个新的Polygon对象,并从Point对象数组对其进行初始化(假设点是一个表示x,y坐标的类):

public Polygon polygonFrom(Point[] corners) {
    // method body goes here
}

Note: If you want to pass a method into a method, then use a lambda expression or a method reference.如果要将方法传递给方法,请使用lambda表达式方法引用

Arbitrary Number of Arguments任意数量的参数

You can use a construct called varargs to pass an arbitrary number of values to a method.可以使用名为varargs的构造将任意数量的值传递给方法。You use varargs when you don't know how many of a particular type of argument will be passed to the method.当您不知道有多少特定类型的参数将传递给该方法时,可以使用varargs。It's a shortcut to creating an array manually (the previous method could have used varargs rather than an array).这是手动创建数组的快捷方式(前面的方法可能使用varargs而不是数组)。

To use varargs, you follow the type of the last parameter by an ellipsis (three dots, ...), then a space, and the parameter name.要使用varargs,请在最后一个参数的类型后面加一个省略号(三点,...),然后加一个空格和参数名。The method can then be called with any number of that parameter, including none.然后可以使用任意数量的参数调用该方法,包括none。

public Polygon polygonFrom(Point... corners) {
    int numberOfSides = corners.length;
    double squareOfSide1, lengthOfSide1;
    squareOfSide1 = (corners[1].x - corners[0].x)
                     * (corners[1].x - corners[0].x) 
                     + (corners[1].y - corners[0].y)
                     * (corners[1].y - corners[0].y);
    lengthOfSide1 = Math.sqrt(squareOfSide1);

    // more method body code follows that creates and returns a 
    // polygon connecting the Points
}

You can see that, inside the method, corners is treated like an array.您可以看到,在方法内部,corners被视为数组。The method can be called either with an array or with a sequence of arguments.可以使用数组或参数序列调用该方法。The code in the method body will treat the parameter as an array in either case.在这两种情况下,方法体中的代码都将参数视为数组。

You will most commonly see varargs with the printing methods; for example, this printf method:您将最常见地看到带有打印方法的varargs;例如,此printf方法:

public PrintStream printf(String format, Object... args)

allows you to print an arbitrary number of objects.允许您打印任意数量的对象。It can be called like this:可以这样调用:

System.out.printf("%s: %d, %s%n", name, idnum, address);

or like this还是像这样

System.out.printf("%s: %d, %s, %s, %s%n", name, idnum, address, phone, email);

or with yet a different number of arguments.或者有不同数量的论点。

Parameter Names参数名

When you declare a parameter to a method or a constructor, you provide a name for that parameter.向方法或构造函数声明参数时,请提供该参数的名称。This name is used within the method body to refer to the passed-in argument.此名称在方法体中用于引用传入的参数。

The name of a parameter must be unique in its scope.参数的名称在其作用域中必须是唯一的。It cannot be the same as the name of another parameter for the same method or constructor, and it cannot be the name of a local variable within the method or constructor.它不能与同一方法或构造函数的另一个参数的名称相同,也不能是该方法或构造函数中的局部变量的名称。

A parameter can have the same name as one of the class's fields.参数可以与类的某个字段同名。If this is the case, the parameter is said to shadow the field.如果是这种情况,则称该参数为字段的影子Shadowing fields can make your code difficult to read and is conventionally used only within constructors and methods that set a particular field.影子字段会使代码难以阅读,并且通常仅在设置特定字段的构造函数和方法中使用。For example, consider the following Circle class and its setOrigin method:例如,考虑下面的Circle类及其setOrigin方法:

public class Circle {
    private int x, y, radius;
    public void setOrigin(int x, int y) {
        ...
    }
}

The Circle class has three fields: x, y, and radius.Circle类有三个字段:xyradiusThe setOrigin method has two parameters, each of which has the same name as one of the fields.setOrigin方法有两个参数,每个参数与其中一个字段的名称相同。Each method parameter shadows the field that shares its name.每个方法参数都会对共享其名称的字段进行阴影处理。So using the simple names x or y within the body of the method refers to the parameter, not to the field.因此,在方法体中使用简单名称xy将引用参数,而不是字段。To access the field, you must use a qualified name.要访问该字段,必须使用限定名称。This will be discussed later in this lesson in the section titled "Using the this Keyword."这将在本课程后面标题为“使用this关键字”的部分中讨论

Passing Primitive Data Type Arguments传递原语数据类型参数

Primitive arguments, such as an int or a double, are passed into methods by value.原语参数(如intdouble)通过值传递给方法。This means that any changes to the values of the parameters exist only within the scope of the method.这意味着对参数值的任何更改只存在于方法的范围内。When the method returns, the parameters are gone and any changes to them are lost.当方法返回时,参数将消失,对它们的任何更改都将丢失。Here is an example:以下是一个例子:

public class PassPrimitiveByValue {

    public static void main(String[] args) {
           
        int x = 3;
           
        // invoke passMethod() with 
        // x as argument
        passMethod(x);
           
        // print x to see if its 
        // value has changed
        System.out.println("After invoking passMethod, x = " + x);
           
    }
        
    // change parameter in passMethod()
    public static void passMethod(int p) {
        p = 10;
    }
}

When you run this program, the output is:运行此程序时,输出为:

After invoking passMethod, x = 3

Passing Reference Data Type Arguments传递引用数据类型参数

Reference data type parameters, such as objects, are also passed into methods by value.引用数据类型参数(如对象)也按值传递给方法。This means that when the method returns, the passed-in reference still references the same object as before.这意味着当方法返回时,传入的引用仍然引用与以前相同的对象。However, the values of the object's fields can be changed in the method, if they have the proper access level.但是,如果对象字段具有适当的访问级别,则可以在方法中更改它们的值。

For example, consider a method in an arbitrary class that moves Circle objects:例如,考虑一个在移动Circle对象的任意类中的方法:

public void moveCircle(Circle circle, int deltaX, int deltaY) {
    // code to move origin of circle to x+deltaX, y+deltaY
    circle.setX(circle.getX() + deltaX);
    circle.setY(circle.getY() + deltaY);
        
    // code to assign a new reference to circle
    circle = new Circle(0, 0);
}

Let the method be invoked with these arguments:使用以下参数调用该方法:

moveCircle(myCircle, 23, 56)

Inside the method, circle initially refers to myCircle.在方法内部,circle最初指的是myCircleThe method changes the x and y coordinates of the object that circle references (that is, myCircle) by 23 and 56, respectively.该方法将圆引用的对象(即myCircle)的xy坐标分别更改2356These changes will persist when the method returns.当方法返回时,这些更改将保持不变。Then circle is assigned a reference to a new Circle object with x = y = 0.然后,circle被指定为一个x = y = 0的新圆对象的参照。This reassignment has no permanence, however, because the reference was passed in by value and cannot change.但是,此重新分配没有永久性,因为引用是按值传入的,无法更改。Within the method, the object pointed to by circle has changed, but, when the method returns, myCircle still references the same Circle object as before the method was called.在该方法中,circle指向的对象已更改,但是,当该方法返回时,myCircle仍然引用与调用该方法之前相同的circle对象。


Previous page: Providing Constructors for Your Classes
Next page: Objects