由于发送到Java中的方法的参数指向调用方法中的原始数据结构,因此其设计者是否打算将它们用于返回多个值,这是其他语言(如C语言)中的常量吗?
或者这是对Java的一般属性的危险误用,变量是指针吗?
答案 0 :(得分:15)
很久以前,我与Ken Arnold(Java团队的一次成员)进行了对话,这可能是1996年的第一次Java One会议。他说他们正考虑添加多个返回值所以你可以这样写:
x, y = foo();
当时推荐的方法是创建一个具有多个数据成员的类,然后返回它。
基于这一点,以及从事过Java工作的人的其他评论,我想说的意思是你返回一个类的实例,而不是修改传入的参数。
这是常见的做法(因为C程序员希望修改参数......最终他们通常会看到Java的做法。只需将其视为返回结构。: - )
(根据以下评论进行编辑)
我正在阅读一个文件并生成两个 数组,类型为String,int来自 它,从中选择一个元素 每一行。我想两个都回来 它们是任何调用它的函数 哪个文件可以这种方式分割。
我想,如果我理解你的话,我可能会这样做:
// could go with the Pair idea from another post, but I personally don't like that way
class Line
{
// would use appropriate names
private final int intVal;
private final String stringVal;
public Line(final int iVal, final String sVal)
{
intVal = iVal;
stringVal = sVal;
}
public int getIntVal()
{
return (intVal);
}
public String getStringVal()
{
return (stringVal);
}
// equals/hashCode/etc... as appropriate
}
然后让你的方法如下:
public void foo(final File file, final List<Line> lines)
{
// add to the List.
}
然后像这样调用它:
{
final List<Line> lines;
lines = new ArrayList<Line>();
foo(file, lines);
}
答案 1 :(得分:7)
在我看来,如果我们谈论的是公共方法,你应该创建一个代表返回值的单独类。当你有一个单独的班级时:
Point
类,而不是两个longs的数组)我总是选择返回一个新实例,而不是实际修改传入的值。对我来说这似乎更清楚,并且更倾向于不可变性。
另一方面,如果是内部方法,我猜可能会使用以下任何一种方法:
new Object[] { "str", longValue }
)Arrays.asList(...)
返回不可变列表)不过,我更喜欢最后一个选项,配备合适的构造函数。如果您发现自己从多个地方返回相同的元组,则尤其如此。
答案 2 :(得分:5)
见1999年推出的RFE:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4222792
我认为,如果你需要返回多个值来将它们封装在一个对象中,那么它的意图就是不允许它用Java语言。
使用像Scala这样的语言但是你可以返回元组,参见:
http://www.artima.com/scalazine/articles/steps.html
您也可以使用Java中的Generics返回一对对象,但这就是AFAIK。
编辑:元组
只是为此添加更多内容。我之前已经在项目中实现了一对,因为JDK内部缺乏。链接到我的实现在这里:
http://pbin.oogly.co.uk/listings/viewlistingdetail/5003504425055b47d857490ff73ab9
请注意,此处没有哈希码或等号,可能应该添加。
在对这些提供元组功能的问题进行研究时,我也遇到了这个问题:
它允许您创建包括其他类型的元组的Pair。
答案 3 :(得分:5)
我确实希望JDK中有一个Pair<E,F>
类,主要是出于这个原因。有Map<K,V>.Entry
,但创建一个实例总是很痛苦。
现在,当我需要com.google.common.collect.Maps.immutableEntry
Pair
答案 4 :(得分:2)
您无法真正返回多个值,但可以将对象传递给方法,并让方法改变这些值。这完全合法。请注意,您无法传入对象并使对象本身成为不同的对象。那就是:
private void myFunc(Object a) {
a = new Object();
}
将导致暂时和本地更改a
的值,但这不会更改调用者的值,例如,来自:< / p>
Object test = new Object();
myFunc(test);
myFunc返回后,您将拥有旧对象,而不是新对象。
法律(通常是气馁)是这样的:
private void changeDate(final Date date) {
date.setTime(1234567890L);
}
我选择Date
是有原因的。这是一个人们普遍认为应该永远不可变的课程。上面的方法将更改传递给它的任何Date
对象的内部值。当非常清楚该方法将改变或配置或修改传入的内容时,这种代码是合法的。
注意:一般来说,一个方法应该做一件事:
Collections.sort()
)或Collections.min()
)或Collections.checkedList()
或Collections.singleton()
)Collections
没有示例,但StringBuilder.append()
是一个很好的例子。)变异传入对象的方法和返回单独的返回值通常会做太多事情。
答案 5 :(得分:0)
当然有一些方法可以修改作为参数传递的对象(see java.io.Reader.read(byte[] buffer))作为示例,但是我没有看到用作返回值的替代参数,特别是对于多个参数。它在技术上可能有效,但这是非标准的。
答案 6 :(得分:0)
它通常不被认为是非常好的做法,但在JDK中偶尔会出现这种情况。查看View.getNextVisualPositionFrom()和相关方法的'biasRet'参数,例如:它实际上是一个用“额外返回值”填充的一维数组。
为什么这样做?好吧,只是为了节省你必须为“偶尔的额外返回值”创建一个额外的类定义。这是凌乱,不优雅,糟糕的设计,非面向对象,等等等等。我们都不时地完成它......
答案 7 :(得分:0)
一般来说,埃迪说的是,但我还要补充一点:
答案 8 :(得分:0)
我有一个Result对象,它通过一系列验证void方法作为方法参数进行级联。每个验证void方法都会改变结果参数对象以添加验证结果。
但是这是不可能测试的,因为现在我不能将void方法存根,以便在Result对象中返回验证的存根值。
因此,从测试的角度来看,似乎应该支持返回一个对象而不是改变一个方法参数。