繁体   English   中英

使用数组作为参数返回多个值是不好的做法

[英]Is it a bad practice to use arrays as parameter(s) to return multiple values

我有时(实际上,经常)发现自己使用单元素数组从方法返回多个值。 像这样的东西:

public static int foo(int param1, int param2[], String param3[])
{
    // method body
    ....
    // set return values
    param2[0] = <some value>;
    param3[0] = <some value>;

    return <some value>;
}

这是一种不好的做法吗? (好像是因为我的一些朋友说他们不知道它在做什么2秒!)但我之所以这么做的原因是因为这看起来最接近所谓的pass-by-reference C ++中的pass-by-reference C++并没有劝阻这种做法,所以......

但如果这真的是一种错误的做事方式,那么任何想法如何以干净的方式重写它?

谢谢

创建一个包含要返回的数据的对象。

然后,您可以返回该对象的实例。

class FooData {
    private int someInt;
    private int anotherInt;
    private String someString;

    public FooData(int a, int b, String c) {
        someInt = a;
        anotherInt = b;
        someString = c;
    }
}

public FooData foo() {
    // do stuff
    FooData fd = new FooData(blah, blahh, blahhh);
    return fd;
}

虽然我同意这里的一般意见,为此目的使用数组是不好的做法,但我想补充一些内容。 您确定首先通过“参考传递”确实是您所需要的吗? 很多人说你的代码风格不好,但现在让我告诉你为什么那是恕我直言。 “通过引用传递”主要是“通过副作用编程”的同义词,这是你总是想要避免的事情。 它使代码更难以调试和理解,并且在多线程环境中,这种态度的不良影响确实会给你带来困难。 要在Java中编写可伸缩且线程安全的代码,您应该尽可能地使对象“只读”,即理想情况下,您创建一个对象并同时对其进行初始化,然后在整个应用程序中使用此不可修改的状态。 对状态的逻辑更改几乎总是被视为新状态的“创建”,即创建初始化为当时所需状态的新实例。 许多现代脚本语言只允许您以这种方式工作,它使事情更容易理解。 与C ++相反,Java在分配和释放短期对象方面效率更高,因此其他人建议的内容实际上没有任何问题:创建一个特殊类的实例来保存函数结果,仅用于此目的返回结果。 即使你在循环中这样做,JVM也足够聪明,可以有效地处理它。 Java只会在需要时以非常大的块分配来自操作系统的内存,并且将在内部处理对象创建和释放,而不会产生C / C ++等语言的开销。 “通过引用传递”实际上对Java没有多大帮助。

编辑:我建议你在这个论坛或网上搜索术语“副作用”,“函数式编程”或“不变性”。 这很可能会为您的问题打开一个新的视角。

我认为使用作为方法参数的单元素数组“返回”值是不好的做法。

这是关于这个主题的另一个问题 简而言之,它的可读性非常糟糕。

有一个简单的解决方法:在您专门为此目的定义的类中包装要返回的所有值,并返回该类的实例。

return new ValueHolder(someValue1, someValue2, someValue3);

这不是非常惯用的java。 通常有更好的软件设计方法。

你真正用“单元素数组”做的是创建一个可变对象(因为String是不可变的,就像int这样的基元)并通过引用传递它。 修改此可变对象称为该方法的“副作用”。 通常,您应该最小化可变性( Effective Java Item 15 ),并且您的方法应该是无副作用的。 这里有几种方法。

1.将方法拆分为两个(或三个)方法,所有方法都采用相同的参数:

public static int foo1(int param1)
{
    // method body
    ....
    return <some value>;
}

同样,你可能有

public static int foo2(int param1) { ... }

public static String foo3(int param1) { ... }

2.返回复合对象。

public Container {
    private final int originalReturn;
    private final int param2;
    private final String param3;

    public Container(int originalReturn, int param2, String param3) {
        this.originalReturn = originalReturn;
        this.param2 = param2;
        this.param3 = param3;
    }

    // getters
}

public static Container foo(int param1, int param2[], String param3[])
{
    // method body
    ....
    // set return values
    return new Container(<some value>, <some value>, <some value>);
}

如果值不相关,这确实是不好的做法。 这通常是一个指示器,您可以将该功能拆分为两个,每个返回一个值。

编辑:

我假设您要返回在数组中的方法中计算的两个值。 这不是这种情况吗?

例如

public int[] getStatistics(int[] nums)
{
    //code

    int[] returns = new int[2];
    returns[0] = mean;
    returns[1] = mode;

    return returns;
}

上面的函数可以分为getMean()getMode()

通过引用传递变量允许函数“合法地”改变它们的值。 请参阅此文章以清除Java中何时可能出现的混淆,以及何时不...

如果值具有不同类型和不同实体(例如名称和地址等),这是不好的做法。创建具有相同数据类型的数组(例如地址列表)就可以了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM