Are all final variables captured by anonymous classes?











up vote
14
down vote

favorite
3












I thought I knew the answer to this, but I can't find any confirmation after an hour or so of searching.



In this code:



public class Outer {

// other code

private void method1() {
final SomeObject obj1 = new SomeObject(...);
final SomeObject obj2 = new SomeObject(...);
someManager.registerCallback(new SomeCallbackClass() {
@Override
public void onEvent() {
System.out.println(obj1.getName());
}
});
}
}


Assume that registerCallback saves its parameter somewhere, so that the object of the anonymous subclass will live for a while. Obviously this object has to maintain a reference to obj1 so that onEvent will work if it is called.



But given that the object doesn't use obj2, does it still maintain a reference to obj2, so that obj2 can't be garbage-collected while the object lives? I was under the impression that all visible final (or effectively final) local variables and parameters were captured and thus couldn't be GC'ed as long as the object was alive, but I can't find anything that says one way or the other.



Is it implementation-dependent?



Is there a section in the JLS that answers this? I wasn't able to find the answer there.










share|improve this question






















  • How do you know that obj2 is bound to callback$x? You have seen it in bytecode?
    – Antoniossss
    yesterday






  • 1




    "Is it implementation-dependent?" Technically, yes. There is no reason for the anonymous class to capture obj2, but there is no reason it can't.
    – Andy Turner
    yesterday










  • I think a good reason it would not capture obj2 as a matter of course is that you can have multiple anonymous classes declared in a method: one of those classes might refer to obj1 only, whilst another might refer to obj2 only. It wouldn't be sensible for both classes to capture both variables.
    – Andy Turner
    yesterday












  • You can check this using reflection or a debugger.
    – Peter Lawrey
    yesterday















up vote
14
down vote

favorite
3












I thought I knew the answer to this, but I can't find any confirmation after an hour or so of searching.



In this code:



public class Outer {

// other code

private void method1() {
final SomeObject obj1 = new SomeObject(...);
final SomeObject obj2 = new SomeObject(...);
someManager.registerCallback(new SomeCallbackClass() {
@Override
public void onEvent() {
System.out.println(obj1.getName());
}
});
}
}


Assume that registerCallback saves its parameter somewhere, so that the object of the anonymous subclass will live for a while. Obviously this object has to maintain a reference to obj1 so that onEvent will work if it is called.



But given that the object doesn't use obj2, does it still maintain a reference to obj2, so that obj2 can't be garbage-collected while the object lives? I was under the impression that all visible final (or effectively final) local variables and parameters were captured and thus couldn't be GC'ed as long as the object was alive, but I can't find anything that says one way or the other.



Is it implementation-dependent?



Is there a section in the JLS that answers this? I wasn't able to find the answer there.










share|improve this question






















  • How do you know that obj2 is bound to callback$x? You have seen it in bytecode?
    – Antoniossss
    yesterday






  • 1




    "Is it implementation-dependent?" Technically, yes. There is no reason for the anonymous class to capture obj2, but there is no reason it can't.
    – Andy Turner
    yesterday










  • I think a good reason it would not capture obj2 as a matter of course is that you can have multiple anonymous classes declared in a method: one of those classes might refer to obj1 only, whilst another might refer to obj2 only. It wouldn't be sensible for both classes to capture both variables.
    – Andy Turner
    yesterday












  • You can check this using reflection or a debugger.
    – Peter Lawrey
    yesterday













up vote
14
down vote

favorite
3









up vote
14
down vote

favorite
3






3





I thought I knew the answer to this, but I can't find any confirmation after an hour or so of searching.



In this code:



public class Outer {

// other code

private void method1() {
final SomeObject obj1 = new SomeObject(...);
final SomeObject obj2 = new SomeObject(...);
someManager.registerCallback(new SomeCallbackClass() {
@Override
public void onEvent() {
System.out.println(obj1.getName());
}
});
}
}


Assume that registerCallback saves its parameter somewhere, so that the object of the anonymous subclass will live for a while. Obviously this object has to maintain a reference to obj1 so that onEvent will work if it is called.



But given that the object doesn't use obj2, does it still maintain a reference to obj2, so that obj2 can't be garbage-collected while the object lives? I was under the impression that all visible final (or effectively final) local variables and parameters were captured and thus couldn't be GC'ed as long as the object was alive, but I can't find anything that says one way or the other.



Is it implementation-dependent?



Is there a section in the JLS that answers this? I wasn't able to find the answer there.










share|improve this question













I thought I knew the answer to this, but I can't find any confirmation after an hour or so of searching.



In this code:



public class Outer {

// other code

private void method1() {
final SomeObject obj1 = new SomeObject(...);
final SomeObject obj2 = new SomeObject(...);
someManager.registerCallback(new SomeCallbackClass() {
@Override
public void onEvent() {
System.out.println(obj1.getName());
}
});
}
}


Assume that registerCallback saves its parameter somewhere, so that the object of the anonymous subclass will live for a while. Obviously this object has to maintain a reference to obj1 so that onEvent will work if it is called.



But given that the object doesn't use obj2, does it still maintain a reference to obj2, so that obj2 can't be garbage-collected while the object lives? I was under the impression that all visible final (or effectively final) local variables and parameters were captured and thus couldn't be GC'ed as long as the object was alive, but I can't find anything that says one way or the other.



Is it implementation-dependent?



Is there a section in the JLS that answers this? I wasn't able to find the answer there.







java anonymous-class






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









ajb

26.6k33258




26.6k33258












  • How do you know that obj2 is bound to callback$x? You have seen it in bytecode?
    – Antoniossss
    yesterday






  • 1




    "Is it implementation-dependent?" Technically, yes. There is no reason for the anonymous class to capture obj2, but there is no reason it can't.
    – Andy Turner
    yesterday










  • I think a good reason it would not capture obj2 as a matter of course is that you can have multiple anonymous classes declared in a method: one of those classes might refer to obj1 only, whilst another might refer to obj2 only. It wouldn't be sensible for both classes to capture both variables.
    – Andy Turner
    yesterday












  • You can check this using reflection or a debugger.
    – Peter Lawrey
    yesterday


















  • How do you know that obj2 is bound to callback$x? You have seen it in bytecode?
    – Antoniossss
    yesterday






  • 1




    "Is it implementation-dependent?" Technically, yes. There is no reason for the anonymous class to capture obj2, but there is no reason it can't.
    – Andy Turner
    yesterday










  • I think a good reason it would not capture obj2 as a matter of course is that you can have multiple anonymous classes declared in a method: one of those classes might refer to obj1 only, whilst another might refer to obj2 only. It wouldn't be sensible for both classes to capture both variables.
    – Andy Turner
    yesterday












  • You can check this using reflection or a debugger.
    – Peter Lawrey
    yesterday
















How do you know that obj2 is bound to callback$x? You have seen it in bytecode?
– Antoniossss
yesterday




How do you know that obj2 is bound to callback$x? You have seen it in bytecode?
– Antoniossss
yesterday




1




1




"Is it implementation-dependent?" Technically, yes. There is no reason for the anonymous class to capture obj2, but there is no reason it can't.
– Andy Turner
yesterday




"Is it implementation-dependent?" Technically, yes. There is no reason for the anonymous class to capture obj2, but there is no reason it can't.
– Andy Turner
yesterday












I think a good reason it would not capture obj2 as a matter of course is that you can have multiple anonymous classes declared in a method: one of those classes might refer to obj1 only, whilst another might refer to obj2 only. It wouldn't be sensible for both classes to capture both variables.
– Andy Turner
yesterday






I think a good reason it would not capture obj2 as a matter of course is that you can have multiple anonymous classes declared in a method: one of those classes might refer to obj1 only, whilst another might refer to obj2 only. It wouldn't be sensible for both classes to capture both variables.
– Andy Turner
yesterday














You can check this using reflection or a debugger.
– Peter Lawrey
yesterday




You can check this using reflection or a debugger.
– Peter Lawrey
yesterday












4 Answers
4






active

oldest

votes

















up vote
8
down vote



accepted










The language spec has very little to say about how anonymous classes should capture variables from their enclosing scope.



The only especially relevant section of the language spec that I can find is JLS Sec 8.1.3:




Any local variable, formal parameter, or exception parameter used but not declared in an inner class must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.)




(Anonymous classes are inner classes)



It does not specify anything about which variables the anonymous class should capture, or how that capturing should be implemented.



I think it is reasonable to infer from this that implementations need not capture variables that aren't referenced in the inner class; but it doesn't say they can't.






share|improve this answer






























    up vote
    9
    down vote













    Only obj1 is captured.



    Logically, the anonymous class is implemented as a normal class something like this:



    class Anonymous1 extends SomeCallbackClass {
    private final Outer _outer;
    private final SomeObject obj1;
    Anonymous1(Outer _outer, SomeObject obj1) {
    this._outer = _outer;
    this.obj1 = obj1;
    }
    @Override
    public void onEvent() {
    System.out.println(this.obj1.getName());
    }
    });


    Note that an anonymous class is always an inner class, so it will always maintain a reference to the outer class, even if it doesn't need it. I don't know if later versions of the compiler have optimized that away, but I don't think so. It is a potential cause of memory leaks.



    The use of it becomes:



    someManager.registerCallback(new Anonymous1(this, obj1));


    As you can see, the reference value of obj1 is copied (pass-by-value).



    There is technically no reason for obj1 to be final, whether declared final or effectively final (Java 8+), except that if it wasn't and you change the value, the copy wouldn't change, causing bugs because you expected the value to change, given that the copying is a hidden action. To prevent programmer confusion, they decided that obj1 must be final, so you can never become confused about that behavior.






    share|improve this answer



















    • 2




      Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
      – Boris the Spider
      yesterday










    • it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
      – Carlos Heuberger
      yesterday








    • 3




      Note this of the enclosing instance is also captured whether it is used or not.
      – Peter Lawrey
      yesterday










    • @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
      – Andreas
      yesterday










    • @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
      – Andreas
      yesterday


















    up vote
    1
    down vote













    I was curious and surprised by your statement that much (why would compiler do such thing???), that I had to check it myself. So I made simple example like this



    public class test {
    private static Object holder;

    private void method1() {
    final Object obj1 = new Object();
    final Object obj2 = new Object();
    holder = new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    System.out.println(obj1);
    }
    };
    }
    }


    And resulted with following bytecode for of method1



     private method1()V
    L0
    LINENUMBER 8 L0
    NEW java/lang/Object
    DUP
    INVOKESPECIAL java/lang/Object.<init> ()V
    ASTORE 1
    L1
    LINENUMBER 9 L1
    NEW java/lang/Object
    DUP
    INVOKESPECIAL java/lang/Object.<init> ()V
    ASTORE 2
    L2
    LINENUMBER 10 L2
    NEW test$1
    DUP
    ALOAD 0
    ALOAD 1
    INVOKESPECIAL test$1.<init> (Ltest;Ljava/lang/Object;)V
    PUTSTATIC test.holder : Ljava/lang/Object;


    Which means:




    • L0 - store first final with idx 1 (ASTORE 1)

    • L1 - store second final with idx 2(that one is not used in anon class) (ASTORE 2)

    • L2 - create new test$1 with argumets (ALOAD 0) this and obj1 (ALOAD 1)


    So I have no idea, how did you get to the conclusion that obj2 is passed to anonymous class instance, but it was simply wrong. IDK if it is compiler dependent, but as for what other has stated, it is not impossible.






    share|improve this answer





















    • To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
      – ajb
      yesterday


















    up vote
    0
    down vote













    obj2 will be garbage collected since it has no reference to it. obj1 will not be garbage collected as long as the event is active since even if you created an anonymous class, you've created a direct reference to obj1.



    The only thing final does is that you can't re-define the value, it doesn't protect the object from the garbage collector






    share|improve this answer



















    • 1




      If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
      – Rab
      yesterday










    • OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
      – Antoniossss
      yesterday












    • I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
      – Nertan Lucian
      yesterday






    • 1




      You are missing the point and if you answered base on title, it is still off topic IMHO.
      – Antoniossss
      yesterday













    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53203529%2fare-all-final-variables-captured-by-anonymous-classes%23new-answer', 'question_page');
    }
    );

    Post as a guest
































    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    8
    down vote



    accepted










    The language spec has very little to say about how anonymous classes should capture variables from their enclosing scope.



    The only especially relevant section of the language spec that I can find is JLS Sec 8.1.3:




    Any local variable, formal parameter, or exception parameter used but not declared in an inner class must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.)




    (Anonymous classes are inner classes)



    It does not specify anything about which variables the anonymous class should capture, or how that capturing should be implemented.



    I think it is reasonable to infer from this that implementations need not capture variables that aren't referenced in the inner class; but it doesn't say they can't.






    share|improve this answer



























      up vote
      8
      down vote



      accepted










      The language spec has very little to say about how anonymous classes should capture variables from their enclosing scope.



      The only especially relevant section of the language spec that I can find is JLS Sec 8.1.3:




      Any local variable, formal parameter, or exception parameter used but not declared in an inner class must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.)




      (Anonymous classes are inner classes)



      It does not specify anything about which variables the anonymous class should capture, or how that capturing should be implemented.



      I think it is reasonable to infer from this that implementations need not capture variables that aren't referenced in the inner class; but it doesn't say they can't.






      share|improve this answer

























        up vote
        8
        down vote



        accepted







        up vote
        8
        down vote



        accepted






        The language spec has very little to say about how anonymous classes should capture variables from their enclosing scope.



        The only especially relevant section of the language spec that I can find is JLS Sec 8.1.3:




        Any local variable, formal parameter, or exception parameter used but not declared in an inner class must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.)




        (Anonymous classes are inner classes)



        It does not specify anything about which variables the anonymous class should capture, or how that capturing should be implemented.



        I think it is reasonable to infer from this that implementations need not capture variables that aren't referenced in the inner class; but it doesn't say they can't.






        share|improve this answer














        The language spec has very little to say about how anonymous classes should capture variables from their enclosing scope.



        The only especially relevant section of the language spec that I can find is JLS Sec 8.1.3:




        Any local variable, formal parameter, or exception parameter used but not declared in an inner class must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.)




        (Anonymous classes are inner classes)



        It does not specify anything about which variables the anonymous class should capture, or how that capturing should be implemented.



        I think it is reasonable to infer from this that implementations need not capture variables that aren't referenced in the inner class; but it doesn't say they can't.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday

























        answered yesterday









        Andy Turner

        77.6k877125




        77.6k877125
























            up vote
            9
            down vote













            Only obj1 is captured.



            Logically, the anonymous class is implemented as a normal class something like this:



            class Anonymous1 extends SomeCallbackClass {
            private final Outer _outer;
            private final SomeObject obj1;
            Anonymous1(Outer _outer, SomeObject obj1) {
            this._outer = _outer;
            this.obj1 = obj1;
            }
            @Override
            public void onEvent() {
            System.out.println(this.obj1.getName());
            }
            });


            Note that an anonymous class is always an inner class, so it will always maintain a reference to the outer class, even if it doesn't need it. I don't know if later versions of the compiler have optimized that away, but I don't think so. It is a potential cause of memory leaks.



            The use of it becomes:



            someManager.registerCallback(new Anonymous1(this, obj1));


            As you can see, the reference value of obj1 is copied (pass-by-value).



            There is technically no reason for obj1 to be final, whether declared final or effectively final (Java 8+), except that if it wasn't and you change the value, the copy wouldn't change, causing bugs because you expected the value to change, given that the copying is a hidden action. To prevent programmer confusion, they decided that obj1 must be final, so you can never become confused about that behavior.






            share|improve this answer



















            • 2




              Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
              – Boris the Spider
              yesterday










            • it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
              – Carlos Heuberger
              yesterday








            • 3




              Note this of the enclosing instance is also captured whether it is used or not.
              – Peter Lawrey
              yesterday










            • @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
              – Andreas
              yesterday










            • @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
              – Andreas
              yesterday















            up vote
            9
            down vote













            Only obj1 is captured.



            Logically, the anonymous class is implemented as a normal class something like this:



            class Anonymous1 extends SomeCallbackClass {
            private final Outer _outer;
            private final SomeObject obj1;
            Anonymous1(Outer _outer, SomeObject obj1) {
            this._outer = _outer;
            this.obj1 = obj1;
            }
            @Override
            public void onEvent() {
            System.out.println(this.obj1.getName());
            }
            });


            Note that an anonymous class is always an inner class, so it will always maintain a reference to the outer class, even if it doesn't need it. I don't know if later versions of the compiler have optimized that away, but I don't think so. It is a potential cause of memory leaks.



            The use of it becomes:



            someManager.registerCallback(new Anonymous1(this, obj1));


            As you can see, the reference value of obj1 is copied (pass-by-value).



            There is technically no reason for obj1 to be final, whether declared final or effectively final (Java 8+), except that if it wasn't and you change the value, the copy wouldn't change, causing bugs because you expected the value to change, given that the copying is a hidden action. To prevent programmer confusion, they decided that obj1 must be final, so you can never become confused about that behavior.






            share|improve this answer



















            • 2




              Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
              – Boris the Spider
              yesterday










            • it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
              – Carlos Heuberger
              yesterday








            • 3




              Note this of the enclosing instance is also captured whether it is used or not.
              – Peter Lawrey
              yesterday










            • @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
              – Andreas
              yesterday










            • @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
              – Andreas
              yesterday













            up vote
            9
            down vote










            up vote
            9
            down vote









            Only obj1 is captured.



            Logically, the anonymous class is implemented as a normal class something like this:



            class Anonymous1 extends SomeCallbackClass {
            private final Outer _outer;
            private final SomeObject obj1;
            Anonymous1(Outer _outer, SomeObject obj1) {
            this._outer = _outer;
            this.obj1 = obj1;
            }
            @Override
            public void onEvent() {
            System.out.println(this.obj1.getName());
            }
            });


            Note that an anonymous class is always an inner class, so it will always maintain a reference to the outer class, even if it doesn't need it. I don't know if later versions of the compiler have optimized that away, but I don't think so. It is a potential cause of memory leaks.



            The use of it becomes:



            someManager.registerCallback(new Anonymous1(this, obj1));


            As you can see, the reference value of obj1 is copied (pass-by-value).



            There is technically no reason for obj1 to be final, whether declared final or effectively final (Java 8+), except that if it wasn't and you change the value, the copy wouldn't change, causing bugs because you expected the value to change, given that the copying is a hidden action. To prevent programmer confusion, they decided that obj1 must be final, so you can never become confused about that behavior.






            share|improve this answer














            Only obj1 is captured.



            Logically, the anonymous class is implemented as a normal class something like this:



            class Anonymous1 extends SomeCallbackClass {
            private final Outer _outer;
            private final SomeObject obj1;
            Anonymous1(Outer _outer, SomeObject obj1) {
            this._outer = _outer;
            this.obj1 = obj1;
            }
            @Override
            public void onEvent() {
            System.out.println(this.obj1.getName());
            }
            });


            Note that an anonymous class is always an inner class, so it will always maintain a reference to the outer class, even if it doesn't need it. I don't know if later versions of the compiler have optimized that away, but I don't think so. It is a potential cause of memory leaks.



            The use of it becomes:



            someManager.registerCallback(new Anonymous1(this, obj1));


            As you can see, the reference value of obj1 is copied (pass-by-value).



            There is technically no reason for obj1 to be final, whether declared final or effectively final (Java 8+), except that if it wasn't and you change the value, the copy wouldn't change, causing bugs because you expected the value to change, given that the copying is a hidden action. To prevent programmer confusion, they decided that obj1 must be final, so you can never become confused about that behavior.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            Andreas

            72.5k454116




            72.5k454116








            • 2




              Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
              – Boris the Spider
              yesterday










            • it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
              – Carlos Heuberger
              yesterday








            • 3




              Note this of the enclosing instance is also captured whether it is used or not.
              – Peter Lawrey
              yesterday










            • @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
              – Andreas
              yesterday










            • @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
              – Andreas
              yesterday














            • 2




              Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
              – Boris the Spider
              yesterday










            • it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
              – Carlos Heuberger
              yesterday








            • 3




              Note this of the enclosing instance is also captured whether it is used or not.
              – Peter Lawrey
              yesterday










            • @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
              – Andreas
              yesterday










            • @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
              – Andreas
              yesterday








            2




            2




            Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
            – Boris the Spider
            yesterday




            Worth mentioning that since Java 8 the restriction on having to explicitly declare final has been lifted. The JLS now talks about "effectively final" variables.
            – Boris the Spider
            yesterday












            it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
            – Carlos Heuberger
            yesterday






            it is not only logically, it is almost exactly that what the compiler does (Java 8 and 11), just the fields are named differently [:-)
            – Carlos Heuberger
            yesterday






            3




            3




            Note this of the enclosing instance is also captured whether it is used or not.
            – Peter Lawrey
            yesterday




            Note this of the enclosing instance is also captured whether it is used or not.
            – Peter Lawrey
            yesterday












            @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
            – Andreas
            yesterday




            @PeterLawrey Already covered in the answer (_outer), as explained in the note below the class.
            – Andreas
            yesterday












            @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
            – Andreas
            yesterday




            @CarlosHeuberger And the class itself is named differently, using a name that is not allowed by Java syntax (e.g. Outer$1).
            – Andreas
            yesterday










            up vote
            1
            down vote













            I was curious and surprised by your statement that much (why would compiler do such thing???), that I had to check it myself. So I made simple example like this



            public class test {
            private static Object holder;

            private void method1() {
            final Object obj1 = new Object();
            final Object obj2 = new Object();
            holder = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            System.out.println(obj1);
            }
            };
            }
            }


            And resulted with following bytecode for of method1



             private method1()V
            L0
            LINENUMBER 8 L0
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 1
            L1
            LINENUMBER 9 L1
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 2
            L2
            LINENUMBER 10 L2
            NEW test$1
            DUP
            ALOAD 0
            ALOAD 1
            INVOKESPECIAL test$1.<init> (Ltest;Ljava/lang/Object;)V
            PUTSTATIC test.holder : Ljava/lang/Object;


            Which means:




            • L0 - store first final with idx 1 (ASTORE 1)

            • L1 - store second final with idx 2(that one is not used in anon class) (ASTORE 2)

            • L2 - create new test$1 with argumets (ALOAD 0) this and obj1 (ALOAD 1)


            So I have no idea, how did you get to the conclusion that obj2 is passed to anonymous class instance, but it was simply wrong. IDK if it is compiler dependent, but as for what other has stated, it is not impossible.






            share|improve this answer





















            • To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
              – ajb
              yesterday















            up vote
            1
            down vote













            I was curious and surprised by your statement that much (why would compiler do such thing???), that I had to check it myself. So I made simple example like this



            public class test {
            private static Object holder;

            private void method1() {
            final Object obj1 = new Object();
            final Object obj2 = new Object();
            holder = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            System.out.println(obj1);
            }
            };
            }
            }


            And resulted with following bytecode for of method1



             private method1()V
            L0
            LINENUMBER 8 L0
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 1
            L1
            LINENUMBER 9 L1
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 2
            L2
            LINENUMBER 10 L2
            NEW test$1
            DUP
            ALOAD 0
            ALOAD 1
            INVOKESPECIAL test$1.<init> (Ltest;Ljava/lang/Object;)V
            PUTSTATIC test.holder : Ljava/lang/Object;


            Which means:




            • L0 - store first final with idx 1 (ASTORE 1)

            • L1 - store second final with idx 2(that one is not used in anon class) (ASTORE 2)

            • L2 - create new test$1 with argumets (ALOAD 0) this and obj1 (ALOAD 1)


            So I have no idea, how did you get to the conclusion that obj2 is passed to anonymous class instance, but it was simply wrong. IDK if it is compiler dependent, but as for what other has stated, it is not impossible.






            share|improve this answer





















            • To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
              – ajb
              yesterday













            up vote
            1
            down vote










            up vote
            1
            down vote









            I was curious and surprised by your statement that much (why would compiler do such thing???), that I had to check it myself. So I made simple example like this



            public class test {
            private static Object holder;

            private void method1() {
            final Object obj1 = new Object();
            final Object obj2 = new Object();
            holder = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            System.out.println(obj1);
            }
            };
            }
            }


            And resulted with following bytecode for of method1



             private method1()V
            L0
            LINENUMBER 8 L0
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 1
            L1
            LINENUMBER 9 L1
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 2
            L2
            LINENUMBER 10 L2
            NEW test$1
            DUP
            ALOAD 0
            ALOAD 1
            INVOKESPECIAL test$1.<init> (Ltest;Ljava/lang/Object;)V
            PUTSTATIC test.holder : Ljava/lang/Object;


            Which means:




            • L0 - store first final with idx 1 (ASTORE 1)

            • L1 - store second final with idx 2(that one is not used in anon class) (ASTORE 2)

            • L2 - create new test$1 with argumets (ALOAD 0) this and obj1 (ALOAD 1)


            So I have no idea, how did you get to the conclusion that obj2 is passed to anonymous class instance, but it was simply wrong. IDK if it is compiler dependent, but as for what other has stated, it is not impossible.






            share|improve this answer












            I was curious and surprised by your statement that much (why would compiler do such thing???), that I had to check it myself. So I made simple example like this



            public class test {
            private static Object holder;

            private void method1() {
            final Object obj1 = new Object();
            final Object obj2 = new Object();
            holder = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            System.out.println(obj1);
            }
            };
            }
            }


            And resulted with following bytecode for of method1



             private method1()V
            L0
            LINENUMBER 8 L0
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 1
            L1
            LINENUMBER 9 L1
            NEW java/lang/Object
            DUP
            INVOKESPECIAL java/lang/Object.<init> ()V
            ASTORE 2
            L2
            LINENUMBER 10 L2
            NEW test$1
            DUP
            ALOAD 0
            ALOAD 1
            INVOKESPECIAL test$1.<init> (Ltest;Ljava/lang/Object;)V
            PUTSTATIC test.holder : Ljava/lang/Object;


            Which means:




            • L0 - store first final with idx 1 (ASTORE 1)

            • L1 - store second final with idx 2(that one is not used in anon class) (ASTORE 2)

            • L2 - create new test$1 with argumets (ALOAD 0) this and obj1 (ALOAD 1)


            So I have no idea, how did you get to the conclusion that obj2 is passed to anonymous class instance, but it was simply wrong. IDK if it is compiler dependent, but as for what other has stated, it is not impossible.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered yesterday









            Antoniossss

            14.6k12149




            14.6k12149












            • To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
              – ajb
              yesterday


















            • To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
              – ajb
              yesterday
















            To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
            – ajb
            yesterday




            To answer your question "How did I get to the conclusion"... I thought I had read it somewhere, a long time ago, but it looks like I misremembered. I envisioned a compiler creating a hidden object with a reference to the outer this and references to all the final variables and parameters, when it first starts processing the inner class. Perhaps I created a mental picture to help me understand what was going on with inner classes, and later got it confused with something I thought I read? I don't know.
            – ajb
            yesterday










            up vote
            0
            down vote













            obj2 will be garbage collected since it has no reference to it. obj1 will not be garbage collected as long as the event is active since even if you created an anonymous class, you've created a direct reference to obj1.



            The only thing final does is that you can't re-define the value, it doesn't protect the object from the garbage collector






            share|improve this answer



















            • 1




              If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
              – Rab
              yesterday










            • OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
              – Antoniossss
              yesterday












            • I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
              – Nertan Lucian
              yesterday






            • 1




              You are missing the point and if you answered base on title, it is still off topic IMHO.
              – Antoniossss
              yesterday

















            up vote
            0
            down vote













            obj2 will be garbage collected since it has no reference to it. obj1 will not be garbage collected as long as the event is active since even if you created an anonymous class, you've created a direct reference to obj1.



            The only thing final does is that you can't re-define the value, it doesn't protect the object from the garbage collector






            share|improve this answer



















            • 1




              If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
              – Rab
              yesterday










            • OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
              – Antoniossss
              yesterday












            • I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
              – Nertan Lucian
              yesterday






            • 1




              You are missing the point and if you answered base on title, it is still off topic IMHO.
              – Antoniossss
              yesterday















            up vote
            0
            down vote










            up vote
            0
            down vote









            obj2 will be garbage collected since it has no reference to it. obj1 will not be garbage collected as long as the event is active since even if you created an anonymous class, you've created a direct reference to obj1.



            The only thing final does is that you can't re-define the value, it doesn't protect the object from the garbage collector






            share|improve this answer














            obj2 will be garbage collected since it has no reference to it. obj1 will not be garbage collected as long as the event is active since even if you created an anonymous class, you've created a direct reference to obj1.



            The only thing final does is that you can't re-define the value, it doesn't protect the object from the garbage collector







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            Nertan Lucian

            9619




            9619








            • 1




              If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
              – Rab
              yesterday










            • OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
              – Antoniossss
              yesterday












            • I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
              – Nertan Lucian
              yesterday






            • 1




              You are missing the point and if you answered base on title, it is still off topic IMHO.
              – Antoniossss
              yesterday
















            • 1




              If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
              – Rab
              yesterday










            • OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
              – Antoniossss
              yesterday












            • I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
              – Nertan Lucian
              yesterday






            • 1




              You are missing the point and if you answered base on title, it is still off topic IMHO.
              – Antoniossss
              yesterday










            1




            1




            If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
            – Rab
            yesterday




            If you don't understand the OP why would you post an answer to this question when it is already answered by 4 different people.
            – Rab
            yesterday












            OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
            – Antoniossss
            yesterday






            OP meant that he thought that even obj2 is not used in anon class it still holds reference to it (which is false btw). Its not about final or not declarations.
            – Antoniossss
            yesterday














            I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
            – Nertan Lucian
            yesterday




            I answered base on title, obj2 in op post has no outside reference as long as Outer class is not instantiated
            – Nertan Lucian
            yesterday




            1




            1




            You are missing the point and if you answered base on title, it is still off topic IMHO.
            – Antoniossss
            yesterday






            You are missing the point and if you answered base on title, it is still off topic IMHO.
            – Antoniossss
            yesterday




















             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53203529%2fare-all-final-variables-captured-by-anonymous-classes%23new-answer', 'question_page');
            }
            );

            Post as a guest




















































































            Popular posts from this blog

            Schultheiß

            Verwaltungsgliederung Dänemarks

            Liste der Kulturdenkmale in Wilsdruff