gpt4 book ai didi

java - 更改 void 方法中的值或返回新对象,哪一种是正确的方法?

转载 作者:行者123 更新时间:2023-11-30 01:47:47 27 4
gpt4 key购买 nike

当您需要修改 map /列表或对象时,您更喜欢哪一种,哪一种是更好的方法?,我的意思是从以下角度来看;

  • 维护
    • 处理 void 方法或新对象创建时遇到维护困难吗?
  • 成本
    • 是的,新的对象创建仍在函数范围内,并且可供 GC 使用,但想知道它如何影响应用程序如果我们在整个项目中这样做,可能会很高兴听到一些有经验的人的意见
  • 可测试性
    • 使用 void 方法很难测试,而不是在调用方法中测试,但很高兴听到有关 void 与 new 的想法
  • 稳健性
    • 使用新方法似乎可以避免副作用并且更加稳健。你有什么想法?

假设我有一个从该方法返回的 map ;

public Map<Integer, User> getUsers() {
Map<Integer, User> names = getNames();
return names;
}

所以在同一个函数中,我需要给它们添加前缀;

public Map<Integer, User> getUsers() {
Map<Integer, User> names = getNames();
addPrefixes(names);
return names;
}

从不变性的角度来看,哪一个更好?我应该使用这种方式吗?

public Map<Integer, User> getUsers() {
Map<Integer, User> names = getNames();
Map<Integer, User> prefixedNames = getPrefixed(names);
return prefixedNames;
}

如果是这样,如何实现 getPrefixed 函数,深复制每个 User 并将其添加到新的 Map 中并返回,您能举个例子吗?

最佳答案

让我们看一下代码:

public Map<Integer, User> getUsers() {
Map<Integer, User> names = getNames();
// addPrefixes or names=getPrefixes
return names;
}

getNames 是来自同一类 getUsers 的方法。如果 getNames 是公共(public)的,则它不应公开该类的内部字段。我的意思是,如果你有类似的东西:

public Map<Integer, User>() getNames() { return this.names; }

是时候制作副本了,因为对象的状态可能会被任何用户破坏。但即使 getNames 是私有(private)字段并返回内部字段,如果有人调用 getUsers (一次、两次……)会发生什么?前缀将添加到内部字段。

因此,我假设 getNames 返回名称的副本(例如从数据库检索)。局部变量 names 是您的,并且是名称的工作副本。

现在,您有三个选择:

void addPrefixes(Map<Integer, User> names) { // 1
// update names
}

Map<Integer, User> getPrefixed(Map<Integer, User> names) { // 2
// update names
return names;
}

Map<Integer, User> getPrefixed(Map<Integer, User> names) { // 3
// create copy, e.g. use Java8 stream;
return namesCopy;
}

选项 1 和 2 基本相同(这是签名问题),而选项 3 是进行复制的功能版本。

维护

我认为选项 2 和 3 更容易阅读:给出输入并获得输出。选项 1 更难理解:addPrefixes 是什么?对于名称还是对象本身?是否还有其他副作用(现在或以后,在改进版本中)?

此外,如果添加前缀的过程变得更加复杂,您可以轻松替换:

return getPrefixed(names);

作者:

return prefixer.getPrefixed(names);

成本

如果该函数是应用程序的瓶颈,您可以从选项 3(更安全)开始,然后切换到选项 2(带注释)。选项 1 和 2 的成本相同。

可测试性

如果您需要测试前缀是否正确添加,请将 getPrefixed 设为小型 Prefixer 类的公共(public)方法(单一职责原则)。

稳健性

选项 3 是最好的。如果将 getNames 修改为返回内部字段,会发生什么情况。示例:

// before
public Map<Integer, User>() getNames() {
// query the db
// create the map
return names;
}

// after: the method was to slow, cache the result
public Map<Integer, User>() getNames() {
if (this.names == null) {
// query the db
// create the map
}
return this.names;
}

选项 1 和 2 将损坏字段names

重要提示:无论您决定如何,请记录您的选择:修改参数时,您应该让用户知道,因为最初的期望(在 Java 中)是参数不会被修改。如果函数返回副本,请让用户知道。

关于java - 更改 void 方法中的值或返回新对象,哪一种是正确的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57323420/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com