在运行时按名称Java间接访问变量?

时间:2016-02-08 23:15:26

标签: java reflection

这个问题有很多部分,在最后一部分都有意义:

  1. 是否可以在运行时以编程方式列出Java类中任何程序员定义的变量。?

    我最近在VB.Net中编写了一个实用程序,它按名称列出了我项目中的所有表单,因此我可以选择一个从列表框中运行(仅用于开发目的)。在StackOverflow上的其他地方的帮助下,我能够将下面的一些代码固定在一起,并且为了说明的目的,这个例子被固定在一起......

        System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes(n).BaseType.FullName
    

    在Java中可以做类似的事情来列出变量名吗?例如,MyInteger,MyString或MyObject。它就像"当地人"背后的功能。 Visual Studio中的窗口(但我使用的是Eclipse for Java)。

  2. 在过去20年的某个地方,在另一种编程语言中,我遇到了一个名为Indirect(String varname)的函数。它用于通过 name 访问原始变量。并且' varname'参数本身可以是一个变量;它不一定是文字。以下是显示其用途的示例:

    int N1, N2, N3;
    // N1, N2, & N3 are all zero
    for (int i = 1; i < 4; i++){
        Indirect("N" + i.toString) = 100
    }
    // N1, N2, & N3 are now all 100
    

    Java是否具有Indirect()的等价物,或者有没有办法复制相同的功能..?

  3. 将所有这些粘合在一起,以及整个论坛发布的原因是,我有以下程序,我已经编写了用于调试目的,我将进入我的类以输出变量值开发期间的CSV格式......

    public String listVars(){
        Object input[] = {var1, var2, var3, var4, var5};    // list of vars
        String output = "";                     // output catcher
        int varCount = input.length;            // get the length of the array
        for (int i = 0; i < varCount; i++){     // loop through the array
            output += "\"" + input[i] + "\"";   // surround with quotes, append to output
            if (i < varCount-1){                // if the item NOT the last...
                output += ",";                  // append a comma to it
            }
        }
        return output;                          // return completed output
    }
    
  4. 我想要做的是使用自动枚举变量的代码自动输入Object数组,因此我不必复制&amp;将它们粘贴到函数中。而且我假设这样做,一旦确定了名称,就需要间接引用它们,因此可以用代码访问它们的值。

  5. PS - 按范围过滤变量会很不错,例如私人&#34;,&#39;超&#39;,&lt; classname&gt;,&#39;公共&#39;等等,但我知道这可能会让它有点太过分了。 = - )

2 个答案:

答案 0 :(得分:1)

  1. 在运行时列出类字段/方法
  2. 是的,你可以用反思做到这一点。请参阅教程here

    for (Field f : getClass().getDeclaredFields()) {
        System.out.println("found " + f);
    }
    
    1. “间接”访问
    2. 是的,使用上述机制查找您想要祭坛的字段,然后可以设置其值

      Field f = ... //get it from somewhere
      f.set(this, "new value");
      

      你想要达到的目标听起来非常接近j ava bean概念。它的要点是你保持getter和setter方法的getX()/ setX()命名约定,每个这样的对代表一个名为“x”的属性,然后你可以利用面向bean的库,比如{{ 3}}对你来说所有繁重的工作(我告诉过你),就像这样:

      Employee employee = ...;
      String firstName = (String)PropertyUtils.getSimpleProperty(employee, "firstName");
      String lastName = (String)PropertyUtils.getSimpleProperty(employee, "lastName");
       ... manipulate the values ...
      PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
      PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
      

答案 1 :(得分:0)

首先,可以在下面找到所有Java的反射api Bug 11046: __callee__ returns incorrect method name in orphan proc 学习该软件包的最佳方法可能是java自己的路径 java.lang.reflect package

TL; DR

1)经过一些调查后似乎有一个Field.getName(),所以这可能对你有好处。

2)确实有一种获取字段(变量)以及方法甚至构造函数的方法。 [特定路径页] [3] 这样做的方法是通过反射包中的Field类。这方面的一个例子是Field foo = myObject.class.getField("fieldName")class.getDeclaredField("name"),区别在于声明的版本只显示在该对象中,并且也获取私有字段。

还有一些版本class.getDeclaredFields()class.getFields()返回Field []。还有所有4种类型的方法和构造函数版本(声明,常规和两者的s(数组))

3)可以从访问修饰符(私人,公共等)以及Field.toGenericString()Field.getModifiers()等访问大量信息。

至于实现,它应该与Field.getDeclaredFields()结合Field.getName()Field.get*()一致,其中*是类型(int,long,Object等)。如果您需要来自超级类的字段并且仍想列出私有字段,那么您需要以Class.getSuperclass()递归地应用Field.getDeclaredFields()。 另外Field.toGenericString()如果你想要一个很好的长详细字符串。