在 Java 中使用复制/复制传出 [duplicate]

Using copy-in / copy-out passing in Java [duplicate]

提问人:Chelsea 提问时间:1/31/2023 最后编辑:Chelsea 更新时间:2/1/2023 访问量:89

问:

这个问题在这里已经有答案了:
10个月前关闭。

这篇文章是在 10 个月前编辑并提交审核的,但未能重新打开帖子:

原始关闭原因未解决

我正在努力完全理解 Java 中的复制/复制传递。我不是在问 Java 是按值传递还是按引用传递,我只是在这种情况下难以理解它。

我需要更新 main 方法中的浮点数(f1、f2 和 f3),使用 adjustDistance() 方法调整距离。这是家庭作业测验,所以我可以/不能改变的东西是有限的。寻找一些关于我需要做什么以及为什么的信息。

这是代码:

public class Flow {
public static String formatF1F2F3(float f1, float f2, float f3)
{
    return
      "f1 = " + f1 + ", f2 = " + f2 + ", f3 = " + f3;
}

//      The new record type is needed to
//      so that the two results
//      of adjustDistance can be returned together.
//
//      adjustDistance is a method inside this
//      class so that parameter passing is simpler
private static class TwoFlows
{
    public float flow1;
    public float flow2;

    public TwoFlows(float flow1, float flow2)
    {
        this.flow1 = flow1;
        this.flow2 = flow2;
    }

    public void adjustDistance()
    {
        if ( Math.abs(flow1 - flow2) < 10 )
        {
            if(flow1 > flow2)
            {
                flow2 = flow2 / 3;
                flow1 = flow1 + flow2;
                flow1 = flow1 + flow2;
            }
            else
            {
                flow1 = flow1 / 3;
                flow2 = flow2 + flow1;
                flow2 = flow2 + flow1;
            }
        }
    }
}

public static void main(String[] args)
{
    float f1, f2, f3;
    f1 = 3; f2 = 3; f3 = 4;
    
    System.out.println(formatF1F2F3(f1,f2,f3));

    //    TASK:
    //    Write code that it simulates *copy-in copy-out* passing
    //    of formal parameters flow1 and flow2 to method adjustDistance.
    //    only alter code below this comment

    // my attempt:

    TwoFlows twoFa = new TwoFlows(f2, f3);
    twoFa.adjustDistance();
    System.out.println(formatF1F2F3(f1,f2,f3));
    TwoFlows twoFb = new TwoFlows(f1,f2);
    twoFb.adjustDistance();
    System.out.println(formatF1F2F3(f1,f2,f3));
    TwoFlows twoFc = new TwoFlows(f3,f3);
    twoFc.adjustDistance();
    System.out.println(formatF1F2F3(f1,f2,f3));
} }

输出:

f1 = 3.0,f2 = 3.0,f3 = 4.0

f1 = 3.0,f2 = 3.0,f3 = 4.0

f1 = 3.0,f2 = 3.0,f3 = 4.0

f1 = 3.0,f2 = 3.0,f3 = 4.0

如果我每次都不初始化新的 TwoFlows(),我会收到一个错误。我不认为 flow1 和 flow2 会像我所期望的那样更新。

我相信预期的产出是:

f1 = 3.00,f2 = 3.00,f3 = 4.00

f1 = 3.00,f2 = 1.00,f3 = 6.00

f1 = 3.67,f2 = 0.33,f3 = 6.00

f1 = 3.67,f2 = 0.33,f3 = 10.00

java 参数传递

评论

0赞 undefined symbol 1/31/2023
“adjustDistance”方法更新 TwoFlows 对象的成员变量。它对 main() 的同名局部变量没有影响。这是你所期望的吗?
0赞 Chelsea 1/31/2023
是的,我想我明白这一点。main() 方法是使用 TwoFlows() 和 adjustDistance() 方法更改 f1、f2 和 f3 变量值。我正在尝试将它们传递到 TwoFlows 中,然后调整距离以更新值。
0赞 Maurice Perry 1/31/2023
停留的字段。要打印结果,请执行如下操作:,等等...TwoFlowsTwoFlowsSystem.out.println(formatF1F2F3(f1,twoFa.flow1,twoFa.flow2));
0赞 undefined symbol 2/1/2023
是的,我想我明白这一点。让我改写一下 - 您在初始化时设置了 main 的 f1,f2,f3 一次,并且没有代码可以更改它们的值,因此每次使用 formatf1f2f3 处理这些相同的值时,您必须并且将得到相同的结果。

答:

0赞 Thomas 1/31/2023 #1

我正在努力完全理解 Java 中的复制/复制传递。

我不知道“复制”和“复制”这两个术语,但我认为它们指的是“按价值传递”。这基本上意味着参数或返回类型的值被复制,即如果您稍后更改变量,则不会反映在另一端。

请考虑以下几点:

int someMethod(int param) { 
  try {
        param++;
        return param;
    } finally {
        param--;
        param--;
    }
}

void test() {
  int a = 2; 
  int b = someMethod(a);
}

这是一份副本,这意味着增量只影响而不影响。返回时,该值将复制到 ,因此递减仅应用于 。这意味着值为 3,而将保持其值 2,即使先递增到 3 并在定义返回值后递减到 1。- 在您的示例中,这意味着 的值被复制到 ,但变量本身永远不会改变。paramaparamaparambparambaparamf1f2f3TwoFlows(...)

请注意,如果变量和参数是对象引用,则复制的值是引用(将它们视为对象的地址),而不是对象本身。

因此,让我们更改要使用的示例,让我们更改对象的值:AtomicInteger

AtomicInteger someMethod(AtomicInteger param) {
    try {
        param.incrementAndGet();
        return param;
    } finally {
        //decrement twice after "copying" the return value
        param.decrementAndGet();
        param.decrementAndGet();
    }
}

void test() {
  AtomicInteger a = new AtomicInteger(2);
  AtomicInteger b = someMethod(a);
}

现在将是参考文献的副本,并且将是参考文献的副本。最后,所有 3 个引用都“指向”同一个实例。因此,递增和递减操作都会影响它们,这意味着它们都返回相同的值 - 1。paramabparamAtomicInteger

那么我该如何修复我的代码呢?

要修复你的代码,你需要得到 和 的值,例如,像这样:flow1flow2

TwoFlows twoFa = new TwoFlows(f2, f3);
twoFa.adjustDistance();
System.out.println(formatF1F2F3(f1,twoFa.flow1,twoFa.flow2));
0赞 Evangelos Englezakis 1/31/2023 #2

浮点变量是原始的 Java 类型,因此当您在方法或构造函数中传递它们时,它们是按值传递的,而不是按引用传递的。这意味着,无论静态类和方法中的变量 f1、f2、f3 发生什么变化,它们都只在该类中“可见”。当您尝试在 main 方法中打印值时,您只是打印未更改的原始浮点值。 如果您想打印更改后的值,我建议如下:adjustDistance()

System.out.println(formatF1F2F3(f1,f2,f3));
System.out.println(formatF1F2F3(f1,twoFa.flow1,twoFa.flow2));
System.out.println(formatF1F2F3(twoFb.flow1,twoFb.flow2,f3));     
System.out.println(formatF1F2F3(f1,twoFc.flow1,twoFc.flow2));