【问题标题】:How to lists all variables in java classes which are mutable in that class如何列出该类中可变的Java类中的所有变量
【发布时间】:2020-05-12 10:03:44
【问题描述】:

我有一个大约 200 个 Java 类的列表。我需要准备一个变量列表(特别是静态的和非最终的),其值在 Java 类中被修改/变异。为了准备所有静态和非最终变量的列表,我使用了反射。

但我不确定如何检查类中的每个变量是否都发生了变异,而无需手动打开每个文件。

class ClassVO{
    private static final String name;
    private String fieldName;
    private static double single=0.01;
    private static double value;

   void calculate(){
     value = value*0.25;
   }
}

在上面的示例中,需要返回“值”变量。 是否有任何可用的工具可用于完成此类工作?请分享。

【问题讨论】:

  • 听起来是一项乏味的任务。考虑到即使一个字段是最终的,它也可以被改变。例如,添加/删除元素时的最终集合。所以除了修饰符,你应该检查每个实例是否不可变。
  • @Ezequiel,即使集合本身不允许添加、设置或删除,元素也可以是可变的。
  • 那么,这是否意味着我必须手动完成。因为这些文件列表很大,我在想一些像 PMD 这样的工具可以解决它,但不确定它的用途。
  • @Chabukswar 我添加了一个答案希望对你有所帮助
  • @Ezequiel 我提供了一个锻炼示例,你可以看看吗?

标签: java static


【解决方案1】:

要做到这一点很难,我使用了可以加载 JavaClass 文件的 Apache bcel 库。
bcel-6.0.jar 示例输入类:-

public class Test {
    private static final String name = "";
    private String fieldName;
    private static String  single = "notMutable";
    private static double value;
    private String random;

    public void print(){
        value = value*0.25;
        fieldName = "foo";
        String sample =single+"1";
    }
}

检查方法中变量(静态/实例)引用的代码

import java.util.ArrayList;
import java.util.List;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;

public class Sample {
    public static void main(String[] args) {
        try {
            List<String> usedVariables = new ArrayList<String>();
            JavaClass  javaClass =  Repository.lookupClass(Test.class);
            for(Method m: javaClass.getMethods()) {
                String code = m.getCode().toString();
                String[] codes = code.split("\\r?\\n");
                if(!m.getName().matches("<clinit>|<init>")) {
                    for(String c: codes) {
                        if(c.contains(javaClass.getClassName()+".") && (c.contains("putstatic") || c.contains("putfield"))) {
                            System.out.println("Class static/Instant mutable variable Used inside method @ --> "+c);
                            String variableName = c.substring(c.indexOf(javaClass.getClassName()));
                            usedVariables.add(variableName.split(":")[0]);
                        }
                    }
                }
            }
            System.out.println("Result --> " +usedVariables);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

输出

Class static/Instant mutable variable Used inside method @ --> 7:    putstatic      Test.value:D (30)
Class static/Instant mutable variable Used inside method @ --> 13:   putfield       Test.fieldName:Ljava/lang/String; (36)
Result --> [Test.value, Test.fieldName]

虽然在方法 print 内部使用了静态变量值和单个变量,但变量 single 的值没有改变,而 value 改变了
因此仅输出显示可变字段即。

Result --> [Test.value, Test.fieldName]

【讨论】:

  • 它对我有用。谢谢!!我可以参考这段代码。我不知道 Apache bcel 库。
  • @Chabukswar 如果你觉得这个答案对你有帮助,你也可以投票。
猜你喜欢
  • 2023-04-07
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
  • 2010-12-18
相关资源
最近更新 更多