2014-10-02 73 views
0

对于传递给子方法的对象的修改或更多分配,我遇到问题。有一个Cost对象,它只有一些双变量来保存某些值。在调用方法中传递参数后,在调用方法中分配一个对象在调用方法中不起作用

public class Cost { 
    double insertCost = 0; 
    double deleteEleCost = 0; 

    private void addInsertCost(double cost) { 
     insertCost += checkCost(cost); 
    } 

    private void addDeleteCost(double cost) { 
     deleteEleCost += checkCost(cost); 
    } 

    public double getInsertCost() { 
     return insertCost; 
    } 

    public double getDeleteCost() { 
     return deleteEleCost; 
    } 

    public double getTotalCost() { 
     return insertCost + deleteEleCost; 
    } 
} 

在calcAverageCost()结束后,以下,费用成本的值始终为0,尽管在该方法calcAverageCost(),用于传递的成本对象中的值大于0(计算值)更大:

private Cost handleCase1(Content content1, Content content2, Cost cost) { 
    calcAverageCost(content1, content2, cost); 
    System.out.println("insert: " + cost.getInsertCost()); 
    System.out.println("delete: " + cost.getDeleteCost()); 
    return cost; 
} 

在calcAverageCost()方法getCost()基于两个Content对象计算成本。对于这个例子,这些并不重要,事实上,对于两个内容的每个方面而言,新的6个单独的Cost对象在将它们放入getCost()后,实际上都会为insertCost和deleteCost分别赋值一些值。

这6个较小的成本对象被合并为三个较大的成本对象。即使那些按预期持有价值。 作为最后一步,getMinCost()(请参阅最后)返回具有最小成本值的一个成本对象,并将其分配给新的成本对象finalCost。然后,将此对象分配给上面传递的成本对象(成本)。即使在这两个操作之后,修改后的双重变量也会很好地打印出最终成本以及成本成本。但是,当方法calcAverageCost()结束并且handleCase1()继续上面的方法时,传递的Cost成本在变量中仅包含0,就像calcAverageCost()中的变更期间没有发生任何变化。

根据我的理解,Java中应该有一个内部对象,它是getMinCost()方法的结果。通过给它分配finalCost,这个内部对象指向那个Cost对象。并且通过为成本成本做同样的事情,这个也应该指向那里。但不知何故,这种效应不会传递给原来的调用方法?我在这里有一个误解吗?我认为这就像Java的工作方式。

我记得在Stackoverflow上的一个气球线程,以及许多关于传递值和Java的其他线程。通常我会尝试只读线程,这是我第一次无法绕过问题,所以我专门提出问题...

我真的很感激任何帮助,并且对不起,如果这个问题是一个糟糕的问题。

private void calcAverageCost(Content content1, Content content2, Cost cost){ 
    Cost min_min = new Cost(); 
    Cost min_max = new Cost(); 
    Cost avg_min = new Cost(); 
    Cost avg_max = new Cost(); 
    Cost max_min = new Cost(); 
    Cost max_max = new Cost(); 

    getCost(content1, content2,min_min); 
    getCost(content1, content2,min_max); 
    getCost(content1, content2,avg_min); 
    getCost(content1, content2,avg_max); 
    getCost(content1, content2,max_min); 
    getCost(content1, content2,max_max); 

    System.out.println("step1"); 
    printCost(min_min); 
    printCost(min_max); 
    printCost(avg_min); 
    printCost(avg_max); 
    printCost(max_min); 
    printCost(max_max); 
    //These one prints out nicely 

    Cost s_min = new Cost(); 
    Cost s_avg = new Cost(); 
    Cost s_max = new Cost(); 

    s_min.addInsertCost((min_min.getInsertCost()+min_max.getInsertCost())/2d); 
    s_min.addDeleteCost((min_min.getDeleteCost()+min_max.getDeleteCost())/2d); 
    s_avg.addInsertCost((avg_min.getInsertCost()+avg_max.getInsertCost())/2d); 
    s_avg.addDeleteCost((avg_min.getDeleteCost()+avg_max.getDeleteCost())/2d); 
    s_max.addInsertCost((max_min.getInsertCost()+max_max.getInsertCost())/2d); 
    s_max.addDeleteCost((max_min.getDeleteCost()+max_max.getDeleteCost())/2d); 

    System.out.println("step2"); 
    printCost(s_min); 
    printCost(s_avg); 
    printCost(s_max); 
    //These one prints out nicely as well 

    Cost finalCost = getMinCost(getMinCost(s_min,s_avg),s_max); 
    printCost(finalCost); 
    //Also this one prints out nicely 
    cost = finalCost; 
    printCost(cost); 
    //Even this one prints out nicely 
} 

这里是getMinCost()方法,它只是比较两个成本对象,并返回一个具有更好的变量

private Cost getMinCost(Cost cost1, Cost cost2) { 
    Cost cost = cost1; 
    System.out.println("cost1:"+cost1.getTotalCost()); 
    System.out.println("cost2:"+cost2.getTotalCost()); 
    if (cost1.getTotalCost() < cost2.getTotalCost()) { 
     cost = cost1; 
     System.out.println("cost1smaller"); 
    } else if (cost1.getTotalCost() > cost2.getTotalCost()) { 
     cost = cost2; 
     System.out.println("cost2smaller"); 
    } else if (cost1.getTotalCost() == cost2.getTotalCost()) { 
     if (cost1.getDeleteCost() < cost2.getDeleteCost()) { 
      cost = cost1; 
      System.out.println("cost1delsmaller"); 
     } else if (cost1.getDeleteCost() > cost2.getDeleteCost()) { 
      cost = cost2; 
      System.out.println("cost2delsmaller"); 
     } else if (cost1.getDeleteCost() == cost2.getDeleteCost()) { 
      cost = cost1; 
      System.out.println("cost1deleq"); 
     } 
    } 
    System.out.println("cost:"+cost.getTotalCost()); 
    //shows correct result so far, the minimum cost 
    return cost; 
} 
+2

这是一个真正迂回的方式,询问Java是传递值还是传递引用。答案是:[Java是通过值传递](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value)。 – biziclop 2014-10-02 09:52:15

+0

@biziclop指的是什么,意味着生产线成本= finalCost;只会改变成本_inside_方法的参考,并不会影响调用上下文中的成本参考。因此,在handleCase1中调用calcAverageCost方法后,成本参考仍将指向同一对象,并且finalCost中存在的更改将不会反映出来。 – 2014-10-02 10:07:05

+0

谢谢你们两位。所以参数成本参考也只是原始成本参考的一种“复制”。我想这就是“引用也是按值传递”的含义。我原本以为我理解这个概念,但似乎并非如此。我终生学到了一些东西,再次感谢。 – Soulbrandt 2014-10-02 10:33:17

回答

1

如果你想模仿“按引用传递”的行为,为了修改的投入成本,使用支架可变对象:

public class Holder<T> { 
    private T value; 
    public void setValue(T value) {this.value = value;} 
    public T getValue() {return this.value;} 
} 

而且有:

private void calcAverageCost(Content content1, Content content2, Holder<Cost> holder) { 
    ... 
    holder.setValue(finalCost); 
} 

或者,由于只有一个参数发生变化:

private Cost calcAverageCost(Content content1, Content content2, final Cost cost) { 
    ... 
    return finalCost; 
} 

和使用中调用代码返回值。这会更好(你应该避免改变方法的参数)。

+0

啊......我现在觉得很愚蠢。所以,我唯一需要做的就是e。 G。 cost.addInsertCost(finalCost.getInsertCost())而不是分配它。但持有人可能是更好的解决方案,非常感谢。 我可以问为什么它是不好的参数变异?你是指从最佳做法还是从技术角度来看? – Soulbrandt 2014-10-02 10:13:20

+0

从技术角度而言,它来自最佳实践。我猜你在这里粘贴的代码是一个代表企业而不是框架的代码:在这种情况下(商业),你应该保持简单明了,以实现更好的可维护性。请注意,在Scala中,我们鼓励不变性,并且我认为最好在Java中尽可能地实现它:不可变对象是_normally_线程安全的。 – NoDataFound 2014-10-02 15:01:52