我正在学习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构造函数的代码保持不变。什么给出了什么?这是否与被引用的'start'在Line构造函数的范围内是本地的这一事实有关?
答案 0 :(得分:5)
Java不使用pass-by-reference,它使用ALWAYS pass-by-value。 实际上,Java中的引用类型只是指针,并不像C#中的引用那样共享相同的含义。
所以当你在构造函数中执行此语句时:
start = new Point(0.4, 0.4);
传入参数的原始Point
未更改。
但是,局部变量(表示参数)将指向由坐标Point
定义的新0,4, 0,4
。
为了更好地理解,请阅读这篇文章:Java is Pass-by-Value, Dammit!
答案 1 :(得分:0)
该变量是构造函数的本地变量。因此,在构造函数之外为它指定一个新引用是没有意义的,因为它不存在于构造函数之外。
实现这种效果的一种方法是将其包装在另一个对象中。并传递对可变包装器的引用。
答案 2 :(得分:0)
它似乎没有真正改变参考
您无法更改用于在该方法内调用方法的参数的引用。参数的值(对象的引用)将复制到方法参数中,因此您可以对同一对象进行第二次引用。在方法内部,您只能修改第二个引用,并且不能更改原始引用。你唯一能做的就是修改引用的对象。
答案 3 :(得分:0)
当您执行“start = new Point(0.4,0.4);”时,您将引用构造函数上收到的开头。当构造函数将其定义为final时,将非新的值赋给变量是非法的。
细节是,当java使用按值传递方法时,即使您不使用final并更改构造函数内的值,也会将原始值的值(作为参数传递给方法的值) )仍然是一样的。
答案 4 :(得分: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。
当您将状态写为“最终对象o =新对象()”时,您已在内存中分配了两个内容
首先,java堆上的“new Object()”。 (堆)
第二,指向堆栈上方的指针,即“对象o”。 (STACK)
在你的情况下,你只是试图覆盖标量类型的“最终对象o”并且只读取jvm内存(STACK)。
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);
}