Java中如何以参数形式返回对对象的引用 虽然我已经编程C、C++和C多年,但我对java只是表面上熟悉。帮助我的同事完成一个Java大学项目时,他需要从Java中的一个方法返回对两个对象的引用。我建议返回一个作为函数值,返回第二个作为引用。他不知道该怎么做。我做了一些研究,意识到这可能是不可能的。我的问题是在Java中,当一个方法需要返回对一个对象的多个引用时,常用的方法是什么。这是我儿子的具体例子 // This method returns references to the head and tail objects from the passed in // linked list. The head object is returned as the function value and the tail is // returned as a parameter. public Static Node GetHeadTail(List list, Node tail)

Java中如何以参数形式返回对对象的引用 虽然我已经编程C、C++和C多年,但我对java只是表面上熟悉。帮助我的同事完成一个Java大学项目时,他需要从Java中的一个方法返回对两个对象的引用。我建议返回一个作为函数值,返回第二个作为引用。他不知道该怎么做。我做了一些研究,意识到这可能是不可能的。我的问题是在Java中,当一个方法需要返回对一个对象的多个引用时,常用的方法是什么。这是我儿子的具体例子 // This method returns references to the head and tail objects from the passed in // linked list. The head object is returned as the function value and the tail is // returned as a parameter. public Static Node GetHeadTail(List list, Node tail),java,reference,parameter-passing,Java,Reference,Parameter Passing,我意识到上述方法在Java中不起作用,因为尾部是对节点的引用,而在Java中,引用本身是通过值传递的。Java中最常见的处理方法是什么?我儿子的解决方案是为函数值返回一个由2个节点对象组成的数组。我说这是一个糟糕的解决方案,因为它没有记录数组中每个元素的含义。另一个解决方案是创建一个包含头部和尾部引用的对象。然而,在特定的示例中,最感兴趣的是head指针,如果返回了一个对象,那么如果方法的调用方只需要head,那么它将为调用方创建不希望的编码开销 在Java中只能按值传递。您最好的解决方案是您儿

我意识到上述方法在Java中不起作用,因为尾部是对节点的引用,而在Java中,引用本身是通过值传递的。Java中最常见的处理方法是什么?我儿子的解决方案是为函数值返回一个由2个节点对象组成的数组。我说这是一个糟糕的解决方案,因为它没有记录数组中每个元素的含义。另一个解决方案是创建一个包含头部和尾部引用的对象。然而,在特定的示例中,最感兴趣的是head指针,如果返回了一个对象,那么如果方法的调用方只需要head,那么它将为调用方创建不希望的编码开销

在Java中只能按值传递。您最好的解决方案是您儿子建议的第二个解决方案,即返回具有头部和尾部的对象。

在这种情况下,java程序员通常会创建一个包含两个成员的类:
head
tail
。这将是
getHeadTail(List)
方法的返回类型

LinkedList list = new LinkedList();
head = list.getFirst();
tail = list.getLast();
Java总是按值传递。困难的事情可能是理解 Java将对象作为引用传递,并且这些引用被传递 按价值计算。()

但是,您可以这样做:

public static void main(String[] args)
{
    Car c = new Car("Blue");
    System.out.println(c.getName());
    changer(c);
    System.out.println(c.getName());
}

public static void changer(Car c)
{
    c.setName("Red");
}
class MyCrazyClass {

  private static void myCrazyMethod(Future<String> returnVal1, Future<Integer> returnVal2, Future<Float> returnVal3) {
    returnVal1.set("We are cool!");
    returnVal2.set(123);
    returnVal3.set(321F);
  }

  public static void main(String[] args) {
    Future<String> strRetVal = new Future<>();
    Future<Integer> intRetVal = new Future<>();
    Future<Float> floatRetVal = new Future<>();

    myCrazyMethod(strRetVal, intRetVal, floatRetVal);

    System.out.println(strRetVal.get());
    System.out.println(intRetVal.get());
    System.out.println(floatRetVal.get());
  }
}
汽车类

public class Car 
{
    private String name;

    public Car(String n)
    {
        name = n;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String n)
    {
        name = n;
    }
}
输出将是:

Blue
Red


知道了这一点,您将能够更改
tail
指向的内容,并且仍然能够返回
head

Java做了一件有趣的事情,它是按值传递和按引用传递的混合体。基本上,函数不能更改参数,但函数可以通过调用其中的某个方法来要求参数自行更改


在回答“Java中最常见的处理方法是什么?”时,您创建包含head和tail引用的类的解决方案可能是最常见和最佳实践。如果可能的话,最好只使用单独的getHead和getTail方法。

一个稍微不那么明显的解决方案:使用一种内置类型,如Queue或LinkedList,它已经有了head和tail

LinkedList list = new LinkedList();
head = list.getFirst();
tail = list.getLast();

根据你的需要,有很多像这样的类型

一种有点老套的技术是使用数组作为参数。然后,函数可以更改一个或多个元素的值以“返回”它。它并不漂亮,但可以完成工作,并且避免为此目的创建特殊的包装器对象


作为旁注,Scala通过让您返回元组解决了这个问题。

如果您试图实现一个返回多个值作为参数的方法,您可以使用如下方法:

public static void main(String[] args)
{
    Car c = new Car("Blue");
    System.out.println(c.getName());
    changer(c);
    System.out.println(c.getName());
}

public static void changer(Car c)
{
    c.setName("Red");
}
class MyCrazyClass {

  private static void myCrazyMethod(Future<String> returnVal1, Future<Integer> returnVal2, Future<Float> returnVal3) {
    returnVal1.set("We are cool!");
    returnVal2.set(123);
    returnVal3.set(321F);
  }

  public static void main(String[] args) {
    Future<String> strRetVal = new Future<>();
    Future<Integer> intRetVal = new Future<>();
    Future<Float> floatRetVal = new Future<>();

    myCrazyMethod(strRetVal, intRetVal, floatRetVal);

    System.out.println(strRetVal.get());
    System.out.println(intRetVal.get());
    System.out.println(floatRetVal.get());
  }
}
公共类未来{
私人T实例;
公共部门得不到{
返回此.instance;
}
公共无效集(T值){
this.instance=值;
}
}
然后像这样使用它:

public static void main(String[] args)
{
    Car c = new Car("Blue");
    System.out.println(c.getName());
    changer(c);
    System.out.println(c.getName());
}

public static void changer(Car c)
{
    c.setName("Red");
}
class MyCrazyClass {

  private static void myCrazyMethod(Future<String> returnVal1, Future<Integer> returnVal2, Future<Float> returnVal3) {
    returnVal1.set("We are cool!");
    returnVal2.set(123);
    returnVal3.set(321F);
  }

  public static void main(String[] args) {
    Future<String> strRetVal = new Future<>();
    Future<Integer> intRetVal = new Future<>();
    Future<Float> floatRetVal = new Future<>();

    myCrazyMethod(strRetVal, intRetVal, floatRetVal);

    System.out.println(strRetVal.get());
    System.out.println(intRetVal.get());
    System.out.println(floatRetVal.get());
  }
}

事实上,常见的解决方案是您已经知道的:a)将要返回的对象封装在一个对象中,或b)返回一个数组。您真的需要在一次调用中获得这两个吗?在大多数情况下,我只会使用两种方法:
getHead
getTail
。我认为你儿子的解决方案是好的,但是根据它的情况创建一个对象是很好的。根据我个人的说法,我发现了你暗示的神秘方法,但我从来没有真正喜欢C++。我会将头部和尾部包装在某个命名有意义的类(您描述的解决方案之一)的对象中。其他JVM语言会给你更多的选择(比如Scala,以及它在语法和类型上处理元组的方式),但我担心这和你在Java中得到的一样好。将其拆分为两个单独的方法听起来也像是一个计划。拆分为两个单独的调用并不是一个好的解决方案,因为在本例中查找head和tail在计算上很重要,一旦方法返回,结果就会丢失。也就是说,必须再次遍历列表才能找到尾部。我在这里看到的最好的建议是创建一个独特的类来包含head和tail。