java Java参数传递问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2039190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:04:57  来源:igfitidea点击:

Java parameter passing question

javaintegerparameters

提问by fsm

I am relatively new to Java and while trying out some code came across something that surprised me. Hopefully some one can shed some light on this. Here's some code snippets relevant to my question. Those who've read the practice of programming might find this familiar.

我对 Java 比较陌生,在尝试一些代码时遇到了一些让我感到惊讶的事情。希望有人可以对此有所了解。这是与我的问题相关的一些代码片段。那些阅读过编程实践的人可能会觉得这很熟悉。

This function is defined for the List datatype, and applies the passed "fn" argument (which is nothing but a function wrapped in an object) to all members of the list.

这个函数是为 List 数据类型定义的,并将传递的“fn”参数(它只不过是一个包装在对象中的函数)应用于列表的所有成员。

    public void apply(MapFunctionI fn, Object fnArg) {
    Node curr = head;
    for (; curr != null; curr = curr.getNext()){
        fn.function(curr.getItem(), fnArg);
    }
}

Next, I try to use this function to count the number of elements in a list using a class that implements MapFunctionI (an interface that requires a method called 'function')

接下来,我尝试使用这个函数来计算列表中元素的数量,使用一个实现 MapFunctionI 的类(一个需要一个名为“函数”的方法的接口)

class CounterFunction implements MapFunctionI {
public void function(Object node, Object arg){
    ((MyInteger)arg).increment();
}
}

Here's how I call this.

这就是我如何称呼它的。

    static void TestApply(LinkedList l){
    System.out.println("Number of elements in List -> ");
    MyInteger n = new MyInteger(0);
    l.apply(new CounterFunction(),n);
    System.out.println(n.value());
}

And here's the MyInteger type.

这是 MyInteger 类型。

class MyInteger {
private int n;

MyInteger(int i){
    n = i;
}

public void increment(){
    n++;
}

public int value(){
    return n;
}

Now, if you're wondering why I am using my own Integer type, that's what my question is related to. I tried using the Java Integer type for this, but I could not get it to work, the answer printed was always O, the value of the "Integer" did not persist across multiple invocations. Here's how I was doing it,

现在,如果您想知道为什么我使用我自己的 Integer 类型,这就是我的问题。我尝试为此使用 Java Integer 类型,但我无法让它工作,打印的答案总是 O,“Integer”的值在多次调用中没有持续存在。这是我的做法,

arg = ((Integer)arg).intValue() + 1;

What explains this behavior?

什么解释了这种行为?

And I am sure there is a more succinct way of posing this question :-)

我相信有一种更简洁的方式来提出这个问题:-)

回答by Carl Smotricz

The first problem is that type Integeris immutable; once created with a certain integer value, that value cannot be changed. So you can't directly change an Integer (I'm not saying you didn't know this or tried to).

第一个问题是类型Integer是不可变的;一旦使用某个整数值创建,该值就无法更改。所以你不能直接改变一个整数(我不是说你不知道或试图知道)。

The next problem is that what gets passed to the function is a reference to that Integer. You can, inside the function, change that reference to point to a different-valued Integer, but the changed reference from inside the function is never passed back out to the calling function, so its value isn't relevant there.

下一个问题是传递给函数的是对该整数的引用。您可以在函数内部将该引用更改为指向不同值的 Integer,但是从函数内部更改的引用永远不会传回给调用函数,因此它的值在那里不相关。

The reason why your home-built class works is that you are now changing the internal contents of your object and not just a reference to it. The very same object exists inside and outside your function, so when you change it inside, the change is indeed seen outside.

您自制的类之所以有效,是因为您现在正在更改对象的内部内容,而不仅仅是对它的引用。完全相同的对象存在于您的函数内部和外部,因此当您在内部更改它时,确实可以在外部看到更改。

回答by Ben Zotto

First off, Java's Integerclass is immutable; it only ever represents a single integer value. When you call intValue()on it, that's simply returning the current (immutable) value of the integer.

首先,Java 的Integer类是不可变的;它只代表一个整数值。当您调用intValue()它时,它只是返回整数的当前(不可变)值。

When you assign the (unboxed and reboxed) incremented value to arg, argis just a local reference to what got passed in (just like a pointer value inside a function in C, say). Setting to something and then returning from the function loses the new value you just gave it.

当您将(未装箱和重新装箱)递增的值分配给 时argarg它只是对传入内容的本地引用(就像 C 中函数内的指针值,比如说)。设置为某物然后从函数返回会丢失您刚刚给它的新值。

If you were in C/C++, this is where you'd use a pointer-to-a-pointer. But Java doesn't have an equivalent construct, so you're on your own in dealing with it-- a wrapper object like you've used is a reasonable solution to your problem.

如果您使用的是 C/C++,那么您将在此处使用指向指针的指针。但是 Java 没有等效的构造,因此您需要自己处理它——像您使用的这样的包装器对象是解决问题的合理解决方案。

回答by danben

The reason it didn't work when you used the Integertype is because you were updating the local copy of the argpointer inside function(). In Java, all non-primitives are "reference types", and all function arguments are passed by value.

当您使用该Integer类型时它不起作用的原因是因为您正在更新arg内部指针的本地副本function()。在 Java 中,所有非原语都是“引用类型”,所有函数参数都是按值传递的。

Edit- in case that last statement is confusing, imagine if you were working with a dialect of C++ that only allowed you to pass references by value (ie you could only pass copies of pointers), and you wanted to implement the swapfunction. Not possible, right? Updating the local pointers would have no effect on the pointers that were passed to the function.

编辑- 如果最后一条语句令人困惑,请想象一下,如果您正在使用只允许按值传递引用的 C++ 方言(即,您只能传递指针的副本),并且您想要实现该swap函数。不可能吧?更新本地指针不会影响传递给函数的指针。

回答by Andrea Zilio

This happens because in Java parameter passing is BY VALUE. NOTE that when you pass an object to a function you pass BY VALUE its reference... Or, said in another way, you pass its address by value.

发生这种情况是因为在 Java 中参数传递是按值传递的。请注意,当您将对象传递给函数时,您将按值传递其引用……或者,换句话说,您是按值传递其地址。

When you write:

当你写:

arg = .... // a new Integer Object

you change the value of the arg reference locally in the function (to point to the new object), while the reference saved in the fnArg variable in the List.apply function is still the same (and so pointing to the same Integer(0)).

您在函数中本地更改 arg 引用的值(以指向新对象),而 List.apply 函数中保存在 fnArg 变量中的引用仍然相同(因此指向同一个 Integer(0) )。

If you know C++ it's the same difference you have in a function with a int* or an int*& as a parameter: in Java it's like having int* (for objects).

如果您了解 C++,那么它与使用 int* 或 int*& 作为参数的函数的区别是一样的:在 Java 中,它就像使用 int*(用于对象)。

回答by amphetamachine

The problem with the last code portion is that the argvariable just holds a reference to an Integerclass. When you set argto something, its value gets replaces in the local context with a new object, and does not update the object that already exists. You have to specify the full path to the reference you're updating.

最后一段代码的问题在于arg变量只保存了对Integer类的引用。当你设置arg为某物时,它的值在本地上下文中被一个新对象替换,并且不会更新已经存在的对象。您必须指定要更新的参考的完整路径。