我需要帮助的快速摘要:
String x=(String)y;
将y的值复制到x。为什么?
Test x=(Test)y;
在y处正确地指向x。
我有这个Java程序......有人可以解释引用的内容吗?
public class Main {
public static void foo(String a){
a="2";
}
public static void main(String[] args) {
String x="1";
foo(x);
System.out.println("x="+x);
}
}
输出:
x=1
预期产出:
x=2
发生了什么事?我认为无论我对a
内foo
所做的事情也会影响x
,因为a
只是x
的别名 - 不是吗?
这里有一个类似的问题:
public class Main {
public static void main(String[] args) {
String x=new String("1");
String y=new String("2");
y=x;
x="3";
System.out.println("x="+x);
System.out.println("y="+y);
}
}
输出:
x=3
y=1
预期产出:
x=3
y=3
有人可以解释一下吗?
编辑:
为什么这些例子会产生预期的结果,而上面的例子中没有String?
1:
public class Main {
private static class Test{
public String val;
public Test(String set){val=set;}
public Test(){}
}
public static void foo(Test a){
a.val="2";
}
public static void main(String[] args) {
Test x=new Test("1");
foo(x);
System.out.println("x="+x.val);
}
}
输出(和预期输出):
x=2
2:
public class Main {
private static class Test{
public String val;
public Test(String set){val=set;}
public Test(){}
}
public static void main(String[] args) {
Test x=new Test("1");
Test y=new Test("2");
x=y;
x.val="3";
System.out.println("x="+x.val);
System.out.println("y="+y.val);
}
}
输出(和预期输出):
x=3
y=3
答案 0 :(得分:4)
Java始终是值传递的。
传递的东西是对象的引用,而不是对象本身。
在String的情况下,它是一个不可变的类。因此,您无法在foo()方法中更改String引用所指向的内容。
但是,你可以这样做:
package cruft;
public class Main
{
private String value;
public Main(String s)
{
this.value = s;
}
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
public static void foo(Main main)
{
main.setValue("2");
}
@Override
public String toString()
{
return "Main{" +
"value='" + value + '\'' +
'}';
}
public static void main(String[] args)
{
Main main = new Main("1");
System.out.println("before: " + main);
foo(main);
System.out.println("after: " + main);
}
}
看到区别?我没有在foo()方法中更改对Main的引用;我只是改变了部分状态。
答案 1 :(得分:3)
a != x
。 a
是引用x
的副本,请考虑指向公共String的指针的副本。因此,a = "2"
说make a
等于对“2”的引用, not 使得指向的值a
等于“2”。 / p>
第二种情况x
& y
是您要更新的不同参考,以指向不同的值。
基本上,所有Java值(不包括基元)都是引用类型(C ++表示法中的some_class*
),并且所有函数都作为pass-by-value调用。因此,调用一些引用类型作为参数的方法会复制这些参数。
答案 2 :(得分:1)
将对象视为在内存中漂浮的数据blob。您定义的变量(如String s)指向这些blob:它们不代表blob本身。
相反,int
直接引用值。
答案 3 :(得分:1)
为什么我使用自己的类而不是使用String获得预期的结果?
简单说明,因为你正在比较苹果和橘子。您的String示例正在执行a = "2";
,但您后面的示例正在执行a.val = "2";
。第一个是尝试更新调用者中的引用...这不起作用。第二个是成功的,因为你告诉它(使用“。”运算符)来改变引用所表示的对象的状态。
如果您更改后面的示例以执行String示例尝试执行的操作,您会发现它们也不起作用。
第二点是您无法更改String的状态,因为String API旨在使其无法实现。相比之下,您的课程旨在允许更改其状态。但这并不能解释您所看到的行为,因为您的String示例甚至不是尝试来更改String的状态。
答案 4 :(得分:1)
首先:我知道这是虚伪的,但我认为把这个想法牢牢掌握在脑海中的最佳位置是获取Java教科书(或者可能是在线教程)。我不认为你能通过我们的答案对这些概念有充分的了解。
也许尝试(我没有读过这些,只是略读):
我将尝试以不同的方式回答这个问题。正确的答案已经存在,但是如果你不与这个人面对面,这种事情很难解释IMO。
这是你的第一段代码:
public class Main {
public static void foo(String a){
a="2";
}
public static void main(String[] args) {
String x="1";
foo(x);
System.out.println("x="+x);
}
}
问题是行a = "2"
。简单来说,它意味着:“使变量'a'指向一个值为'2'的String实例”。这意味着:“忘记当前指向的'a'字符串,以便它可以指向这个新值”。因此,您要告诉它忘记它指向您传递的String(作为方法的参数),因此它可以指向新的。
作为参数传递的String仍然存在,变量“x”仍然指向它。您没有更改变量'x'指向的String,只更改了变量'a'指向的String。
如上所述,这是因为Java使用pass-by-value而不是pass-by-reference。