【问题标题】:Best way to return a String as a parameter in Java在Java中将字符串作为参数返回的最佳方法
【发布时间】:2016-09-19 20:02:17
【问题描述】:

我经常遇到这样一种情况,我想从 Java 方法返回多个值,而仅仅为此目的创建一个类/对象是不值得的。在我当前的具体情况下,我有许多输入验证方法来计算我想在调用者中重复使用的中间结果。

一种解决方案是传入一个新列表并让该方法附加我的结果,但是当我知道我想要返回的每个参数总是有一个值时,这是一种误导。

最常见的这种情况是当我想返回一个字符串时。我可以传入 StringBuilder 或 StringBuffer,并让方法填充值。但是由于一些奇怪的原因,这些类没有提供 set() 方法(除了构造函数,这对这个目的没有帮助)。我能想出的最接近的是myStringBuilder.replace(0, myStringBuilder.length(), myString),但这真的很难看,并没有清楚地传达我的意图。所以我想用我自己的实用程序类来扩展这些类,它添加了一个 set() 方法(并在内部使用替换),但是这些类被声明为 final 出于某种奇怪的原因,我不能这样做要么。

我错过了什么吗?是否有一些首选的方式来做我想做的事情 - 传入某种可写的字符串缓冲区,该方法可以将值放入其中?这些类被声明为 final 有充分的理由吗?

这种方法的一个例子可能是:

void foo(List<ObjectA> arg1, List<ObjectB> arg2, StringBuffer somethingInteresting, StringBuffer somethingElseInteresting)

如果两个字符串在语义上不相关,我不想用 List 替换最后两个参数,因为我在列表顺序上强加了一些没有明确传达的语义。我不想传入两个单独的 List 并期望每个返回的 size() 为 1,因为调用者也不清楚这一点。

【问题讨论】:

  • 你能分享预期的方法签名吗?
  • 希望当前文本更清晰。我的意思是对于任何给定的参数,我希望得到一个结果,因此传入一堆列表,每个列表在返回时的 size() 都应该为 1,这是一种误导。
  • 我添加了一个方法签名和一些额外的澄清文本。
  • 你的问题有点不清楚,有点像文字墙。您能否在程序的实际上下文中添加一个简明扼要的陈述,说明您究竟想要完成什么?
  • 您所描述的技术术语是 out 参数。 Java 没有直接支持此功能。

标签: java string parameter-passing


【解决方案1】:

问题是你拒绝创建另一个类。我并不是说你的问题是无效的,但是如果你想返回一堆值并且你的函数知道单一责任原则,那么这些值是相关的。由于它们是相关的,因此您将有其他想要对它们进行操作的东西作为一个组。这些操作属于您返回的类。

我从不后悔创建一个返回相似值的类。

我从不后悔拆分返回两个不相关值的类。

Java 尽量不让做你会后悔的事情变得容易。

顺便说一句,要直接回答问题,您可能会返回一个字符串数组。 String[] 的返回值并让它返回类似“new String[] {firstString, secondString,thirdString}”的内容,但正如我所说,这通常是错误的路径。

正如你所说,你可以创建一个可变字符串,但它们是不可变的有一个很好的理由。不变性是线程安全的关键——即使你认为你使用的线程不多,在你下面改变值也是一个问题。高度线程化的语言正在转向不变性(函数式风格)——我不会开始构建一个远离它的基础设施。

【讨论】:

  • 谢谢。从语义上讲,我不认为传入数组与传入 List 有很大不同(尽管它更轻量级)——在这两种情况下,结果的语义排序都是隐式的,这很糟糕。
  • 是的,传递数组或列表是不好的,正如我所说,创建一个类——最好是不可变的。我只是想回答提出的问题。
  • 另外,请不要改变传递给你的东西,除非它真的需要做。这是下一个编辑器很容易错过的意外行为。你真的应该在返回值中返回你的结果。 Java 没有“out”参数是有原因的——它们只是一个坏主意。不过,以某种可预测的方式改变具有状态的业务对象是合理的。
  • 顺便说一句-“SRP”?我不认识那个缩写词。
  • @BobDoolittle ps--对不起,我不是想成为精英或任何东西,我只是不想弄清楚我是否能正确拼写责任。
【解决方案2】:

如果你不喜欢使用myStringBuilder.replace(0, myStringBuilder.length(), myString),因为它的意图不清楚,你可以使用

  myStringBuilder.setLength(0);     // clears the existing content
  myStringBuilder.append(myString); // sets the new string

【讨论】:

  • 我想我只是对为什么这个类一开始没有提供方法来做到这一点感到困惑。似乎是一个很大的疏忽。也许(正如 Bill K 建议的那样)这是故意的,旨在引导人们远离模拟返回参数:-)
  • 我仍然认为没有充分的理由将这些类声明为“final”,从而阻止任何人使用其他功能扩展它们。
  • Final 主要是速度问题。这些对象的使用如此频繁,以至于编译器可以获得相当大的速度提升,因为它们是最终的。请记住——Java 比 C 慢大约 2 倍,这对于提供垃圾收集且没有指针的基于 vm 的语言来说速度非常快。他们加快了一切可能做到这一点。他们还可以提供某种程度的信任——当一个方法接受/返回一个字符串时,你可以相信很多假设,如果它不是最终的——谁知道呢?它甚至可能在定时器事件或其他东西上发生变异!?!
猜你喜欢
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
  • 2015-03-15
相关资源
最近更新 更多