提问人:Chelsea 提问时间:1/31/2023 最后编辑:Chelsea 更新时间:2/1/2023 访问量:89
在 Java 中使用复制/复制传出 [duplicate]
Using copy-in / copy-out passing in Java [duplicate]
问:
我正在努力完全理解 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 中的复制/复制传递。
我不知道“复制”和“复制”这两个术语,但我认为它们指的是“按价值传递”。这基本上意味着参数或返回类型的值被复制,即如果您稍后更改变量,则不会反映在另一端。
请考虑以下几点:
int someMethod(int param) {
try {
param++;
return param;
} finally {
param--;
param--;
}
}
void test() {
int a = 2;
int b = someMethod(a);
}
这是一份副本,这意味着增量只影响而不影响。返回时,该值将复制到 ,因此递减仅应用于 。这意味着值为 3,而将保持其值 2,即使先递增到 3 并在定义返回值后递减到 1。- 在您的示例中,这意味着 的值被复制到 ,但变量本身永远不会改变。param
a
param
a
param
b
param
b
a
param
f1
f2
f3
TwoFlows(...)
请注意,如果变量和参数是对象引用,则复制的值是引用(将它们视为对象的地址),而不是对象本身。
因此,让我们更改要使用的示例,让我们更改对象的值: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。param
a
b
param
AtomicInteger
那么我该如何修复我的代码呢?
要修复你的代码,你需要得到 和 的值,例如,像这样:flow1
flow2
TwoFlows twoFa = new TwoFlows(f2, f3);
twoFa.adjustDistance();
System.out.println(formatF1F2F3(f1,twoFa.flow1,twoFa.flow2));
浮点变量是原始的 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));
评论
TwoFlows
TwoFlows
System.out.println(formatF1F2F3(f1,twoFa.flow1,twoFa.flow2));