简体   繁体   English

避免在Java中传递引用的方法

[英]Ways to avoid passing-by-reference in Java

This question is probably as old as the hills. 这个问题可能和山丘一样古老。 Nevertheless, after reading lots of articles and forums I still don't see a good solution to my problem. 然而,在阅读了大量文章和论坛之后,我仍然看不到解决问题的好方法。

I have to transfer some Monte Carlo simulation programs from C++ to Java. 我必须将一些蒙特卡罗模拟程序从C ++转移到Java。 The problem is that it heavily relies on passing variables by reference in functions, like: 问题是它严重依赖于在函数中通过引用传递变量,例如:

void make_step(int &a, int &b, double &c) {
   a++;
   b += a;
   c *= 1.1;
}

There is no passing by reference in Java, as well as possible analogs, like multiple return values or nested functions. Java中没有通过引用传递,也没有可能的类似物,如多个返回值或嵌套函数。 Solutions, which I have read on this site, usually involve encapsulation of primitive types into objects. 我在本网站上阅读的解决方案通常涉及将原始类型封装到对象中。 Alternatively - break functions to single-return ones. 或者 - 将函数分解为单返回函数。 However, in my case it results in too long and complicated code (few lines of C++ code grow to almost pages in Java). 但是,在我的情况下,它导致代码太长而且复杂(几行C ++代码几乎增长到Java中的页面)。 Also, since these algorithms are hard to debug, I want to avoid dramatical changes in code while porting. 此外,由于这些算法很难调试,我希望在移植时避免代码的剧烈变化。

What I do now is substituting of all primitive type variables with arrays of length 1 (which are objects and can be modified inside functions). 我现在所做的是用长度为1的数组替换所有原始类型变量(它们是对象,可以在函数内部进行修改)。 But it doesn't look like very elegant solutions. 但它看起来不是非常优雅的解决方案。 Does anyone have better ideas? 有没有人有更好的想法?

If you want the parameters to be "in-out" variables, they have to be object references. 如果您希望参数为“in-out”变量,则它们必须是对象引用。

With Mutable Wrappers 使用Mutable Wrappers

You can use mutable wrappers but this will require you to slightly modify your existing code (the algorithm): 您可以使用可变包装器,但这需要您稍微修改现有代码(算法):

class Int {
    int v;
}

class MDouble {
    double v;
}

void make_step(Int a, Int b, MDouble c) {
    a.v++;
    b.v += a.v;
    c.v *= 1.1;
}

With Local Variable Copies 使用本地变量副本

If you want to keep your original code, you can create local variable copies of the wrapped parameters, and you can use those without having to modify your code. 如果要保留原始代码,可以创建包装参数的局部变量副本,并且可以使用这些副本而无需修改代码。

At the end of your method (before return ) copy back the local variables into the wrappers and you're done. 在方法结束时( return之前)将局部变量复制回包装器中,然后就完成了。 A tip for this is to use a try-finally block so your local variables will get copied back into the wrappers no matter how or where your method returns: 这样做的一个提示是使用try-finally块,这样无论方法返回的方式和位置如何,都会将局部变量复制回包装器:

void make_step(int[] aa, int[] bb, double[] cc) {
    int a = aa[0];
    int b = bb[0];
    double c = cc[0];

    try {
        // all your original code comes here
        a++;
        b += a;
        c *= 1.1;
    } finally {
        aa[0] = a;
        bb[0] = b;
        cc[0] = c;
    }
}

There are mutable Integer and Decimal classes out there you can use those to pass by reference. 有可变的Integer和Decimal类,你可以使用它们通过引用传递。 Check out Apache Commons libraries here 在这里查看Apache Commons库

There are few options: 选项很少:

  • Wrap all parameters in an object. 包装对象中的所有参数。 The simple version indeed makes the program longer, but if you can wrap the entire algorithm in an object then those parameters become the object members. 简单版本确实使程序更长,但如果您可以将整个算法包装在一个对象中,那么这些参数将成为对象成员。
  • Use mutable integers (objects) - either Java's AtomicInteger which has get()/set() methods, or the commnos-lang version 使用可变整数(对象) - 具有get()/ set()方法的Java的AtomicInteger,或者commnos-lang版本

从c ++到java编写相同的逻辑时更多关于.equals和比较器==> <用于比较使用成员变量和局部变量将更新的对象返回到被调用的方法以获取更改。

You can use "atomic references" to wrap your object in a reference. 您可以使用“原子引用”将对象包装在引用中。

There are atomicXXX classes for most basic types as well. 大多数基本类型都有atomicXXX类。 These will work similarly to normal references aside from the overhead of creating them in the first place. 除了首先创建它们的开销之外,它们的工作方式与普通引用类似。

Arrays of length 1 are just as a solution, but if you dislike the syntax or appearance of them, this is the only other solution that I know of that can mimic the same behavior without a general refactor. 长度为1的数组只是一个解决方案,但如果您不喜欢它们的语法或外观,这是我所知道的唯一可以在没有通用重构的情况下模仿相同行为的其他解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM