java - When an anonymous class with no references to its enclosing class is returned from an instance method, it has a reference to this. Why? -
when anonymous class no references enclosing class returned instance method, has reference this. why?
consider following code:
package so; import java.lang.reflect.field; public class soexample { private static object getanonymousclassfromstaticcontext() { return new object() { }; } private object getanonymousclassfrominstancecontext() { return new object() { }; } public static void main(string[] args) throws nosuchfieldexception, securityexception { object anonymousclassfromstaticcontext = getanonymousclassfromstaticcontext(); object anonymousclassfrominstancecontext = new soexample().getanonymousclassfrominstancecontext(); field[] fieldsfromanonymousclassfromstaticcontext = anonymousclassfromstaticcontext.getclass().getdeclaredfields(); field[] fieldsfromanonymousclassfrominstancecontext = anonymousclassfrominstancecontext.getclass().getdeclaredfields(); system.out.println("number of fields static context: " + fieldsfromanonymousclassfromstaticcontext.length); system.out.println("number of fields instance context: " + fieldsfromanonymousclassfrominstancecontext.length); system.out.println("field instance context: " + fieldsfromanonymousclassfrominstancecontext[0]); } } this output:
number of fields static context: 0 number of fields instance context: 1 field instance context: final so.soexample so.soexample$2.this$0 each method, although seemingly calling same code, doing different. looks me instance method returning nested class, whereas static method returning static nested class (as static member, can't have reference this).
given fact there's no reference enclosing class, can't see benefit in this.
what's going on behind scenes?
there design principle behind anonymous / inner classes: each instance of inner class belongs instance of outer class.
leaving out reference inner class change behavior of garbage collection: way it's implemented, outer class can not garbage collected long inner class alive.
supports idea inner class can not exist without outer class.
applications might rely on behavior example creating temporary file , deleting in destructor. way, file deleted when inner classes gone.
this means current behavior can not changed changing might break existing applications.
so should mark inner classes static when don't need reference, because lead nice memory leaks.
edit: example of trying say (sorry terrible code quality):
class ideone { static object[] objects = new object[2]; public static void main (string[] args) throws java.lang.exception { m1(); m2(); system.gc(); } static void m1() { objects[0] = new foo().bar(); } static void m2() { objects[1] = new foo().baz(); } } class foo { static int = 0; int j = i++; public foo() { system.out.println("constructed: " + j); } object bar() { return new object() { }; } static object baz() { return new object() { }; } protected void finalize() throws throwable { system.out.println("garbage collected " + j); } } output:
constructed: 0
constructed: 1
garbage collected 1
as can see, first foo not garbage collected, because there still "inner instance" alive. behavior work, inner class needs reference.
of course, could implemented differently. say, keeping reference design decision made on purpose, "inner instance" not outlive parent.
btw: the java language reference states quite cryptically (there no exception inner classes not access outer class):
an instance of direct inner class c of class or interface o associated instance of o, known enclosing instance of i. enclosing instance of object, if any, determined when object created (§15.9.2).
Comments
Post a Comment