通过第三方 API,我观察到以下情况。

而不是使用,

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

它使用类似的东西

public static void getString(String output){

}

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

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

有帮助吗?

解决方案

在你的例子中有些事情是不对的。

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”表示字符串“foo”。将输出 not “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"
}

其他提示

我不同意贾斯帕:“在我看来,这是一个非常丑陋和糟糕的方式来返回多个结果”。 在.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中项的不存在区分开来。有时这是必要的。

该示例错误,Java没有输出参数。

您可以做的一件事就是模仿这种行为:

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

但恕我直言,这在多个级别上很糟糕。 :)

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

此功能有一个很大的缺点 - 它不起作用。函数参数是函数的局部函数,并且赋值给它们在函数外部没有任何影响 另一方面

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

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

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

另外,范围 输出 仅限于 获取字符串 方法。如果您更改 输出 变量,调用者将看不到任何东西。

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

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

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

优点:

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

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

现在是C / C ++和.Net(单声道或MS),它促使我java至少不支持基元的去引用;所以,我转而使用数组。

这是一个例子。假设您需要创建一个函数(方法)来检查索引是否在数组中有效,但您还希望在验证索引后返回剩余长度。我们在c中将其称为'bool validate_index(int index,int arr_len,int&amp; 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 ++中的模拟bool tryToGetArray(SomeObject * p,T ** ppArray)'或C#'bool tryToGetArray(SomeObject o,ref T [] array)'。 只要[] []或[]首先在内存中实例化至少有一个元素,它就能正常工作。

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

实施例: 如果无论如何都存在适当的对象,将它传递给方法并更改一些字段会更快。

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top