使用第三方API,我发现了以下内容。
而不是使用,
public static string getString(){
return "Hello World";
}
它使用类似
的东西public static void getString(String output){
}
我正在分配“输出”字符串。
我很好奇实现这种功能的原因。使用这些输出参数有什么好处?
答案 0 :(得分:21)
在你的例子中有些事情是不对的。
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”, 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"
}
答案 1 :(得分:4)
我不同意贾斯帕:“在我看来,这是一个非常丑陋和糟糕的方式来回报不止一个结果”。 在.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中项的不存在区分开来。有时这是必要的。
答案 2 :(得分:3)
该示例错误,Java没有输出参数。
您可以做的一件事就是模仿这种行为:
public void doSomething(String[] output) {
output[0] = "Hello World!";
}
但恕我直言,这在多个级别上很糟糕。 :)
如果你想要一个方法返回一些东西,让它返回它。如果需要返回多个对象,请创建一个容器类以将这些对象放入并返回该对象。
答案 3 :(得分:1)
此功能有一个很大的缺点 - 它不起作用。功能参数是功能的本地功能,分配给它们在功能之外没有任何影响 另一方面
void getString(StringBuilder builder) {
builder.delete(0, builder.length());
builder.append("hello world");
}
会起作用,但我认为没有这样做的好处(除非你需要返回多个值)。
答案 4 :(得分:1)
字符串是不可变的,您不能将Java的伪输出参数与不可变对象一起使用。
此外,输出的范围仅限于 getString 方法。如果您更改输出变量,则调用者将看不到任何内容。
但是,您可以更改参数的状态。请考虑以下示例:
void handle(Request r) {
doStuff(r.getContent());
r.changeState("foobar");
r.setHandled();
}
如果您有一个管理器使用单个请求调用多个句柄,您可以更改请求的状态以允许(通过其他处理程序)对修改的内容进行进一步处理。经理也可以决定停止处理。
优点:
答案 5 :(得分:1)
实际上,在java中输出参数是不可能的,但你可以通过编写一个泛型类来使该方法对不可变的String和原语进行去引用,其中不可变的是泛型的。 value和setter和getter,或者使用一个数组,其中元素0(长度为1)是提供的值,它首先实例化,因为在某些情况下你需要返回多个值,必须编写一个类才能将它们返回到该类仅用于浪费文本而不是真正可重复使用。
现在是C / C ++和.Net(单声道或MS),它促使我不支持至少对基元的去引用;所以,我转而使用数组。
这是一个例子。假设您需要创建一个函数(方法)来检查索引是否在数组中有效,但您还希望在验证索引后返回剩余长度。我们在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)'。 只要[] []或[]首先在内存中实例化至少一个元素,它就能正常工作。
答案 6 :(得分:0)
有时这种机制可以避免创建新对象。
实施例: 如果无论如何都存在适当的对象,将它传递给方法并更改一些字段会更快。
这比在被调用方法中创建新对象,返回并分配其引用(生成需要在某个时间收集的垃圾)更有效。
答案 7 :(得分:0)
在我看来,当你在一个函数中有多个结果时,这很有用。