关于java和链接“&”的有趣问题

时间:2012-05-04 20:47:48

标签: java pass-by-reference

我知道无法访问java中的变量链接(例如在& C或& php中)。但是,例如我有这样的任务:

public class JustTest {

    private int n = 1;
    private int x = 10;

    public int[] getIntegers() {
        return new int[] { n, x };
    }

    public void filledInteger() {
        int[] vals = getIntegers();

        System.out.println("Before change");
        System.out.println(Arrays.toString(vals));

        vals[0] = 2;
        vals[1] = 20;

        System.out.println("After change");
        System.out.println(Arrays.toString(vals));

        System.out.println("Values of name & xml");
        System.out.println(n);
        System.out.println(x);

        System.out.println("calling getIntegers");
        System.out.println(Arrays.toString(getIntegers()));
    }

    public static void main(String[] args) {
        JustTest t = new JustTest();
        t.filledInteger();
    }

}

结果是:

Before change
[1, 10]
After change
[2, 20]
Values of name & xml
1
10
calling getIntegers
[1, 10]

所以,我想更改类实例的“n”和“x”字段的值。我不能通过直接设置(this-> n = 20;)来做到这一点,因为我可能不知道我有哪些字段。只有方法getIntegers知道。

(在这段代码中没有,但是例如我有子类有自己的字段,在父类中我有一个方法fillInteger(),它应该改变子类的指定属性(他从方法中知道这个属性) getIntegers,它在父类中是抽象的,并在子类中实现))

这是简单的实现(没有继承),使用php中的链接

<?php


class JustTest {

    private $n = 1;
    private $x = 10;

    public function getIntegers() {
        return array( &$this->n, &$this->x );
    }

    public function filledInteger() {
        $vals = $this->getIntegers();

        echo("Before change" . "<br/>");
        echo(print_r($vals, true) . "<br/>");

        $vals[0] = 2;
        $vals[1] = 20;

        echo("After change" . "<br/>");
        echo(print_r($vals, true) . "<br/>");

        echo("Values of n & x". "<br/>");
        echo $this->n , "<br/>";
        echo $this->x , "<br/>";

        echo("call getIntegers again" . "<br/>");
        echo(print_r($this->getIntegers(), true) . "<br/>");
    }

}

$t = new JustTest();
$t->filledInteger();

?>

结果是:

Before change
Array ( [0] => 1 [1] => 10 ) 
After change
Array ( [0] => 2 [1] => 20 ) 
Values of n & x
2
20
call getIntegers again
Array ( [0] => 2 [1] => 20 )

这就是我真正需要的。我只是好奇我如何在java中实现它 希望你明白。

下一个例子:

public abstract class ParentTest {
        abstract int[] getIntegers();

        public void fillIntegers(int[] newIntegers) {
            int[] integersOfChild = getIntegers();

            for (int i = 0; i < integersOfChild.length; i++) {
                integersOfChild[i] = newIntegers[i];
            }
        }
    }

    public class ChildTest extends ParentTest {

        private int x;
        private int y;

        @Override
        int[] getIntegers() {
            return new int[] {x, y};
        }

    }

    public class UseTest {
        void main() {
            List<ParentTest> list;

            for (ParentTest item : list) {
                item.fillIntegers(myItegers);
            }
        }
    }

这就是我需要的。我有一个ParentTest实例列表(它可能是ChildTest,或ChildTest2,或ChildTest3;但它们是ParentTest的所有子项),我需要用我的整数值填充所有字段,但我不知道列表实例中是否有项目ChildTest,ChildTest2或ChildTest3类

5 个答案:

答案 0 :(得分:1)

  

如何在Java中实现此功能?

通过Reflection API带来极大的痛苦。如果你想编写这样的代码,最好的想法是使用另一种语言。

考虑使用Groovy进行编程。您可以使用数组语法直接按名称访问类成员:t["n"] = 2;这适用于旧版Java代码,因此无需修改TestClass以支持此用法。

答案 1 :(得分:1)

您所谈论的概念称为传递参考。 Java在很大程度上放弃了它 - 它产生了太多的副作用,就像你在这里看到的那样。

问题在于,虽然不幸的是你不能在这里做到这一点,但实际上它可以防止大量无意的错误被释放。

答案 2 :(得分:0)

这样的事情:

public final class JustTest {

    private final Map<String, Object> fields;

    public void filledInteger() {
        System.out.println("Before change\n" + this.fields);

        fields.put("N", 2);
        fields.put("X", 20);

        System.out.println("After change\n" + this.fields);

        System.out.println("Values of name & xml\n" + fields.get("N")
           + "\n" + fields.get("X"));
    }

    private JustTest() {
        this.fields = Maps.newHashMap(); // guava
        fields.put("N", 1);
        fields.put("X", 10);
    }

    public static void main(String[] args) {
        final JustTest t = new JustTest();
        t.filledInteger();
    }
}

答案 3 :(得分:0)

你的php示例不会返回一个int数组,而是返回一个int指针数组。这不是你可以用Java做的事情,事实上,这不是你想用Java做的事情。给出一个用例,可能有更好的方法来解决你遇到的问题。

如果要返回其他人可以影响的对象并将其包含为成员变量,请执行此操作。一个ArrayList,HashMap等......有很多东西可以满足你的需求。如果给你一个别人的课程,你必须坚持自己的代码,你可以绕过他们的私人声明做以下事情:

public void setN(JustTest j, int n) {
    //You would handle some exceptions here also
    Field f = JustTest.class.getDeclaredField("n");
    f.setInt(j, n);
}

答案 4 :(得分:0)

如果没有反射,您不能执行单个字段,但可以更改集合的内容。请注意,这不是真正意图的行为,而是在使用集合时必须注意的事项。

输出5 3 2 4 2 4

public class Test
{
  public Vector<Integer> args = new Vector<Integer>();

  public void fillArgs()
  {
    args.add(5);
    args.add(3);
  }
  public Vector<Integer> getArgs()
  {
    return args;
  }

  public static void main(String args[])
  {
    Test s = new Test();

    s.fillArgs();
    Vector<Integer> temp = s.getArgs();
    for (Integer i : temp)
      System.out.println(i);
    temp.setElementAt(2, 0);
    temp.setElementAt(4, 1);
    for (Integer i : temp)
      System.out.println(i);
    for (Integer i : s.getArgs())
      System.out.println(i);
  }

}