Just a general query that came about by someone accidentally giving a variable of one class a name that matched another class where both had a method of the same name, one of which was static.
Given the following:
public class A {
public static String dothis(String string){
return "Class";
}
public static String dothis(String string, String string2){
return "Class Method 2";
}
}
and this
public class B {
public String dothis(String string){
return "Object";
}
}
Is it that the following will always call the object and not the static method once the object is instantiated?
System.out.println(A.dothis("..."));//outputs Class
B A = new B();
System.out.println(A.dothis("..."));//outputs Object
N.b. following instantiation it appears to be impossible to call any static methods in class A, i.e.
B A = new B();
System.out.println(A.dothis("..."));
System.out.println(A.dothis("...","..."));//Won't compile
the above won't compile complaining about an erroneous tree type,
Edit: added specific exception :-
java.lang.RuntimeException: Uncompilable source code - Erroneous tree type: <any>
at testbed.....
... does this mean the compiler is effectively deciding which method to call, so a difference javac version may behave differently.
What is going on here and if this is guaranteed could it be used for obfuscation in some way, or would decompilation remove the name clash?
答案 0 :(得分:7)
After doing this:
B A = new B();
... the identifier A
refers to the variable, not the class.
To avoid that being a problem, just don't do that...
What is going on here and if this is guaranteed could it be used for obfuscation in some way, or would decompilation remove the name clash?
That entirely depends on the decompiler. If it's smart enough to recognize the issue, it could rename the local variable to one that doesn't clash.
答案 1 :(得分:2)
一个简单的名称可能出现在上下文中,它可能被解释为变量,类型或包的名称。在这些情况下,§6.5的规则指定将优先选择变量而不是类型,并且将优先选择类型而不是包。因此,有时可能无法通过其简单名称引用可见类型或包声明。我们说这样的声明是模糊的。
在您的示例中,A引用的是变量而不是类。如果A类在包内,您仍然可以使用以下方法访问静态方法:
com.apackage.A.doThis("");
答案 2 :(得分:0)
在你的代码中B A = new B()是B类的本地对象变量,A类被隐藏。
您有两个选择:
选项1:使用包名称(命名空间名称)
B A = new B();
System.out.println(A.dothis("..."));
System.out.println(Pack1.A.dothis("...","..."));//Class defined in Pack1 package .
选项1:重命名变量
B Renamobj = new B();
System.out.println(A.dothis("..."));
System.out.println(A.dothis("...","..."));