[英]performance impact of deep copy
我有一個保存在內存中的復雜對象,不應修改。 它用作模板,在其中首次初始化對象時初始化一些字段,並根據某些調用代碼參數在運行時確定和更新一些字段。
考慮以下示例:
FooTemplate是一個加載到內存中的對象。 調用代碼需要此對象的更新版本。 更新后的版本具有填充的服務中心列表。 列表的內容取決於客戶端代碼中的某些參數,在這種情況下為呼叫者所在的國家。
public class FooTemplate {
private final String companyName;
private final String identifier;
private final List<String> serviceCenters = new ArrayList<String>();
public FooTemplate(String companyName, String identifier) {
this.companyName = companyName;
this.identifier = identifier;
}
public String getCompanyName() {
return companyName;
}
public String getIdentifier() {
return identifier;
}
public List<String> getServiceCenters() {
return serviceCenters;
}
@Override
public String toString() {
return "FooTemplate [companyName=" + companyName + ", identifier="
+ identifier + ", serviceCenters=" + serviceCenters + "]";
}
}
FooManager是一個加載FooTemplate對象的單例:
public class FooManager {
private static final FooManager fooManager = new FooManager();
private FooTemplate fooTemplate;
private FooManager() {
this.fooTemplate = new FooTemplate("ABC inc.", "93746789");
}
public static FooManager getInstance() {
return fooManager;
}
public FooTemplate getFoo() {
return fooTemplate;
}
}
這是測試類:
class Test {
public static void main(String[] args) {
Caller[] callers = {new Caller (CountryCode.US),
new Caller (CountryCode.US),
new Caller (CountryCode.US)};
for (int i = 0; i < callers.length; i++){
System.out.println(getFoo(callers[i]));
}
}
public static FooTemplate getFoo(Caller caller) {
FooManager fooManager = FooManager.getInstance();
FooTemplate fooTemplate = fooManager.getFoo();
if (caller.getCountryCode() == CountryCode.US){
fooTemplate.getServiceCenters().add("Seattle");
fooTemplate.getServiceCenters().add("Boston");
}
if (caller.getCountryCode() == CountryCode.GER){
fooTemplate.getServiceCenters().add("Munich");
fooTemplate.getServiceCenters().add("Berlin");
}
if (caller.getCountryCode() == CountryCode.FRA){
fooTemplate.getServiceCenters().add("Paris");
fooTemplate.getServiceCenters().add("Lyon");
}
return fooTemplate;
}
}
它產生以下輸出:
FooTemplate [companyName = ABC inc。,標識符= 93746789,serviceCenters = [西雅圖,波士頓]]
FooTemplate [companyName = ABC inc。,標識符= 93746789,serviceCenters = [西雅圖,波士頓,西雅圖,波士頓]]
FooTemplate [companyName = ABC inc。,標識符= 93746789,serviceCenters = [西雅圖,波士頓,西雅圖,波士頓,西雅圖,波士頓]]
我知道發生這種情況是因為同一對象在每次迭代中都會被修改。 在修改對象並返回副本之前,是否需要對對象進行深層復制,還是有更好的解決方案?
編輯:在實際的代碼中,模板對象是通過解析xml創建的,僅在單例中解析一次。 這就是為什么我不能在每次需要時都創建一個新的模板對象。
您可以在每次調用getFoo
時創建一個新的FooTemplate
實例。
public static FooTemplate getFoo() {
return new FooTemplate("ABC inc.", "93746789");
}
或者,如果您不想創建太多companyName
和identifier
,請考慮調用String.intern()
。 (我認為編譯器仍然會優化內存分配。)
如果兩個字符串在整個程序中都是常量,請考慮將它們聲明為static final
。
通常,從另一個對象復制對象不是一個好習慣,而您可以從頭開始創建它們。
編輯:只需創建一個新類FooCompany
。
public class FooCompany {
private final String companyName;
private final String identifier;
public FooCompany(String companyName, String identifier) {
this.companyName = companyName;
this.identifier = identifier;
}
public String getCompanyName() {
return companyName;
}
public String getIdentifier() {
return identifier;
}
}
public class FooManager {
private static final FooManager fooManager = new FooManager();
private FooCompany fooCompany;
private FooManager() {
this.fooCompany = new FooCompany("ABC inc.", "93746789");
}
public static FooManager getInstance() {
return fooManager;
}
public FooTemplate getFoo() {
return new FooTemplate(fooCompany.getCompanyName(), fooCompany.getIdentifier());
}
}
//您可以使用以下代碼替換FooManger
公共類FooManager {
private static final FooManager fooManager = new FooManager();
//if company and contact are fix, make them final
private final String COMPANY="ABC inc.";
private final String CONTACT="93746789";
private FooManager() {
}
public static FooManager getInstance() {
return fooManager;
}
public FooTemplate getFoo() {
return new FooTemplate(COMPANY, CONTACT);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.