Gen*_* S. 8 java pass-by-reference pass-by-value
我是Java的新手(多年来一直在写其他东西),除非我遗漏了一些东西(我很高兴在这里错了)以下是一个致命的缺陷......
String foo = new String();
thisDoesntWork(foo);
System.out.println(foo);//this prints nothing
public static void thisDoesntWork(String foo){
foo = "howdy";
}
Run Code Online (Sandbox Code Playgroud)
现在,我很清楚(相当差的措辞)概念,在java中,一切都是通过"值"而不是"引用"传递的,但String是一个对象,有各种各样的花里胡哨,所以,人们会期待与int不同,用户可以对传递给方法的东西进行操作(并且不会被overloaded =设置的值所困).
有人可以向我解释这个设计选择背后的原因是什么?正如我所说,我不是想在这里,也许我错过了一些明显的东西?
当你传递"foo"时,你将对"foo" 的引用作为值传递给ThisDoesntWork().这意味着当您在方法内部执行"foo"赋值时,您只需将局部变量(foo)的引用设置为对新字符串的引用.
在考虑字符串在Java中的行为方式时要记住的另一件事是字符串是不可变的.它在C#中的工作方式相同,并且有一些很好的理由:
现在谈谈你更大的问题.为什么对象以这种方式传递?好吧,如果Java传递你的字符串就像你传统上所说的"按值",它必须实际复制整个字符串,然后再传递给你的函数.那很慢.如果它通过引用传递字符串并让你改变它(就像C一样),你就会遇到我刚刚列出的问题.
由于我的原始答案是"为什么会发生",而不是"为什么设计的语言如此发生",我会再给它一个.
为简化起见,我将摆脱方法调用并以另一种方式显示正在发生的事情.
String a = "hello";
String b = a;
String b = "howdy"
System.out.print(a) //prints hello
Run Code Online (Sandbox Code Playgroud)
为了得到最后的语句来输出"hello",b必须指向内存中的同一个"洞"是一个点(指针).当你想通过引用传递时,这就是你想要的.Java决定不去这个方向有几个原因:
指针令人困惑 Java的设计者试图删除一些关于其他语言的更令人困惑的事情.指针是C/C++最容易被误解和使用不当的结构之一,还有运算符重载.
指针是安全风险指针在误用时会导致许多安全问题.恶意程序会将内容分配给内存的那一部分,然后您认为您的对象实际上是其他人的内容.(Java已经摆脱了最大的安全问题,缓冲区溢出,带有已检查的数组)
抽象泄漏当你开始处理"内存中的内容和位置"时,你的抽象变得不那么抽象了.虽然抽象泄漏几乎肯定会侵入一种语言,但设计师并不想直接烘焙它.
对象都是你关心的 在Java中,一切都是对象,而不是对象所占据的空间.添加指针会使空间占据重要的对象,尽管.......
您可以通过创建"Hole"对象来模拟您想要的内容.您甚至可以使用泛型使其类型安全.例如:
public class Hole<T> {
private T objectInHole;
public void putInHole(T object) {
this.objectInHole = object;
}
public T getOutOfHole() {
return objectInHole;
}
public String toString() {
return objectInHole.toString();
}
.....equals, hashCode, etc.
}
Hole<String> foo = new Hole<String)();
foo.putInHole(new String());
System.out.println(foo); //this prints nothing
thisWorks(foo);
System.out.println(foo);//this prints howdy
public static void thisWorks(Hole<String> foo){
foo.putInHole("howdy");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1275 次 |
| 最近记录: |