Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当涉及多态性时,如何确定JAVA类中使用的变量_Java_Dependencies_Polymorphism_Runtime - Fatal编程技术网

当涉及多态性时,如何确定JAVA类中使用的变量

当涉及多态性时,如何确定JAVA类中使用的变量,java,dependencies,polymorphism,runtime,Java,Dependencies,Polymorphism,Runtime,下面是一个场景。我有一个名为BaseClass的类和6个扩展该类的类:DerivedClass1到DerivedCLass6。比如说,基类有500个变量,而不是所有派生类[1..6]都需要这些变量。是的,这真的很糟糕,这就是我正在努力解决的问题。 问题在于,由于使用了多态性,在创建DerivedClass[1..6]的实例后,它被分配给基类引用。每个方法调用都发生在这个引用上。因此,“查找所有参考资料”并不是很有效。而且,代码库是巨大的 我需要弄清楚这6个派生类使用了哪些公共变量,并将它们保留在

下面是一个场景。我有一个名为BaseClass的类和6个扩展该类的类:DerivedClass1DerivedCLass6。比如说,基类有500个变量,而不是所有派生类[1..6]都需要这些变量。是的,这真的很糟糕,这就是我正在努力解决的问题。 问题在于,由于使用了多态性,在创建DerivedClass[1..6]的实例后,它被分配给基类引用。每个方法调用都发生在这个引用上。因此,“查找所有参考资料”并不是很有效。而且,代码库是巨大的

我需要弄清楚这6个派生类使用了哪些公共变量,并将它们保留在基类中,然后将其余的特定变量移动到它们各自的类中(按照最初的方式)

试图手动跟踪每个变量并找出控制流和逻辑是相当麻烦的。我希望有人有更好的主意

---更新---

我将用一个例子来解释

public class BaseClass{

    private String common1;
    ...
    private String common6;

    private String var1;
    ...
    private String var60;
    // getters and setters follow
}

public class DerivedClass1 extends BaseClass{

    private String _1a;
    private String _1b;
    ...
    //getters and setters
}

所有派生类都使用基类变量common1到common6

DerivedClass1使用var1到var10

DerivedClass2使用var11到var20

DerivedClass6使用var51到var60

我想做的是找出common1到common6,并将它们保留在基类中。 并将特定的派生类变量移动到各自的类中。这些是POJO的,所以除了getter和setter之外没有其他方法

使用这些对象的方式是创建特定的派生类对象并将其指定给基类引用。在基类引用上调用和方法。基类引用到处都在使用。在某些情况下,根据id从hashmap检索对象并将其分配给基类引用。即使我尝试遵循代码,我也不知道在该场景中使用的是什么类型的对象


我希望这是有意义的。

对于每个派生类:

javap -c Derived1.class >res
perl -n -e'/Field (.*):/ && print "$1\n"' <res | sort | uniq >derived1.list
$ doit.sh DerivedClass1 >out1
$ doit.sh DerivedClass2 >out2

$ cat out1
common1
common6
var1

$ cat out2
common1
common6
var60
这将为您提供基类中声明的字段列表

对于base.list中的每一行,您可以检查是否仅在一个派生的.list文件中看到它

编辑: 好啊我将把你的问题重新表述如下,希望它能抓住你的意思:

  • 基类声明了许多私有变量和访问器
  • 该类有许多子类,每个子类调用超类中的一些(但可能不是al)访问器
  • 这些子类由其他类实例化,并分配给基类类型的变量,调用可能引用超类访问器的方法
  • 对于每个派生类,您希望找到基类中声明的变量集,这些变量仅由此类派生类访问(通过访问器),因此您可以在派生类本身中移动这些变量

    首先,第3点是不相关的:知道派生类被其他类访问并没有帮助

    我将使用以下代码作为示例:

    class BaseClass{
    
        private String common1;
        private String common6;
    
        private String var1;
        private String var60;
    
        // getters and setters follow
        public String getCommon1() { return common1; }
        public String  getCommon6() { return common6; }
        public String getVar1() { return var1; }
        public String getVar60() { return var60; }
    
        public void setCommon1(String v) { common1 = v;}
        public void setCommon6(String v) { common6 = v;}
        public void setVar1(String v) { var1 = v;}
        public void setVar60(String v) { var60 = v;}
    
    }
    
    class DerivedClass1 extends BaseClass{
    
        private String _1a;
        private String _1b;
    
        //getters and setters
        public String get_1a() { return _1a; }
        public String get_1b() { return _1b; }
    
        public void foo() {
            setCommon1("val1");
            setCommon6("val6");
            setVar1("val1");
            System.out.println(getCommon1());
            System.out.println(getCommon6());
            System.out.println(getVar1());
            System.out.println(get_1a());
            System.out.println(get_1b());
        }
    }
    
    class DerivedClass2 extends BaseClass {
        //getters and setters
    
        public void foo() {
            setCommon1("val1");
            setCommon6("val6");
            setVar60("val60");
            System.out.println(getCommon1());
            System.out.println(getCommon6());
            System.out.println(getVar60());
        }
    }
    
    首先,让我们编写一个助手脚本:

    #!/bin/bash
    
    # find all variables accessed through accessors in the class
    # passed as argument. Stor ethe list in <class-name>.accessed
    # the names of vars are extracted from accessors invocations
    # by stripping the initial set or get and lowercasing the first
    # letter.
    javap -c $1.class >$1.tmp1
    perl -n -e'/Method [sg]et(.*):/ && print lcfirst("$1\n")' <$1.tmp1 | sort | uniq >$1.accessed
    
    # find all the variables declared in the class passed as argument
    javap -p $1.class >$1.tmp1
    grep -v "(" <$1.tmp1 | perl -n -e'/.* (.*);/ && print "$1\n"' >$1.declared
    
    # print only the variables which are accessed but do not appear in
    # the variable declared
    grep -x -v -f $1.declared $1.accessed
    
    因此,我们得到了每个派生类的变量列表,这些变量通过在基类中声明的访问器访问

    您可以通过以下方式查找两个文件中出现的变量:

    $ grep -x -f out1 out2 
    common1
    common6
    

    这些是必须留在基类中的变量。

    对于每个派生类:

    javap -c Derived1.class >res
    perl -n -e'/Field (.*):/ && print "$1\n"' <res | sort | uniq >derived1.list
    
    $ doit.sh DerivedClass1 >out1
    $ doit.sh DerivedClass2 >out2
    
    $ cat out1
    common1
    common6
    var1
    
    $ cat out2
    common1
    common6
    var60
    
    这将为您提供基类中声明的字段列表

    对于base.list中的每一行,您可以检查是否仅在一个派生的.list文件中看到它

    编辑: 好啊我将把你的问题重新表述如下,希望它能抓住你的意思:

  • 基类声明了许多私有变量和访问器
  • 该类有许多子类,每个子类调用超类中的一些(但可能不是al)访问器
  • 这些子类由其他类实例化,并分配给基类类型的变量,调用可能引用超类访问器的方法
  • 对于每个派生类,您希望找到基类中声明的变量集,这些变量仅由此类派生类访问(通过访问器),因此您可以在派生类本身中移动这些变量

    首先,第3点是不相关的:知道派生类被其他类访问并没有帮助

    我将使用以下代码作为示例:

    class BaseClass{
    
        private String common1;
        private String common6;
    
        private String var1;
        private String var60;
    
        // getters and setters follow
        public String getCommon1() { return common1; }
        public String  getCommon6() { return common6; }
        public String getVar1() { return var1; }
        public String getVar60() { return var60; }
    
        public void setCommon1(String v) { common1 = v;}
        public void setCommon6(String v) { common6 = v;}
        public void setVar1(String v) { var1 = v;}
        public void setVar60(String v) { var60 = v;}
    
    }
    
    class DerivedClass1 extends BaseClass{
    
        private String _1a;
        private String _1b;
    
        //getters and setters
        public String get_1a() { return _1a; }
        public String get_1b() { return _1b; }
    
        public void foo() {
            setCommon1("val1");
            setCommon6("val6");
            setVar1("val1");
            System.out.println(getCommon1());
            System.out.println(getCommon6());
            System.out.println(getVar1());
            System.out.println(get_1a());
            System.out.println(get_1b());
        }
    }
    
    class DerivedClass2 extends BaseClass {
        //getters and setters
    
        public void foo() {
            setCommon1("val1");
            setCommon6("val6");
            setVar60("val60");
            System.out.println(getCommon1());
            System.out.println(getCommon6());
            System.out.println(getVar60());
        }
    }
    
    首先,让我们编写一个助手脚本:

    #!/bin/bash
    
    # find all variables accessed through accessors in the class
    # passed as argument. Stor ethe list in <class-name>.accessed
    # the names of vars are extracted from accessors invocations
    # by stripping the initial set or get and lowercasing the first
    # letter.
    javap -c $1.class >$1.tmp1
    perl -n -e'/Method [sg]et(.*):/ && print lcfirst("$1\n")' <$1.tmp1 | sort | uniq >$1.accessed
    
    # find all the variables declared in the class passed as argument
    javap -p $1.class >$1.tmp1
    grep -v "(" <$1.tmp1 | perl -n -e'/.* (.*);/ && print "$1\n"' >$1.declared
    
    # print only the variables which are accessed but do not appear in
    # the variable declared
    grep -x -v -f $1.declared $1.accessed
    
    因此,我们得到了每个派生类的变量列表,这些变量通过在基类中声明的访问器访问

    您可以通过以下方式查找两个文件中出现的变量:

    $ grep -x -f out1 out2 
    common1
    common6
    

    这些是必须留在基类中的变量。

    我认为您将需要自动化和人工的混合。这里有一种方法:

    首先,获取
    BaseClass
    中所有变量的列表。希望它们的声明是类似的,并且在一大块中:

    class BaseClass {
        protected int myInt;
        protected String myString = "default value";
        protected double myDouble;
        ...
    
    如果是这样的话,您可以将它们全部复制到vim/emacs/随便什么文件中,然后执行一些正则表达式抛出来获得名称。例如,如果它们都是
    [=something],然后您可以在vim中运行
    :%s/*\w\+\w\+\(\w\+\)./\1/

    现在,给定一个名称,我们希望找到所有使用它的
    .java
    文件。这可能会产生一些误报,但希望不会太多。这很简单:

    $ JAVA_FILES='First.java Second.java path/to/Third.java'
    $ NEEDLE="myInt"
    $ grep -l "\b${NEEDLE}\b" $JAVA_FILES | sort
    
    注二:

    • \b
      位查找单词边界——因此上面的值将匹配
      myInt=1
      intfoo=myInt
      int len=myString.length(),但不是
      myInteger=123
      sammyInt`
    • $JAVA_FILES
      在最后一行中没有引号,因为您希望bash将这些文件展开为单独的文件(而不是将它们视为名称中带有空格的文件)。这应该没问题