Java 显然是按值传递,但需要一些说明
Java is clearly a pass by value but wanted some clarification
阅读了很多关于这个主题的堆栈溢出答案,我也阅读了很多博客。我可以肯定地得出结论,Java 是按值传递的。
但是为了说服人们,我需要一些语言的证明,该证明已通过 ref.
所以有人可以给出一个通过引用传递的语言的实例,我们可以将 java 不是通过引用传递的例子联系起来。
我不知道有什么语言一直是按引用传递的,但 C# 有 ref
修饰符,它允许特定参数使用按引用传递。这使您可以很容易地看到差异。例如:
using System;
public class Program
{
static void Main()
{
string x = "original x";
string y = "original y";
Modify(x, ref y);
Console.WriteLine(x);
Console.WriteLine(y);
}
static void Modify(string px, ref string py)
{
px = "modified x";
py = "modified y";
}
}
输出为
original x
modified y
这是因为对 px
的赋值不会影响调用代码中的 x
:x
的 value 被传递给方法。但是对 py
的赋值确实 改变了 y
,因为 y
是通过引用 传递的 ; py
和 y
基本上是同一存储位置的别名。
所有这些只有在您修改参数本身时才有意义。将上面的程序与这个程序进行比较:
using System;
using System.Text;
public class Program
{
static void Main()
{
StringBuilder x = new StringBuilder("original x");
Modify(x);
Console.WriteLine(x);
}
static void Modify(StringBuilder px)
{
px.Length = 0;
px.Append("modified x");
}
}
现在 Modify
方法根本不会更改 px
的值 - 而不是更改 px
的值所引用的对象。不需要按引用传递 - x
的值通过值 传递给方法 ,然后复制到 px
。这就像在一张纸上抄下您的家庭住址并将其交给某人。它不是复制房子本身 - 它只是复制 到达 房子的方式。如果你给纸的人去把前门漆成红色,那么当你回家时你会看到这种变化。
这就是为什么了解 variables, objects and references.
之间的区别很重要的原因
C++ 有不同的参数传递方式。一种方法是将指针类型指定为参数。我认为这与 Java 的作用很接近。指针按值传递。您可以修改指针引用的对象的状态,但不能更改调用函数引用的对象实例。
我包含了一个带有两个函数的 C++ 示例。一个具有按值调用的函数和一个具有按引用语义调用的函数。具有按引用调用语义的函数可以更改调用函数正在引用的对象实例。
#include <iostream>
using namespace std;
class ClassA
{
public:
int a = 0;
};
void funcByValue(ClassA *param)
{
param->a = 1;
param = new ClassA();
}
void funcByReference(ClassA* ¶m)
{
param->a = 1;
param = new ClassA();
}
int main()
{
ClassA *objectA = new ClassA();
cout << objectA->a << "\n"; //1
cout << objectA << "\n"; //0000002B1D355AF0
//This call changes objectA's state
funcByValue(objectA);
cout << objectA->a << "\n"; //1
cout << objectA << "\n"; //0000002B1D355AF0
//This call changes the object objectA is referencing
funcByReference(objectA);
cout << objectA->a << "\n"; //0
cout << objectA << "\n"; //0000002B1D345610
}
Java 是按值传递:
最好的例子:
http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html
C++ 是按引用传递的,也是按值传递的:
http://www.tech-recipes.com/rx/1232/c-pointers-pass-by-value-pass-by-reference/
So can someone give a live example of a language which is pass by reference by whose example we could relate that java is not pass by reference
引用传递与值传递的最佳示例是交换。
void swap(String a, String b) {
String c = b;
b = a;
a = c;
}
void main() {
String a = "A";
String b = "B";
swap(a, b);
System.out.println(a); // A
System.out.println(b); // B
}
在这种情况下,虽然变量 main.a 指向与 swap.a 相同的对象,但您有两个对字符串 "A".
的引用
vs C# (IDE One) 支持 by-ref.
void Swap(ref string a, ref string b) {
string c = b;
b = a;
a = c;
}
void main() {
string a = "A";
string b = "B";
Swap(ref a, ref b);
Console.WriteLine(a); // B
Console.WriteLine(b); // A
}
在这种情况下,变量 main.a 和 swap.a 是相同的引用,因此对 swap.a 的更改也会发生在 main.a。
那么这与
有何不同
void swap(StringBuilder a, StringBuilder b) {
String a1 = a.toString();
String b1 = b.toString();
a.setLength(0);
a.append(b1);
b.setLength(0);
b.append(a1);
}
void main(){
StringBuilder a = new StringBuilder("A");
StringBuilder b = new StringBuilder("B");
swap(a, b);
System.out.println(a); // B
System.out.println(b); // A
}
在这种情况下,指向的对象会发生变化。例如:
public static void main(String... agv){
StringBuilder a = new StringBuilder("A");
StringBuilder b = new StringBuilder("B");
StringBuilder alsoA = a;
swap(a, b);
System.out.println(a); // B
System.out.println(b); // A
System.out.println(alsoA); //B
}
与 C# 中的对比 (IDEOne)
void Main() {
string a = "a";
string b = "b";
string alsoA = a;
Swap(ref a, ref b);
Console.WriteLine(a); // B
Console.WriteLine(b); // A
Console.WriteLine(alsoA); // A
}
Java 如果您仍然不确定,Ranch 有 good article。
阅读了很多关于这个主题的堆栈溢出答案,我也阅读了很多博客。我可以肯定地得出结论,Java 是按值传递的。
但是为了说服人们,我需要一些语言的证明,该证明已通过 ref.
所以有人可以给出一个通过引用传递的语言的实例,我们可以将 java 不是通过引用传递的例子联系起来。
我不知道有什么语言一直是按引用传递的,但 C# 有 ref
修饰符,它允许特定参数使用按引用传递。这使您可以很容易地看到差异。例如:
using System;
public class Program
{
static void Main()
{
string x = "original x";
string y = "original y";
Modify(x, ref y);
Console.WriteLine(x);
Console.WriteLine(y);
}
static void Modify(string px, ref string py)
{
px = "modified x";
py = "modified y";
}
}
输出为
original x
modified y
这是因为对 px
的赋值不会影响调用代码中的 x
:x
的 value 被传递给方法。但是对 py
的赋值确实 改变了 y
,因为 y
是通过引用 传递的 ; py
和 y
基本上是同一存储位置的别名。
所有这些只有在您修改参数本身时才有意义。将上面的程序与这个程序进行比较:
using System;
using System.Text;
public class Program
{
static void Main()
{
StringBuilder x = new StringBuilder("original x");
Modify(x);
Console.WriteLine(x);
}
static void Modify(StringBuilder px)
{
px.Length = 0;
px.Append("modified x");
}
}
现在 Modify
方法根本不会更改 px
的值 - 而不是更改 px
的值所引用的对象。不需要按引用传递 - x
的值通过值 传递给方法 ,然后复制到 px
。这就像在一张纸上抄下您的家庭住址并将其交给某人。它不是复制房子本身 - 它只是复制 到达 房子的方式。如果你给纸的人去把前门漆成红色,那么当你回家时你会看到这种变化。
这就是为什么了解 variables, objects and references.
之间的区别很重要的原因C++ 有不同的参数传递方式。一种方法是将指针类型指定为参数。我认为这与 Java 的作用很接近。指针按值传递。您可以修改指针引用的对象的状态,但不能更改调用函数引用的对象实例。
我包含了一个带有两个函数的 C++ 示例。一个具有按值调用的函数和一个具有按引用语义调用的函数。具有按引用调用语义的函数可以更改调用函数正在引用的对象实例。
#include <iostream>
using namespace std;
class ClassA
{
public:
int a = 0;
};
void funcByValue(ClassA *param)
{
param->a = 1;
param = new ClassA();
}
void funcByReference(ClassA* ¶m)
{
param->a = 1;
param = new ClassA();
}
int main()
{
ClassA *objectA = new ClassA();
cout << objectA->a << "\n"; //1
cout << objectA << "\n"; //0000002B1D355AF0
//This call changes objectA's state
funcByValue(objectA);
cout << objectA->a << "\n"; //1
cout << objectA << "\n"; //0000002B1D355AF0
//This call changes the object objectA is referencing
funcByReference(objectA);
cout << objectA->a << "\n"; //0
cout << objectA << "\n"; //0000002B1D345610
}
Java 是按值传递:
最好的例子:
http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html
C++ 是按引用传递的,也是按值传递的:
http://www.tech-recipes.com/rx/1232/c-pointers-pass-by-value-pass-by-reference/
So can someone give a live example of a language which is pass by reference by whose example we could relate that java is not pass by reference
引用传递与值传递的最佳示例是交换。
void swap(String a, String b) {
String c = b;
b = a;
a = c;
}
void main() {
String a = "A";
String b = "B";
swap(a, b);
System.out.println(a); // A
System.out.println(b); // B
}
在这种情况下,虽然变量 main.a 指向与 swap.a 相同的对象,但您有两个对字符串 "A".
的引用vs C# (IDE One) 支持 by-ref.
void Swap(ref string a, ref string b) {
string c = b;
b = a;
a = c;
}
void main() {
string a = "A";
string b = "B";
Swap(ref a, ref b);
Console.WriteLine(a); // B
Console.WriteLine(b); // A
}
在这种情况下,变量 main.a 和 swap.a 是相同的引用,因此对 swap.a 的更改也会发生在 main.a。
那么这与
有何不同void swap(StringBuilder a, StringBuilder b) {
String a1 = a.toString();
String b1 = b.toString();
a.setLength(0);
a.append(b1);
b.setLength(0);
b.append(a1);
}
void main(){
StringBuilder a = new StringBuilder("A");
StringBuilder b = new StringBuilder("B");
swap(a, b);
System.out.println(a); // B
System.out.println(b); // A
}
在这种情况下,指向的对象会发生变化。例如:
public static void main(String... agv){
StringBuilder a = new StringBuilder("A");
StringBuilder b = new StringBuilder("B");
StringBuilder alsoA = a;
swap(a, b);
System.out.println(a); // B
System.out.println(b); // A
System.out.println(alsoA); //B
}
与 C# 中的对比 (IDEOne)
void Main() {
string a = "a";
string b = "b";
string alsoA = a;
Swap(ref a, ref b);
Console.WriteLine(a); // B
Console.WriteLine(b); // A
Console.WriteLine(alsoA); // A
}
Java 如果您仍然不确定,Ranch 有 good article。