【问题标题】:Java pass by reference and compiler optimizationJava 通过引用传递和编译器优化
【发布时间】:2012-09-23 18:51:59
【问题描述】:

在函数fermatFactorization()ab 中作为参考参数传递,因为我使用的是Long 类。但是,在函数testFermatFactorization() 中,当我将ab 传递给fermatFactorization() 时,ab 的值不会改变,所以testFermatFactorization() 打印(0)(0)。我通过在fermatFactorization() 中打印出ab 进行了测试,得到了我期望的输出。

我忽略了什么?编译器能否更改fermatFactorization() 中的ab,因为它们只是被分配给?(怀疑)

public static void fermatFactorization(Long n, Long a, Long b)   
//PRE:  n is the integer to be factored
//POST: a and b will be the factors of n
{
    Long v = 1L;
    Long x = ((Double)Math.ceil(Math.sqrt(n))).longValue();
    //System.out.println("x: " + x);
    Long u = 2*x + 1;
    Long r = x*x - n;

    while(r != 0)                 //we are looking for the condition x^2 - y^2 - n to be zero
    {
        while(r>0)
        {
            r = r - v;            //update our condition
            v = v + 2;            //v keeps track of (y+1)^2 - y^2 = 2y+1, increase the "y"
        }
        while(r<0)
        {
            r = r + u;
            u = u + 2;            //keeps track of (x+1)^2 - x^2 = 2x+1, increases the "x"
        }
    }

    a = (u + v - 2)/2;            //remember what u and v equal; --> (2x+1 + 2y+1 - 2)/2 = x+y
    b = (u - v)/2;                //                             --> (2x+1 -(2y+1))/2 = x-y
}

public static void testFermatFactorization(Long number)
{
    Long a = 0L;
    Long b = 0L;
    fermatFactorization(number, a, b);
    System.out.printf("Fermat Factorization(%d) = (%d)(%d)\n", number, a, b);
}

【问题讨论】:

  • 查看这个关于变异包装类的问题:stackoverflow.com/questions/4117793/…
  • 看看我的回答here。它实际上不是通过引用,而是通过引用的,因此您实际上无法像更改指针那样更改原始引用。
  • 如果性能很重要,你应该使用long而不是Long 并且尽可能使用double而不是Double

标签: java function reference parameter-passing


【解决方案1】:

Java 是按值传递的。如果为参数分配一个新值,它不会影响调用者方法中的值。

你有两个选择:

  • 让您的方法返回 ab - 在 int[] 中或使用具有两个字段的单独 FactorizationRezult 类。这样,您将在被调用方法中将 ab 声明为局部变量,而不是将它们作为参数。这是最可取的方法。

  • 另一种方法是使用MutableLongsetValue(..) 方法 - 这样更改将影响调用方方法中的对象。这是不太可取的

【讨论】:

  • 我真的很喜欢 Java,但我从来不知道这个……真可惜
【解决方案2】:

a 和 b 是引用,而不是“引用参数”,它们是按值传递的。被调用方法中的值发生了变化,但对调用者没有影响。

Java 中没有“按引用传递”。

【讨论】:

    【解决方案3】:

    在 Java 中,一切都是按值传递的。没有引用调用。即使你传递一个对象,它的引用也是按值传递的。因此,当您传递 Long 对象时,您只是通过值传递对它的引用。

    Long,就像其他原始类型包装器一样,是“不可变的”。您无法更改其内部的 long 值。因此,如果您不想更改设计,则必须自己制作一个可变包装器(或使用MutableLong)并将其传递下去。如果您问我,更改您的设计以返回结果而不是更改方法参数是一种更好的方法。

    【讨论】:

      【解决方案4】:

      使用 = 运算符清除内存中存储局部变量的位置并替换它。这将不会影响原始变量。按值传递仅允许您修改对象中的数据(如修改其中的字段),而不是实际引用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-26
        • 2011-08-24
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        • 2017-11-11
        • 1970-01-01
        相关资源
        最近更新 更多