Java永远不会通过引用传递,对吗?......对吗?

Tro*_*ols 45 java pass-by-reference pass-by-value

可能重复:
Java是"传递引用"吗?

我今天发现了一种不寻常的Java方法:

private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
     if (null == vsName)
       vsName = "";
     else
       vsName = vsName.trim();
     String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
     //SCR10638 - Prevent export of empty rows.
     if (shortenedVoiceSetName.length() > 0)
     {
       if (!voiceSetList.contains("#" + shortenedVoiceSetName))
         voiceSetList.add("#" + shortenedVoiceSetName);
     }
}
Run Code Online (Sandbox Code Playgroud)

根据我读过的有关Java传递变量,复杂对象的行为的一切,这段代码应该什么都不做.所以嗯......我在这里错过了一些东西吗?是否有一些微妙的东西丢失在我身上,或者这些代码是否属于thedailywtf?

Mic*_*ers 105

正如Rytmis所说,Java通过值传递引用.这意味着您可以合法地在方法的参数上调用变异方法,但是您无法重新分配它们并期望值传播.

例:

private void goodChangeDog(Dog dog) {
    dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
    dog = new StBernard(); // compiles, but has no effect outside the method
}
Run Code Online (Sandbox Code Playgroud)

编辑:在这种情况下,这意味着虽然voiceSetList 可能会因此方法而改变(它可能会添加一个新元素),但更改vsName将在方法外部不可见.为了避免混淆,我经常标记我的方法参数final,这样就不会在方法中重新分配(意外或不重新).这将使第二个例子完全不进行编译.

  • @Bill K:如果你想防止将参数作为局部变量处理,那么将参数标记为final是可以的.但是,对我来说,最后只是为了"防止"人们认为局部参数赋值修改外部引用是没有意义的; 如果他们认为首先他们可能应该先学习Java(或几乎任何流行的OO语言?).此外,我同意Java中的限制因为它与静态类型的理念一致,我想我现在将标记我的参数最终:) (5认同)
  • "为了避免混淆,我经常将我的方法参数标记为final,这样就不会在方法内部重新分配(意外或不重新)." 我不相信你,你为什么要改变每一个功能来明确一个已经存在的语言功能?为什么我要问这是因为,如果对他不明确的是,赋值不会修改对象,那么就无法理解Java. (4认同)

Ryt*_*mis 28

Java 按值传递引用,因此您获得引用的副本,但引用的对象是相同的.因此,此方法会修改输入列表.

  • Java变量的两个原则:1)变量通过值传递2)所有变量都是引用(或基元). (10认同)

the*_*_mr 8

引用本身是按值传递的。

\n\n

摘自《Java 如何编程》,第 4 版,作者:Deitel & Deitel:(第 329 页)

\n\n
\n

与其他语言不同,Java 不允许程序员选择是按值还是按引用传递每个参数。原始数据类型变量始终按值传递。对象不传递给方法;相反,对对象的引用将传递给方法。引用本身通过值\xe2\x80\x94 传递引用的副本\n 传递给方法。当方法接收到对象的引用时,该方法可以直接操作该对象。

\n
\n\n

大学学习Java的时候用过这本书。精彩的参考。

\n\n

这是一篇解释它的好文章。\n http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

\n