7

使用第三方 API,我观察到以下内容。

而不是使用,

public static string getString(){
   return "Hello World";
}

它使用类似的东西

public static void getString(String output){

}

我正在分配“输出”字符串。

我很好奇实现这种功能的原因。使用这样的输出参数有什么好处?

4

8 回答 8

25

你的例子有些不对劲。

class Foo {

    public static void main(String[] args) {
        String x = "foo";
        getString(x);
        System.out.println(x);
    }

    public static void getString(String output){
        output = "Hello World"
    }
}

在上面的程序中,将输出字符串“foo”,而不是“Hello World”。

某些类型是可变的,在这种情况下,您可以修改传递给函数的对象。对于不可变类型(例如String),您必须构建某种可以传递的包装类:

class Holder<T> {
    public Holder(T value) {
        this.value = value;
    }
    public T value;
}

然后你可以绕过持有人:

public static void main(String[] args) {
    String x = "foo";
    Holder<String> h = new Holder(x);
    getString(h);
    System.out.println(h.value);
}

public static void getString(Holder<String> output){
    output.value = "Hello World"
}
于 2009-09-10T07:58:38.050 回答
5

这个例子是错误的,Java 没有输出参数。

你可以做的一件事来模仿这种行为是:

public void doSomething(String[] output) {
    output[0] = "Hello World!";
}

但是恕我直言,这在多个层面上都很糟糕。:)

如果你想要一个方法返回一些东西,让它返回它。如果您需要返回多个对象,请创建一个容器类来将这些对象放入并返回。

于 2009-09-10T08:05:27.410 回答
3

我不同意 Jasper:“在我看来,这是返回多个结果的一种非常丑陋和糟糕的方式”。在 .NET 中有一个利用输出参数的有趣结构:

bool IDictionary.TryGet(key, out value);

我觉得它非常有用和优雅。这是最方便的方式来询问一个项目是否在集合中并同时返回它。有了它,你可以写:

object obj;
if (myList.TryGet(theKey, out obj))
{
  ... work with the obj;
}

如果我看到像这样的旧式代码,我会经常责骂我的开发人员:

if (myList.Contains(theKey))
{
  obj = myList.Get(theKey);
}

你看,它把性能减半。在 Java 中,无法在一次调用中区分现有项目的空值与 Map 中不存在的项目。有时这是必要的。

于 2010-12-28T21:48:47.763 回答
1

这个功能有一个很大的缺点——它不起作用。函数参数是函数的局部参数,分配给它们不会在函数之外产生任何影响。
另一方面

void getString(StringBuilder builder) {
    builder.delete(0, builder.length());
    builder.append("hello world");
}

会起作用,但我认为这样做没有任何好处(除非您需要返回多个值)。

于 2009-09-10T08:04:18.247 回答
1

有时这种机制可以避免创建新对象。

示例:如果存在适当的对象,则将其传递给方法并更改某些字段会更快。

这比在被调用方法中创建新对象并返回并分配其引用(产生需要有时收集的垃圾)更有效。

于 2009-09-10T08:05:53.487 回答
1

字符串是不可变的,您不能将 Java 的伪输出参数与不可变对象一起使用。

此外,输出范围仅限于getString方法。如果您更改输出变量,调用者将看不到任何东西。

但是,您可以做的是更改参数的状态。考虑以下示例:

void handle(Request r) {
    doStuff(r.getContent());
    r.changeState("foobar");
    r.setHandled();
}

如果您有一个管理器使用单个请求调用多个句柄,您可以更改请求的状态以允许(由其他处理程序)对修改后的内容进行进一步处理。经理也可以决定停止处理。

好处:

  • 您不需要返回包含新内容以及处理是否应该停止的特殊对象。该对象只会被使用一次,并且创建对象会浪费内存和处理能力。
  • 您不必创建另一个 Request 对象并让垃圾收集器摆脱现在已过时的旧引用。
  • 在某些情况下,您无法创建新对象。例如,因为该对象是使用工厂创建的,而您无权访问它,或者因为该对象具有侦听器,而您不知道如何告诉正在侦听旧请求的对象他们应该改为听新的请求。
于 2009-09-10T08:14:48.753 回答
1

实际上,在 java 中不可能有参数,但是您可以通过编写一个泛型类,其中不可变是具有 value 和 setter 的泛型,使该方法对不可变 String 和原语进行取消引用和 getter 或使用数组,其中元素 0(长度为 1)是提供它首先实例化的值,因为在某些情况下,您需要返回多个值,而必须编写一个类只是为了将它们返回到类所在的位置只用过,只是浪费文本,不能真正重复使用。

现在是 C/C++ 和 .Net(单声道或 MS),它敦促我 Java 至少不支持对原语的取消引用;所以,我改用数组。

这是一个例子。假设您需要创建一个函数(方法)来检查数组中的索引是否有效,但您还想在索引验证后返回剩余的长度。让我们在 c 中将其称为 'bool validate_index(int index, int arr_len, int&rem)'。在 java 中执行此操作的一种方法是“Boolean validate_index(int index, int arr_len, int[] rem1)”。rem1 仅表示数组包含 1 个元素。

public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
    if (index < 0 || arr_len <= 0) return false;

    Boolean retVal = (index >= 0 && index < arr_len);

    if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));

    return retVal;

}

现在,如果我们使用它,我们可以获得布尔返回和余数。

 public static void main(String[] args)
 {
    int[] ints = int[]{1, 2, 3, 4, 5, 6};
    int[] aRem = int[]{-1};
    //because we can only scapegoat the de-ref we need to instantiate it first.
    Boolean result = validate_index(3, ints.length, aRem);

    System.out.println("Validation = " + result.toString());
    System.out.println("Remainding elements equals " + aRem[0].toString());

 }

puts: Validation = True puts: 剩余元素等于 2

数组元素要么总是指向栈上的对象,要么指向堆上对象的地址。因此,即使对于数组,也绝对可以将其用作取消引用,方法是将其实例化为 myArrayPointer = new Class[1][] 然后将其传递给数组,因为有时您不知道数组的长度会是多少直到调用通过类似 'Boolean tryToGetArray(SomeObject o, T[][] ppArray)' 的算法,这与 c/c++ 中的 'template bool tryToGetArray (SomeObject* p, T** ppArray)' 或C#'bool tryToGetArray(SomeObject o, ref T[] array)'。只要 [][] 或 [] 首先在内存中使用至少一个元素进行实例化,它就可以正常工作。

于 2012-08-08T03:10:03.530 回答
0

在我看来,当您在一个函数中有多个结果时,这很有用。

于 2009-09-10T12:17:50.240 回答