0

I'm bothered by the question whether the address of anonymous inner class in Java keep invariable.

I made some test codes,

public class AnonymousInnerClass {
    public static void main(final String[] args) {
        for (int i = 0; i < 5; i++) {
            final Runnable x = () -> {
            };
            System.out.println(x);
        }
        for (int i = 0; i < 5; i++) {
            final int j = i;
            final Runnable x = () -> {
                final int k = j;
                System.out.println(k);
            };
            System.out.println(x);
        }
    }
}

and the outputs are not consistent.

main.AnonymousInnerClass$$Lambda$1/0x0000000800000a00@7a46a697
main.AnonymousInnerClass$$Lambda$1/0x0000000800000a00@7a46a697
main.AnonymousInnerClass$$Lambda$1/0x0000000800000a00@7a46a697
main.AnonymousInnerClass$$Lambda$1/0x0000000800000a00@7a46a697
main.AnonymousInnerClass$$Lambda$1/0x0000000800000a00@7a46a697
main.AnonymousInnerClass$$Lambda$2/0x0000000800000c18@532760d8
main.AnonymousInnerClass$$Lambda$2/0x0000000800000c18@57fa26b7
main.AnonymousInnerClass$$Lambda$2/0x0000000800000c18@5f8ed237
main.AnonymousInnerClass$$Lambda$2/0x0000000800000c18@2f410acf
main.AnonymousInnerClass$$Lambda$2/0x0000000800000c18@47089e5f

It seems the address is invariable if class is simple, I'm wondering that's compiler optimizing behavior or language specification.


More realistic scenario, I'm working with Android's MutableLiveData.

Suppose I have a variable passwd,

public final MutableLiveData<String> passwd = new MutableLiveData<>("");

and passwd has a method public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer).

Normally I call it with an anonymous inner class passwd.observe(mLifecycleOwner, str -> doSomething());, and maybe call it several times.

Api doc said the call would be ignored if the observer has been always registered, that's what I need. But this relies on the address of str -> doSomething() would not change.

I don't want to extract it to a named variable, so I want to know if I can get a language specification guarantee that its address would not change, or if there are some conventions or patterns to handle this situation.

Master Qiao
  • 301
  • 2
  • 10
  • 2
    What we see are not addresses, but the class names and (identity-)hash codes of the objects in hexdec. See [this question](https://stackoverflow.com/questions/1961146/memory-address-of-variables-in-java) and its answers for details. – Turing85 Apr 22 '22 at 18:43
  • There seems to be a misconception about what a lambda (in Java) actually is. A lambda is nothing else than an anonymous implementation of a functional interface. As such, each lambda definition is a new object instance. – Turing85 Apr 22 '22 at 18:51
  • The first five output lines are the same, implying that the object itself was reused, and the last five lines are all different, implying that new objects were created each iteration of the loop. I'm not sure why myself, other than clearly the optimizer found some tricky way to reuse the object in the first loop. – markspace Apr 22 '22 at 19:01
  • In the second loop, 5 new lambda objects because the anonymous class is created with constructor that gets `j` as parameter. New object is created because each iteration have a different `j`. I wonder what'll happen if you persist `j` to be the same value every time: `final int j = 1;` – Shlomi Katriel Apr 23 '22 at 03:02
  • Only one instance will be created in the second loop if persist j to be same value. That seems troublesome if we use lambda objects as map key or something else, for the lambda objects are not guaranteed to be either identical or not. – Master Qiao Apr 23 '22 at 07:31

0 Answers0