I found a scenario where java program behaves differently after renaming a variable. I understand this isn't actually code that anyone would use but if someone knows whats going on it would be nice to have an explanation. I tried this with java 1.6 on Eclipse Kepler.
package _test;
public class TestClass{
public static void main(String...args){
Object testClazz$1 = new Object (){
public String toString() {
return "hello";
}
};
TestClass$1 test = new TestClass$1();
System.out.println(testClazz$1.toString());
test.doStuff();
}
}
class TestClass$1{
public void doStuff(){
System.out.println("hello2");
}
}
This outputs:
hello
Exception in thread "main" java.lang.NoSuchMethodError: _test.TestClass$1.doStuff()V at _test.TestClass.main(TestClass.java:13)
As far as I understand the compiler creates a TestClass$1.class file for the testClazz$1 object and this causes a naming collision.
But after renaming the object to testClass$1:
package _test;
public class TestClass{
public static void main(String...args){
Object testClass$1 = new Object (){
public String toString() {
return "hello";
}
};
TestClass$1 test = new TestClass$1();
System.out.println(testClass$1.toString());
test.doStuff();
}
}
class TestClass$1{
public void doStuff(){
System.out.println("hello2");
}
}
The output is:
_test.TestClass$1@2e6e1408
hello2
Any ideas what is going on here?
No, a variable name can't be changed.
You cannot rename variables in runtime.
Highlight and right click on the variable you want to rename. Navigate to Refactor and select Rename.... Type in your new variable name and press Enter.
Anonymous classes are named automatically by appending a $
sign and an increasing number to the name of the enclosing class.
In your first example the anoymous class will be named TestClass$1
which has no doStuff()
method, you only override toString()
that's why you get NoSuchMethodError
error.
In your 2nd example you already have a local variable named TestClass$1
, so the auto-generated name chosen by the compiler will be a different name, most likely TestClass$2
. Since you instantiate TestClass$1
which is not an anonymous class but a class explicitly defined by you, that will be instantiated which has a doStuff()
method which properly prints "hello2"
and which does not override Object.toString()
so printing the value returned by its toString()
method will print the default value as specified in java.lang.Ojbect
(which is the class name appended with a @
sign followed by the default hash code in hexadecimal format).
Conclusion: While this is an interesting example, you should never use the $
sign in your class names and in identifier names.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With