当您需要在Java中通过引用传递为多个参数赋值时,您是如何做到的?

时间:2010-05-04 01:02:33

标签: java pass-by-reference

为了将一些方法重构为较小的方法,我需要通过引用传递,因为我只能有一个返回类型。每当我需要这样做时,我都可以创建一个不同的返回或参数类型,但后来我最终得到了一堆臃肿的,看似不必要的类。

除了重新设计程序之外,这里有什么最好的替代方案,这是不可能完成的?

编辑:其中一些可以重新设计,这就是我正在做的事情,但是,例如,它在一个点上找到了一个巨大的集合中的最小值和第二个最小值然后操纵它们。我想把它分成2个方法 - 一个发现,另一个操纵 - 但我似乎不太可能干净利落地做到这一点。

8 个答案:

答案 0 :(得分:4)

你所说的是通过所谓的out参数“返回”多个值,就像你有时在C中找到的那样,通过引用传递?

你要求提供一个返回单个值类的替代方法,但这确实是正确的做法。

但是,既然你问,是的,你是正确的,你需要更多的工作来获得Java中的pass-by-reference语义。 Java总是按值传递(是的,我的意思是 - 它是传递给方法的对象引用,并且它们是通过值传递的)。因此,如果你想以这种方式传回一个新的引用,你可以做一些像传递一个Object的数组,并更改它包含的引用的东西。

然而,我称这是非常传统的,不会推荐它。通过重构获得的任何改进都会被破坏。

答案 1 :(得分:1)

  

我需要通过引用传递

严格来说,Java没有通过引用传递。在Java中只有一种传递机制,它是按值传递的。

对于对象,传递的东西不是生成在堆上的对象本身。它是对值传递的对象的引用。

这可能听起来像是一个挑剔,但它是一个重要的。

我不知道这与重构有什么关系。如果您需要创建新类型以便返回,请务必执行此操作。我敢打赌,你真的没有反映手头问题的对象模型,这就是你有这个重构问题的原因。

对我来说听起来不太面向对象,尤其是在阅读完编辑后。

答案 2 :(得分:1)

你可以做一些事情,比如创建一个可以处理函数值的泛型类。

private static class OutValue<T> {
    public T value;

    static <X> OutValue<X> makeOutValue(X value) {
        OutValue<X> outValue = new OutValue<X>();
        outValue.value = value;
        return outValue;
    }
}

这是一个如何使用类从函数中获取整数的示例。

void getInteger(OutValue<Integer> x)
{
    x.value = 1;
}

OutValue<Integer> outValue = OutValue.makeOutValue(0);
getInteger(outValue);
System.out.println("value = " + outValue.value);

这可能不是最优雅的整体解决方案,但是如果你不想做更多涉及的重构,它将使你不必编写大量的类。

答案 3 :(得分:0)

  

一堆臃肿的,看似不必要的课程。

嗯 要么数据属于一个,这就是为什么你决定从单一方法返回它们,或者它们没有。如果他们这样做,是不是新班级合适? 作为最后一个沟,你可以返回一个Vector。

修改

或者如果你总是有一个有限数量的返回项,你可以使用类似Pair<T1,T2>的东西(或定义一些这样的通用元组类型)

答案 4 :(得分:0)

将变量提升为实例变量,这两种方法都可以看到它们(毕竟你可以在对象中拥有状态)。如果他们看起来不应该属于你的对象,那么我认为你无法绕过重新设计。

答案 5 :(得分:0)

因为在一个方法中,对象引用的参数是按值传递的,所以你不能按照以下方式做一些事情:

import java.awt.Point;

public class Example {
    public static void main(String args[]) {
        Point pnt1 = new Point(0, 0);
        Point pnt2 = new Point(0, 0);
        System.out.println("X: " + pnt1.x + " Y: " + pnt1.y);
        System.out.println("X: " + pnt2.x + " Y: " + pnt2.y);
        System.out.println(" ");
        sillyMethod(pnt1, pnt2);
        System.out.println("X: " + pnt1.x + " Y: " + pnt1.y);
        System.out.println("X: " + pnt2.x + " Y: " + pnt2.y);
    }

    public static void sillyMethod(Point arg1, Point arg2) {
        arg1.x = 100;
        arg1.y = 100;
        arg2.x = 200;
        arg2.y = 200;
    }
}

这样,您将更改对象的值,而不返回分歧类型。

答案 6 :(得分:0)

如果没有更多细节,很难给出具体的建议。但可能性包括:

将相关函数放入单个类中并生成数据成员变量。喜欢把你的“发现和微小两个最小”:

class ManipulateLeast2
{
  List<int> list;
  int firstSmallest;
  int secondSmallest;

  public ManipulateLeast2(List<int> list)
  {
    this.list=list;
  }
  public void findTwoSmallest()
  {
     .. scan list and populate firstSmallest and secondSmallest ...
  }
  public void processTwoSmallest()
  {
     ... process firstSmallest and secondSmallest and do whatever ...
  }
}

如果这很尴尬,另一种可能性就是创建一个类来保存你需要的值并返回它。像:

public class Smallest
{
  int first;
  int second;
  public Smallest(int first, int second)
  {
    this.first=first;
    this.second=second;
  }
}
...
public Smallest findSmallest(List list)
{
  ... find two smallest and put in first and second ...
  // Create the object and return it
  return new Smallest(first, second);
}

我认为这比伪造传递引用要好得多。但是,如果你真的坚持,可以通过将值放在包装器中来完成,如下所示:

public StringWrapper
{
  public String s;
}
...
// callee
void getTwoStrings(StringWrapper sw1, StringWrapper sw2)
{
  sw1.s="Hello";
  sw2.s="Goodbye";
} 
// caller
StringWrapper sw1=new StringWrapper();
StringWrapper sw2=new StringWrapper();
getTwoStrings(sw1, sw2);
System.out.println("First is "+sw1.s);
System.out.println("Second is "+sw2.s);

为了使其清洁,您需要为每个类单独包装。我想你可以创建一个ObjectWrapper来使它成为通用的,然后再投射东西,但这变得非常混乱。

我认为你最好考虑你的数据如何相关并将其转移到逻辑类中。

答案 7 :(得分:-1)

仅仅因为一个方法只能有一个返回类型并不意味着该类型不能包含多个信息。您似乎遇到的问题类型的解决方案是声明包含多条信息的数据类型。

按照问题中的示例(“在一个庞大的集合中找到最小和第二个最小值然后操纵它们”):

public class MinimumHolder {
    private int min;
    private int secondMin;
    public MinimumHolder(int min, int secondMin) {
        this.min = min;
        this.secondMin = secondMin;
    }

    //getters...
}

public MinimumHolder findTwoMinimums(Set<Integer> numbers) {
    // ...
    return new MinimumHolder(...);
}

public MinimumHolder manipulateData(MinimumHolder mins) {
    // do stuff with the data, this method could also be
    // declared as void if MinimumHolder was mutable
}

您还可以非常轻松地重构MinimumHolder,以便它可以保存一个“最小值”的变量列表,如果您想要找到两个以上的最小值,则会使用getMinimum(int position)公开。