2014-10-02 70 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