Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的输出参数_Java_Api_Methods_Output Parameter - Fatal编程技术网

Java中的输出参数

Java中的输出参数,java,api,methods,output-parameter,Java,Api,Methods,Output Parameter,使用第三方API,我观察到了以下几点 而不是使用 public static string getString(){ return "Hello World"; } 它使用类似 public static void getString(String output){ } 我正在获得分配的“输出”字符串 我很好奇实现这种功能的原因。使用这些输出参数有什么好处?在您的示例中有些地方不正确 class Foo { public static void main(String[]

使用第三方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”,而不是“helloworld”

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

class Holder<T> {
    public Holder(T value) {
        this.value = value;
    }
    public T value;
}
类持有者{
公共持有人(T值){
这个值=值;
}
公共价值观;
}
然后您可以绕过支架:

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"
}
publicstaticvoidmain(字符串[]args){
字符串x=“foo”;
支架h=新支架(x);
getString(h);
系统输出打印项次(h值);
}
公共静态无效getString(保持器输出){
output.value=“你好,世界”
}

此功能有一个很大的缺点-它不起作用。函数参数是函数的本地参数,分配给它们不会对函数之外产生任何影响。
另一方面

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

将起作用,但我看不出这样做有什么好处(除非您需要返回多个值)。

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

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

public void doSomething(String[] output) {
    output[0] = "Hello World!";
}
但我认为这在多个层面上都很糟糕


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

有时此机制可以避免创建新对象

例如: 如果适当的对象无论如何都存在,那么将其传递给方法并更改某些字段会更快


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

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

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

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

void handle(Request r) {
    doStuff(r.getContent());
    r.changeState("foobar");
    r.setHandled();
}
如果管理器使用单个请求调用多个句柄,则可以更改请求的状态,以允许(由其他处理程序)对修改的内容进行进一步处理。经理还可以决定停止处理

优点:

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

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

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

bool IDictionary.TryGet(key, out value);
我觉得它很有用,也很优雅。如果一件物品正在收集中并同时归还,这是获得aks最方便的方式。你可以用它写:

object obj;
if (myList.TryGet(theKey, out obj))
{
  ... work with the obj;
}
如果我看到旧式代码,我经常责骂我的开发人员,如:

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

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

事实上,在java中不可能有out参数,但您可以通过编写泛型类(其中不可变的是泛型,带有value和setter和getter)或使用数组(其中元素为0)来解决方法对不可变字符串和原语进行反引用的问题(长度为1)是首先实例化的值,因为在某些情况下,您需要返回多个值,必须编写一个类才能返回这些值,而该类仅被使用,这只是浪费了文本,并且不可真正重用

现在作为C/C++和.Net(mono或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;

}
puts:验证=真 puts:重新标记元素等于2

数组元素总是指向堆栈上的对象或堆上对象的地址。因此,将其作为反引用使用是绝对可能的,即使对于数组,也可以将其作为双数组实例化为myArrayPointer=new Class[1][]然后传入它,因为有时你不知道数组的长度,直到调用通过一个类似“Boolean-tryToGetArray(SomeObject o,t[][]ppArray)”的算法,这与c/c++中的“template-bool-tryToGetArray(SomeObject*p,t**ppArray)”或“bool-tryToGetArray(SomeObject o,ref t[]ppArray)”相同。 它起作用了,而且很好
 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());

 }