13

This is in relation to my answer to a question provided in this thread: Are Inner Classes lightweight?

I remember from my reading that if you can only create one object from a single anonymous inner class, and for this reason, if you want to say create an ActionListener class and want to create multiple objects from this one class (not using reflection), to not use an anonymous inner class but rather either a private inner class or a stand along class, but folks are telling me I'm wrong. Can someone please clarify this for me? Please check the link as it contains more details, but if anything is unclear, please ask away!

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks, I think I understand that, but this would require creating multiple classes -- if I understand correctly. The question is given code for a single anonymous inner class, can you make multiple instances of its objects? And I don't mean using a loop, since again, that would create multiple classes --- oops, where'd your comment go? – Hovercraft Full Of Eels Jan 27 '11 at 18:04
  • 1
    I think you mean multiple instances of its class? An object is in of itself an instance – John Vint Jan 27 '11 at 18:05
  • 1
    @Hovercraft, can't put readable code in the comments. ;) – Peter Lawrey Jan 27 '11 at 18:06
  • Peter and John: Thanks for the comments! I have code in the link. Do you want me to repost it here? – Hovercraft Full Of Eels Jan 27 '11 at 18:07
  • 1
    @Hoevercraft if you define two runnables Runnable r1 = new Runnable(){ .. } and Runnable r2 = new Runnable(){ ... } then r1.getClass() != r2.getClass() however, like Peter Lawrey answered, a loop will create multiple instances of the same class – John Vint Jan 27 '11 at 18:17
  • Thanks John -- it's starting to making sense. I will also look up how to check the byte code with Eclipse. I think that this is probably where I should have looked in the first place. – Hovercraft Full Of Eels Jan 27 '11 at 19:10

2 Answers2

16

You can create any number of anonymous class objects, you can create them in one place in your code (unless you copy the code)

ExecutorService service = ...
for(int i=0;i<1000*1000;i++) {
   final int finalI = i;
   service.submit(new Runnable() {
      public void run() {
         System.out.println("Task "+finalI+" run.");
      }
   });
}

This code will create 1 million objects of the same class.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • "This code will create 1 million objects of the same class." This is where I"m confused. Wouldn't this create a million classes, each with one instance? This is the crux of the question. – Hovercraft Full Of Eels Jan 27 '11 at 18:08
  • 4
    @Hovercraft Full Of Eels No there is only one *class* created. This class is the one with the funny name *baked into the byte-code*. (Java just does the messy bit of creating a *named* inner class on your behalf and making sure it is setup in context when created). There is just no way to nicely access the type, except as a new *instance* which is the "result" of the anonymous class declaration. –  Jan 27 '11 at 18:11
  • So I was confused then -- won't be the last time unfortunately. – Hovercraft Full Of Eels Jan 27 '11 at 18:12
  • 5
    No. When compiled, the anonymous runnable will be compiled into its own separate class file (probably something like Outer$1.class). This class definition will be loaded once and used to create all 1 million objects. – ILMTitan Jan 27 '11 at 18:13
  • What do you mean by the "unless you copy the code" part? If I copy the code to a different place, then a different anonymous class is created, even if it's identical to the first one. Or am I wrong? – Sergei Tachenov Jan 27 '11 at 18:26
  • 1
    @Sergey Teachenov: You are right. An anonymous inner class is dependent on it's outer class, which explains why the generated class name will be something like `Outer$1.class`, where `Outer.class` is the separate, outer class, and `$1` is the first anonymous inner class. So if you copy the code into another outer class, then the generated inner class will be `OtherOuter$1.class`. Note that the `1` just stands for which anonymous inner class within the outer class that `.class` is for. – Nate W. Jan 27 '11 at 18:31
4

It is unclear to me. Maybe if we comb through specs we'll find evidence that inner classes should be treated the same as normal classes. However in spirit, an inner class depends on the outer instance, the class doesn't exist beyond the instance. This is different from "normal" classes whose existence is basically perpetual. Two inner classes of two outer instances of course are somewhat related each other, being created by the same source code, yet that doesn't mean they must be identical or even equal.

There are evidence that Java designers intended this way, that an inner class in spirit lives within the scope of the outer instance. For example, the curious syntax outerInstance.new InnerClass(). For example, no static variables, no static initializers for inner classes. In the discussion of class unloading [1], we see that the argument doesn't really apply to inner classes, it's conceivable that inner classes can be unloaded! It is conceivable that a VM creates a new inner class for each new outer instance.

Practically that's not the case, inner classes are indeed treated the same as normal classes. But conceptually, I'll always think of them differently, as instance-private classes.

[1] http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

Update: according to [2]

Two reference types are the same run-time type if They ... have the same binary name

and [3]

The binary name of an anonymous class (§15.9.5) consists of the binary name of its immediately enclosing type, followed by $, followed by a non-empty sequence of digits.

So one anonymous class has one binary name, therefore only one run-time type. The spec guarantees us that different instances of an anonymous class have identitcal class.

[2] http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.4

[3] http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#44909

irreputable
  • 44,725
  • 9
  • 65
  • 93