当涉及多态性时,如何确定JAVA类中使用的变量
下面是一个场景。我有一个名为BaseClass的类和6个扩展该类的类:DerivedClass1到DerivedCLass6。比如说,基类有500个变量,而不是所有派生类[1..6]都需要这些变量。是的,这真的很糟糕,这就是我正在努力解决的问题。 问题在于,由于使用了多态性,在创建DerivedClass[1..6]的实例后,它被分配给基类引用。每个方法调用都发生在这个引用上。因此,“查找所有参考资料”并不是很有效。而且,代码库是巨大的 我需要弄清楚这6个派生类使用了哪些公共变量,并将它们保留在基类中,然后将其余的特定变量移动到它们各自的类中(按照最初的方式) 试图手动跟踪每个变量并找出控制流和逻辑是相当麻烦的。我希望有人有更好的主意 ---更新--- 我将用一个例子来解释当涉及多态性时,如何确定JAVA类中使用的变量,java,dependencies,polymorphism,runtime,Java,Dependencies,Polymorphism,Runtime,下面是一个场景。我有一个名为BaseClass的类和6个扩展该类的类:DerivedClass1到DerivedCLass6。比如说,基类有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文件中看到它
编辑:
好啊我将把你的问题重新表述如下,希望它能抓住你的意思:
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文件中看到它
编辑:
好啊我将把你的问题重新表述如下,希望它能抓住你的意思:
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将这些文件展开为单独的文件(而不是将它们视为名称中带有空格的文件)。这应该没问题