Anonymous vs named inner classes? - best practices?
Asked Answered
B

16

49

I have a class, let's call it LineGraph, that renders a line graph. I need to subclass it, but the derived class is only used in one place and is coupled to the class that uses it. So I am using an inner class.

I see two ways to do this:

Anonymous inner class

public class Gui {
    LineGraph graph = new LineGraph() {
        // extra functionality here.
    };
}

Named inner class

public class Gui {
    MyLineGraph graph = new MyLineGraph();

    private class MyLineGraph extends LineGraph {
        // extra functionality here.
    }
}

I am not a fan of anonymous inner classes, because frankly I just think it looks really ugly. But in the case of a subclass that's only used in one place, is a named inner class overkill? What is the accepted practice?

Bacteriostat answered 3/4, 2009 at 16:6 Comment(0)
D
55

One advantage of anonymous inner classes is that no one can ever use it anywhere else, whereas a named inner class can be used (if only by the class that created it if made private). It's a small distinction, but it does mean that you can protect an inner class from being accidentally used elsewhere.

Also, using the anonymous inner class gives anyone reading your code a head's up - "this class is being used just here and nowhere else." If you see a named inner class, someone might think it'd be used in multiple places in the class.

They are very similar, so neither point is a game-changer. I just think it helps for clarity if you use anonymous inner classes for one-offs, and named inner classes when it's used multiple times within the class.

Depressor answered 3/4, 2009 at 16:12 Comment(1)
+1 Good points, but remember classes can be defined inside functions, too. This limits their scope and can be a good hint they they have a very localized use.Unusual
C
39

(Counter point to Daniel Lew)

One disadvantage of anonymous inner classes is that no one can ever use it anywhere else, whereas a named inner class can be used (if only by the class that created it if made private). It's a small distinction, but it does mean that you can help ensure that an inner class is not accidentally recreated elsewhere.

Also, using the anonymous inner class gives anyone reading your code a harder time as they then have to parse this class that came out of nowhere. Using a named inner class you are able to organize the source more.

I have seen cases where there are two (or more) anonymous inner classes with the exact same code. In GUIs especially (where you may have multiple controls performing the same action) this can crop up (and I am talking production code, not code that my students have written).

The readability issue goes both ways, some people find anonymous inner classes better as it lets you see what is going on in once place, others find it a distraction. That part comes down to personal preference.

Also making an class static is more efficient, if you are declaring an anonymous inner class in an instance then there will be more overhead, which, if you don't need access to the instance variables, is wasteful (but probably not worth worrying about until it presents as a problem).

My personal preference is to use non-anonymous classes as they allow for more flexibility when the code is modified later.

Copula answered 3/4, 2009 at 16:41 Comment(4)
This is what I find ugly about the anonymous inner classes. You are reading through the code, and suddenly there is this class definition smack in the middle of a bunch of fields.Bacteriostat
I always have problem aligning the code inside anonymous class. No matter how hard I try, the code still looks ugly :DKuching
I agree - I find code hard to read/debug if there are lots of anonymous inner classes. Instead of declaring anonymous inner classes within multiple functions (YUCK!), I find that it's much better practice to dedicate sections of the file to named inner classes, i.e. the bottom of the file.Canvasback
what if i do public MyInterface myInterfaceVariable = new MyInterface(){ public void myMethod(){ print("HI") } }; Now i can use myInterfaceVariable object anywhere in that classCartelize
G
10

Why do you need to subclass it? If it's just to override an existing virtual method, I think an anonymous inner class is okay. If you're adding extra functionality, I'd use a named class. I'd make it a nested class though (i.e. with the static modifier) - I find them easier to reason about :)

Goatee answered 3/4, 2009 at 16:11 Comment(4)
My example was somewhat simplified. In the real code, it overrides 5 (non-abstract) methods.Bacteriostat
That sounds like enough to make it worth making into a named class. I like my anonymous classes to be small.Goatee
agreed. I generally only use anonymous classes if they're really simple. Any more than one small function definition and I'll make it a normal inner class (static if possible). Just easier to read that way.Bacchanalia
Looks like you should not use inheritance but make LineGraph an interface and use a different implementation (maybe delegating to your now base class).Kinsey
C
9

Do the simplest thing that could possibly work: Use the anonymous inner class.

If you later find that you need a broader scope, then refactor the code to support this.

(You would do the same with variables -- putting them in the most specific scope. It makes sense to do the same with other source assets.)

Concernment answered 3/4, 2009 at 18:37 Comment(0)
C
5

My personal rule of thumb: If the anonymous inner class is going to be small, stick with an anonymous class. Small being defined as around 20 - 30 lines or less. If it is going to be longer, it starts to be unreadable in my opinion, so I make it a named inner class. I remember once seeing a 4000+ line anonymous inner class.

Culinarian answered 30/7, 2009 at 18:55 Comment(0)
T
4

Anonymous inner classes are hard to debug in Eclipse (thats what I use). You will not be able to look at variable values/inject values by simply right clicking.

Tello answered 3/4, 2009 at 16:30 Comment(0)
R
3

A disadvantage of inner classes is that they can not be static. This means that will hold a reference to the outer class that contains them.

Non-static inner classes can be an issue. For example we recently had an inner class being serialised, but the outer class was not serializeable. The hidden reference meant that the outer class would also be serialised, which of course failed, but it took a while to find out why.

Where I work, static inner classes are encouraged in our coding best practices (where possible) as they carry less hidden baggage and are leaner.

Rigveda answered 3/4, 2009 at 17:11 Comment(0)
S
2

Anonymous inner classes would generally be the way to go. I find them very readable. However, if the instance of that class ever needs to be serialized (even if only because it's a field of something else), I would strongly recommend using named inner classes. The names of anonymous inner classes in the bytecode can change very easily, and this can break serialization.

Stairway answered 3/4, 2009 at 16:35 Comment(0)
Q
2

Anonymous classes can't have a constructor, since they don't have a name. If you need to pass other variables than those in the constructor(s) of the class you're extending, you should use a (static) named inner class. This can sometimes be overcome by using final variables in the surrounding method/code, but it's a bit ugly imho (and can lead to what Robin said).

Quintuplicate answered 20/11, 2010 at 4:15 Comment(0)
C
1

I don't have a problem with simple anonymous classes. But if it consists of more than a few lines of code or a couple of methods, an inner class is more clear. I also think that under certain conditions they should never be used. Such as when they must return data.

I have seen code where a final array of 1 item is used to pass data back from a call to an anonymous inner class. Inside the method of the anon class, the single element is set, then this 'result' extracted once the method is complete. Valid, but ugly code.

Compassion answered 3/4, 2009 at 18:24 Comment(0)
D
1

Anonymous classes:

  • cannot have anything static in the definition (static class, static field, static initializer, etc.)
  • fields cannot be inspected in Eclipse
  • cannot be used as a type (Foo$1 myFoo=new Foo$1(){int x=0;} doesn't work)
  • cannot be located using the class name in Eclipse (searching for Foo$1 doesn't work for me)
  • cannot be reused

Anonymous classes can, however, have an initializer like {super.foo(finalVariable+this.bar);}

Named inner classes don't have these limitations, but even if one is used exclusively in the middle of a long procedure, the declaration will have to be moved up to the next named class.

I personally prefer anonymous inner classes if the restrictions don't apply because:

  • I know any additional fields are only referenced in the class definition.
  • Eclipse can convert them to nested classes easily.
  • I don't need to copy in variables I want to use. I can just declare them final and reference them. This is especially useful when I have lots of parameters.
  • The code that interacts is close together.
Drinker answered 26/5, 2012 at 21:1 Comment(0)
C
0

I think what you've done makes perfect sense in this case and either way you look at it, I think you are really splitting hairs with this particular issue. They are both so similar and either will work.

Colotomy answered 3/4, 2009 at 16:11 Comment(1)
There are plenty of times where two options will work but one is more readable and maintainable than another. I think it makes a lot of sense to ask for other people's opinions when in doubt about the best way to go.Goatee
L
0

I think this is a matter of taste. I prefer to use anonymous classes for Functors. But in your case, I'd use an inner class, since I think you'll be packing more than just a few lines of code in there, perhaps more than just a method. And it would emphasise the fact that it's adding functionality to the superclass, by putting it inside the class, rather than hidden somewhere in a method. Plus, who knows, maybe someday you might need the subclass else where. This, of course, depends on how much you know about how your software will evolve. Other than that, just flip a coin. :)

Leann answered 3/4, 2009 at 16:24 Comment(0)
C
0

Just had this discussion today with my coworker and was digging around for popular opinion.

I am in agreement with TofuBeer. If your code has more than 2 lines, it's probably not a 'one-off' and might be re-used some day. If you are creating a form using an MVC pattern, you might have 20 controllable elements on a page instead of cluttering the view up with tons of anonymouse classes (hell your view was probably created using a GUI builder and the code was auto-genned making editing the source not even an option) you will likely feed each element to a controller. You can nest inner classes within the controller to handle each different handler/listener interface that your view requires. This organizes the code really well, especially if you have a convention that your handler class must be named using the GUI element name (like backButtonHandler for a backButtonElement). This worked really well for us, and we wrote an auto-registration tool (when you register a controller on a view, the view looks for inner-classes using the element name and uses them for a handler on each named element). This would not be possible with anonymous classes and makes the controller much more recyclable.

TLDR: when in doubt write a named inner-class. You'll never know if someone wants to re-use your code some day (unless it's 2 lines, then you have to wonder 'does this code smell?'). Code that is well organized has much higher benefits in the long term, especially when your project is in maintenance.

Casals answered 16/4, 2013 at 22:23 Comment(0)
C
0

With anonymous inner classes, we cannot change the state of the including class members. They need to be declared as final.

Crosley answered 27/2, 2016 at 12:18 Comment(0)
A
0

Well, the main thing is that it is quicker to just create an anonymous inner class rather than create a new separate class. Anonymous inner classes are especially useful when you only need to override a small amount of functionality (like just one method) in a superclass, and don’t want to deal with the overhead of creating an entire class for something so simple.

see java-anonymous-class-example and anonymous-class-interface

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.

official doc

Amharic answered 29/5, 2022 at 4:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.