繁体   English   中英

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

[英]When you need pass by reference in Java to assign values to multiple parameters, how do you do it?

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

除了重新设计程序之外,这里最好的选择是什么呢?

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

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

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

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

但是,我称之为高度非常规,并不会推荐它。 通过重构获得的任何改进都会被破坏。

我需要通过引用传递

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

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

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

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

对我来说听起来不太面向对象,特别是在阅读你的编辑之后。

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

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);

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

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

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

编辑

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

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

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

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;
    }
}

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

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

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

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来使它成为通用的,然后再投射东西,但这变得非常混乱。

我认为你最好考虑一下你的数据如何相关并将其转化为逻辑类。

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

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

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)公开。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM