Java 传递常量是否自动通过引用传递?

Java 传递常量是否自动通过引用传递?,java,c#,c++,c,pass-by-reference,Java,C#,C++,C,Pass By Reference,如果我将一个变量传递给函数,但将该变量标记为常量,它会自动通过引用传递吗 在C++中 测试后:否,因为它打印不同的内存位置 void foo(const int a) { cout << &a << endl; } int main() { int a = 5; foo(a); cout << &a << endl; return 0; } C# 和Java一样 void foo(const

如果我将一个变量传递给函数,但将该变量标记为常量,它会自动通过引用传递吗


在C++中 测试后:否,因为它打印不同的内存位置

void foo(const int a)
{
    cout << &a << endl;
}

int main()
{
   int a = 5;
   foo(a);
   cout << &a << endl;
   return 0;
}

C# 和Java一样

void foo(const int a)


我知道我的问题中包括了4种语言,但因为我经常使用这4种语言,所以我想知道

有没有办法强迫Java和C来处理这个问题?我知道C++中我可以把代码>和代码>添加到函数中,它将是我想要的。
 void f(const int &a)

这正是我希望Java和C编译器在幕后做的事情。

在Java中,所有变量都是按值传递的

原语实际上是复制的,而对象变量无论如何都是引用,这意味着对象变量的值实际上是引用->您正在传递引用的值

不过,您总是通过值,与C++相同,如果不显式使用引用,则值将通过。 我几乎可以肯定,这在C#中是一样的

编辑:我忘了C

在C中也是一样的:默认情况下按值传递。显然,您可以传递指针。在C++中,这是扩展的,因此您可以将引用作为参数:

void function(int& intByReference) {
    cout<<&intByReference<<endl; //prints x
}

int main() {
    int n = 0;
    cout<<&n<<endl; //prints x
    function(n);
}

您错误地认为您的直觉可以指导您如何实现语言的细节。这完全不是事实。在C++和C的情况下,规范清楚地说明了如何处理这个问题。
Java作为一种传递值语言,在final/const/not-moved值的规范中可能对这种行为有一些规定。(我不知道)但只有规范允许这种行为。

在回答您的问题之前,让我举例来测试您的场景

假设通过传递变量
inta
从方法
void calledFrom()
调用一个方法
void called(inta)

据我理解:

如果在任何方法中a的值的更改影响另一个(从调用的
中a的更改影响调用的
中a的值),则其通过引用调用,否则其通过值调用

现在让我们使用final在java中测试这一点

public class MyClass
{
    int a;
    public void setA(final int a)
    {
        this.a=a;
    }
    public void printA()
    {
        System.out.println(a);
    }

}
从main方法可以执行以下操作:

int a=10;
MyClass mclass=new MyClass();

mclass.setA(a);
mclass.printA();
a++;
mclass.printA();
输出为: 10 十,

因此,在
main
中更改,而不是在
MyClass
中更改
a
的值。所以对公共void setA(final int a)
的调用不是按引用调用的,而是按值调用的

final
可能会引起一些混淆。当您在方法中编写final时,签名不会以任何其他方式影响is行为
,除非您不能在该方法中更改该参数的值。
例如,如果你写

public void setA(final int a)
{
    a++; //error
    this.a=a;
}
您将得到一个编译错误

但你可以做到这一点

 public void printA()
{
    a++; //ok
    System.out.println(a);
}
我认为这不仅仅是在java中,所有其他语言都有相同的行为。你可以用其他语言试试

要在java上下文中获得关于按值传递和按引用传递的清晰概念,您可以阅读thread


或者阅读答案

所有这些都是语义上的按值传递。编译器能否在引擎盖下进行优化?当然,这是可能的。我猜你会问这个问题,因为你经常看到C++函数原型,把一个const对象引用为一个参数。这是一种有意的优化,允许函数参数值为右值,而不必为函数调用复制它们(C++11也可以添加右值引用)。但是,const函数参数在默认情况下不会通过引用传递。对于一个包含多个语言标记且实际上与它们都相关的问题,+1。Java原语没有引用。Java总是按值传递的。你的问题“有没有办法强迫Java和C处理这个问题”的目的是什么?如果您希望传递相同的内存位置,以便该方法可以修改参数并允许调用方查看修改后的值,那么可以在Java中实现这一点(我对C不太了解)。但是如果不是,那么为什么你希望编译器在幕后传递地址,为什么你在意呢?注意,通过地址传递<代码> int >代码>程序会慢一些,因为它需要间接访问值。剩下的部分呢?C++部分:-实际上,你通过值,如果直接传递对象,甚至用构造函数复制对象。考虑到这一点,只有在C#中相同才有意义——传递值应该是默认值,特别是对于原语,这是唯一有意义的事情。在C#中相同。除非参数标记为
ref
out
,否则它总是按值传递,在这种情况下,它是按引用传递的。这一点并不完全清楚。你先暗示这些是实现细节,然后再提到规范,它与实现细节无关…@OliCharlesworth No我是说他是在根据直觉推断规范涵盖的内容。如果我不清楚,请编辑或建议编辑。
int a=10;
MyClass mclass=new MyClass();

mclass.setA(a);
mclass.printA();
a++;
mclass.printA();
public void setA(final int a)
{
    a++; //error
    this.a=a;
}
 public void printA()
{
    a++; //ok
    System.out.println(a);
}