3

我正在学习 Java 中的类和构造函数。我在一个示例程序中弄乱了代码,似乎无法弄清楚到底发生了什么。

这段代码无法编译,这对我来说很有意义:

class Line {
Point start;
Point end;

Line(final Point start, final Point end) {

    this.start = new Point(start);
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}...

我试图通过调用 Point 对象的构造函数将原始起始点对象引用分配给另一个 Point 对象。final 关键字与此冲突。

但是,当我从 Point start 参数中删除 final 关键字时...

class Line {
Point start;
Point end;

Line(Point start, final Point end) {

    this.start = new Point(start);
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}

它似乎并没有真正改变引用,传递给 Line 构造函数的 Point 对象似乎仍然指向原始对象,并且 Line 构造函数的代码没有改变。那么给了什么?这是否与所指的“开始”在 Line 构造函数的范围内是本地的事实有关?

4

5 回答 5

5

Java 不使用按引用传递,它始终使用按值传递。实际上,Java 中的引用类型只是指针,与 C# 中的引用完全不同。

因此,当您在构造函数中执行此语句时:

start = new Point(0.4, 0.4);

原始Point传入参数没有改变。但是,局部变量(即参数)将指向新Point定义的坐标:0,4, 0,4

为了更好地理解,请阅读这篇文章:Java is Pass-by-Value, Dammit!

于 2012-11-18T23:36:20.987 回答
0

该变量是构造函数的本地变量。因此,在构造函数之外为其分配一个新的引用没有意义,因为它在构造函数之外不存在。

实现这种效果的一种方法是将其包裹在另一个对象中。并传递对可变包装器的引用。

于 2012-11-18T23:36:35.673 回答
0

它似乎并没有真正改变参考

您不能更改用于在该方法本身内部调用方法的参数的引用。参数的值(它是对对象的引用)被复制到方法参数中,因此您对同一对象有第二个引用。在方法内部,您只能修改第二个引用,而不能更改原始引用。您唯一能做的就是修改引用的对象。

于 2012-11-18T23:36:39.363 回答
0

当您执行“start = new Point(0.4, 0.4);”时,您将引用在构造函数中接收到的开始。由于构造函数将其定义为 final,因此为变量分配新值是非法的。

细节是,由于java使用按值传递的方法,即使您不使用final并更改构造函数内部的值,原始值(您作为参数传递给方法的值)的值仍然是相同。

于 2012-11-18T23:38:28.493 回答
0

当您在从“Line(Point start, final Point end) {”初始化后通过执行“this.start = new Point(start)”来修改“start”时,您并没有替换“start”指向的堆上的实际对象到但在与现有的不同区域的堆上分配新的 Point 对象,并修改现有的指针“start”(STACK 上的标量类型)以指向新分配的。

构造函数是一种特殊用途的方法(函数),在java堆上分配对象后由java的new操作符调用。所以当一个方法被调用时,堆栈被分配并且任何标量类型(在java中它是原始类型,如int,double,char ...)和方法中的REFERENCE被分配在堆栈(而不是堆)上。当您将语句编写为“final Object o = new Object()”时,您已经在内存上分配了两件事。
首先,Java 堆上的“new Object()”。(HEAP)
其次,指向堆栈中的上方的指针,即“Object o”。(堆栈)
在您的情况下,您只是试图覆盖标量类型的“final Object o”,并且只在 jvm 内存(堆栈)上读取。

class Line {
Point start;
Point end;

// On the first line "Line(Point start, Point end) {",
// two references and two actual Objects that references point to
// are already allocated in memory.  
// So you've allocated four things.
Line(Point start, final Point end) { // "start" initialized on stack as final
    this.start = new Point(start); // tried to modify final variable on stack.
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}
于 2012-11-19T00:30:39.847 回答