Java参数传递问题

发布于 2024-08-17 08:35:36 字数 1286 浏览 4 评论 0原文

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

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

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

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

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

以下是我的调用方式。

    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());
}

这是 MyInteger 类型。

class MyInteger {
private int n;

MyInteger(int i){
    n = i;
}

public void increment(){
    n++;
}

public int value(){
    return n;
}

现在,如果您想知道为什么我使用自己的整数类型,这就是我的问题所涉及的。我尝试使用 Java Integer 类型来实现此目的,但我无法让它工作,打印的答案始终是 O,“Integer”的值在多次调用中不会持续存在。这就是我的做法,

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

如何解释这种行为?

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

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.

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.

    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')

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.

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,

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

What explains this behavior?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

稀香 2024-08-24 08:35:36

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

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

您的自制类起作用的原因是您现在正在更改对象的内部内容,而不仅仅是对其的引用。函数内部和外部都存在相同的对象,因此当您在内部更改它时,外部确实会看到更改。

The first problem is that type Integer is 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).

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.

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.

玩世 2024-08-24 08:35:36

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

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

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

First off, Java's Integer class 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.

When you assign the (unboxed and reboxed) incremented value to arg, arg is 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.

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.

逆夏时光 2024-08-24 08:35:36

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

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

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

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 swap function. Not possible, right? Updating the local pointers would have no effect on the pointers that were passed to the function.

街道布景 2024-08-24 08:35:36

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

当您编写时:

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

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

如果您了解 C++,这与带有 int* 或 int*& 的函数中的区别相同。作为参数:在 Java 中,它就像 int* (对于对象)。

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.

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)).

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).

北恋 2024-08-24 08:35:36

最后代码部分的问题是 arg 变量仅保存对 Integer 类的引用。当您将 arg 设置为某个内容时,其值会在本地上下文中替换为新对象,并且不会更新已存在的对象。您必须指定要更新的参考的完整路径。

The problem with the last code portion is that the arg variable just holds a reference to an Integer class. When you set arg to 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文