1

我知道没有办法访问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 知道。

(在这段代码中没有,但是例如我有具有自己的字段的子类,并且在父类中我有一个方法filledInteger() 应该更改子类的指定属性(他从方法 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 类

4

5 回答 5

1

我如何在 Java 中实现它?

通过反射 API 非常痛苦。如果你想写这样的代码,最好的办法是使用另一种语言。

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

于 2012-05-04T20:56:30.653 回答
1

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

问题是,虽然很遗憾您不能在这里执行此操作,但它实际上可以防止大量无意的错误被释放。

于 2012-05-04T20:57:26.623 回答
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();
    }
}
于 2012-05-04T21:00:18.500 回答
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);
}
于 2012-05-04T21:02:26.153 回答
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);
  }

}
于 2012-05-04T21:09:17.510 回答