• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Rob Spoor
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Henry Wong
  • Liutauras Vilda
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Tim Holloway
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Mikalai Zaikin
  • Piet Souris

Nested Class Types usage summary anyone?

 
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi

Today we have been going through nested class types, and the teacher was using the diagram on this page: https://www.tutorialspoint.com/java/java_innerclasses.htm

I know that anonymous classes are often used in event handling, but I couldn't see why I'd want to use a static inner class, an inner class or a method-local inner class. I understand the mechanism and scope of these, but can't imagine ever needing to use one. I wonder if anyone can help me here? For example, point to me to a source that explains the use, with examples? The teacher just said they are used when we want to structure and organise our code that way...which did not help me much.

Thanks
Antonio
 
Marshal
Posts: 74042
332
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Antonio Moretti wrote:. . . anonymous classes are often used in event handling . . .

Also for sorting; you can writeNot any more.
You can replace such an anonymous Comparator class, or an ActionListener, or the contents of an onSomething() method in JavaFX by a λ, so there is much less need for such anonymous classes.

a static inner class, an inner class or a method-local inner class.

Don't say, “static inner class.” Inner classes are implicitly not static, so call them, “static nested classes.” An inner class implicitly has a this reference pointing to an instance of its enclosing type, so it can only be created when there already is such an outer class instance. Look in books like Bruce Eckel's Thinking in Java. A static nested class is easier to use, especially if it isn't private. There are restrictions on access to instance members of the enclosing type, and an inner class has restrictions on having static members (not mentioned in your link).

I understand the mechanism and scope of these, but can't imagine ever needing to use one. . . .

What about a linked list? You should consider nested classes whenever there is an intimate relationship between the nested and enclosing classes. If you have a linked list, you usually have nodes too. Is there an intimate relationship between nodes and linked lists? Yes, a node IS‑A‑PART‑OF a linked list. There is no need for code to access individual nodes from outside the list.I am not sure I have got the generics correct.
I am not convinced that nested classes are a security measure as suggested in the tutorial. There is often no need to a this reference to the enclosing type, as explained in a section in Effective Java by Joshua Bloch about preferring static nested classes to inner classes (2nd edition p106, 3rd edition P112).
 
Saloon Keeper
Posts: 1306
40
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Many examples of these things date back to before Java 8 gave us lambdas and method references in 2014.

Nowadays, you might want to ask the question as "When might I want one of these things instead of a lambda or method reference when those things are so easy to use once learned?"

A lambda or method reference can only be used to implement a Single Abstract Method interface, which is quite common indeed but not always enough for what you may need at that moment in real life.

An anonymous class is more typing, more reading and more work, but it can implement any ONE interface (not just a single abstract method one) or extend any ONE class, but not both.

A named local or inner class is more work than that but can do even more, which is needed even less frequently than the requirements you have for an anonymous inner class.
It can implement as many interfaces as it needs to AND also extend any single class in your world, basically more stuff to muck around about, fewer restrictions.

So you learn them all and when coding use the easiest thing that meets your needs.  You can nearly always replace a small, neat, easy Java construct with a bigger and messier one, but not vice versa, because the small easy convenient things have the most restrictions, and as they get smaller and easier, apply to fewer possible needs (but still a lot).

The main reason for all of these is encapsulation and organization.  When you make something publicly visible, others will start making direct use of it, if anyone is using your code at all.
Then when you want or need to change something, you find yourself painted into a corner, because you can't make the improvements you want without breaking code you don't even know about (or that is owned by people somewhere else in your organization, who will grumble at you and possibly complain that you are making extra work for them).

A lot of tutorial and explanatory material concerning Java is reasonably old, because Java is 25 years plus (since it was released to the world) and the internet has a great memory.

If you are preparing for a Certification Exam, it seems quite annoying that there are so many possible ways of doing things, each with their own gotchas and tricks and limitations and rules.
When you are actually coding for work, for yourself, for a programming contest, whatever -- the fact that there are a whole bunch of different crayons in your box, that can be arranged from "simplest, easiest, most limited" to "most complex, most hassle, can do pretty much anything" is actually a great thing (if you remember how to use them).  You should get used to choosing the simplest easiest thing that works for the problem you are trying to solve.

One problem for Certification Seekers is that some of the things that used to be heavily used (with some grumbling) in Java have become very rare because the easiest and simplest solutions (e.g. lambdas) actually work fine in most cases and you can forget rules about these things because you just don't use them often.  I don't have a real solution to that one.

If you do look at or work with older code you will actually see many clunky awkward things that could actually be done with lambdas or method references now, but you will also see things that actually needs the clunkier things (or at least, that is the most straightforward way to do them for the way they understood the problem at the time).

That was very abstract, rather than giving examples, but you can find code that matches these patterns all over the Java world, so I answered in Shapes instead of Circles, Triangles, Squares and Octagons.
 
Jesse Silverman
Saloon Keeper
Posts: 1306
40
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Believe it or else, I left something out!

It is weird that more sources don't talk about this, but some incisive ones do.

To some extent, many of these Java constructions you are wondering "Why would I ever really want to use these?" could be seen at doing an end-run around the limitation of single inheritance in Java.

Unlike some popular (C++, Python, etc.) languages Java strictly enforces single-inheritance for classes.

If you on the lookout for examples, you may (well I have) seen places where these things were used to kinda "cheat" your way around that.

An inner class can extend some other class different than its outer class.
It can then access all protected or public members of the class it extends, and ALL of the class it is nested in.

I won't try to go into an example here, but I have definitely seen them.
So that isn't "Just about encapsulation or organization" as I had (too) neatly summarized above, it would be a way to adapt some designs that utilized multiple inheritance in C++, Python etc. not-too-indirectly in Java.
 
Saloon Keeper
Posts: 24314
167
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Not any more

PLEASE! This is JAVA! We don't do "not any more here". Leave that to Microsoft and the unwashed masses. The old practice does still work. It's just that given more elegant alternatives, there's no justification for doing it that way for new code - and some IDEs do have a "magic button" that will upgrade legacy code when you do maintenance on it.

But it's not like the old way doesn't work anymore.

Jesse may have already heard about me and multiple inheritance in C++. To put it politely, it can be a real mess. If multiple classes all implement the same method and they are all used as base classes in a multiply-inheriting class, you get a quandary - which base class method should get called when you're calling the subclass inheritance?

Java got around that by defining that Interfaces guarantee that an implementing class will implement that method, but the actual details are solely and definitively provided by the implementing class. Since Interfaces don't* implement methods, the fact that a class might implement several interfaces with overlapping method declarations is not a problem.

===
*Traditionally. I'll leave it to Campbell to explain how recent developments factor into this strategy.
 
Campbell Ritchie
Marshal
Posts: 74042
332
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . We don't do "not any more here". Leave that to XXX . . ..

Yes, you are right; the old ways still work.
 
Campbell Ritchie
Marshal
Posts: 74042
332
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . . I'll leave it to Campbell to explain how recent developments factor into this strategy.

Hahahahahahaha! I shall wait for AM to post a new question about that.
 
Jesse Silverman
Saloon Keeper
Posts: 1306
40
Eclipse IDE Postgres Database C++ Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now what would you pay?  But WAIT, there's MORE!!

This would be too much info for most "Beginning Java" threads, but I know the OP has a strong thirst for Deep Knowledge of Java from their posting history.

Some more words about Encapsulation in Java.

Most good programmers realize the tremendous long-term benefits of Strong Encapsulation for projects that will get large, will live a long time, or both.

They are seeking it however they can get it.

Just how you can go about getting it has evolved a lot over Java's long history.

Modern Java now finally has the Java Platform Module System (sometimes still called Project Jigsaw).

Let me describe briefly the problem it solved and then I will leave it to you to work out in code that targeted Java 8 and earlier the places and ways and workarounds they used to try to deal with the fact that it wasn't there for us yet.

In Java, you will very commonly see all but the smallest projects split into many packages.

The idea was supposed to be that everything that used a default accessibility (unfortunately spelled "" because there was no way to say it aloud!) can be seen by all other classes in the same package.

Well, that worked, except that you will also see most larger packages split into "sub-packages".

But that doesn't mean what it seems to for people coming from other languages.

Let's take an example using some "famous" Java packages we should all know about:
java.nio
...
java.nio.file


It would be reasonable to think that maybe java.nio.file can access those package-friendly, default or "no access modifier specified" components of java.nio, right?

"But NOOOOOO..." as John Belushi would have said, as far as access to each other goes they might as well be in:
shows.classic.snl

and

holidays.fun.snowy

But let's say they need to access stuff in each other, not sure for the example I gave because I am rushing, but it is VERY common.

So what did we used to do?

Anything that code in ANY other package in the world needed to access, even a "sub-package" that we just learned gets no special access privileges compared to any other package in the world, needed to be marked public or it couldn't be accessed.

But now, ANYONE who knows the package name can access it.  Oh, no!

Too bad.  There wasn't really a solution to this, we tried to do things like calling it "something.unsafe", "whatever.internal" or, in places I worked (this is not a joke) "mypackage.donotuse".

Did people listen?   Nooooo...

This caused much pain and suffering.  We needed to make changes or improvements and couldn't because there were people accessing stuff we didn't want them to, but they did and now it was OUR problem!!

So now we have the concept of modules, a higher level of organization than packages.
Modules can decide what of the multiple packages they contain can be seen by the outside world, and, in fact, by which modules if we know of a "Safe List" of those.
So all the implementations and stuff we might want to change can be safely marked public in the code and used within the module, and, optionally, some things can be shown to all or just select users of the module.

This is all wonderful and terrific and you should learn all about it.

BUT...this only came along relatively very recently!!  Java was around for no less than 22 years before we got these much-needed options for encapsulation.

All but the newest code projects you may see were started long before modules were actually usable (the Jigsaw project started way back but there were many difficult roadblocks to overcome before it actually saw the light of day and we could actually use it).

You will see many, many things in older code bases used to Desperately Seek Encapsulation for good reason that had no language support in Java for "modules" (JPMS is known both by the compiler and the JVM, it took a long time to get there but "the whole Java System" knows about, and respects them now)...

Some of these will involve Nested or Inner Classes.

Some of them would look neater or easier or cleaner implemented in other ways now that we know about and can use Modules to organize our code.

But what would we say "You should have waited another 16 years to release your popular open-source project so that it could use JPMS?"

So the point is, there are a lot of better ways to organize code and achieve great encapsulation in Modern Java using modules that we would be dumb not to avail ourselves of now.

But we can't fault others for not using what wasn't there yet for all the years before they had access to it.

Various different attempts to achieve such results might look clunky, awkward or complex BECAUSE THEY WERE.  But it wasn't their fault.

Having a very full knowledge of Java includes recognizing those paradigms and idioms so as to be able to work productively with such code.

It would be a Very Bad Idea to rely on such clunky solutions in new code that doesn't have to run on Java 8 or before, but there are billions of lines of Java and probably millions of classes (and probably even packages and sub-packages) that were in production and getting used heavily before we had any of these nifty ways to do things.

So, it is a bit like hand-cranked cars, horses-and-buggies or churning your own butter, except that you will actually see these things in Real Life Java Code.

Especially regarding dependency management at runtime and encapsulation as enforced by the compiler and JVM, best practices in the old days and now for new code that knows it is on say, at least Java 11 look VERY differently.

I'm not sure how much of this directly touches on Nested and Inner Classes, but some of it indeed does, and we did bring up Encapsulation, the notion of "Okay, it is great.  So how do I get it?" has changed a LOT between "Classical Java" and "Modern Java"...
 
Jesse Silverman
Saloon Keeper
Posts: 1306
40
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I intentionally focused on "Since these newer cooler neater things seem better, when do we still pull out the older crayons from the box?" because I knew Tim would say that!

Then I went off on a wild riff about Encapsulation (and how to get it) that seems inappropriate for Beginning Java but I think the OP would want to see because they want to be a Great Java Programmer, and it is hard to do that without appreciating both "the Old Ways" and "Better, Newer Ways" if you are operating in the Real World.  Heck, it isn't that easy even if you DO.  
 
Antonio Moretti
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jesse Silverman wrote:Now what would you pay?  But WAIT, there's MORE!!

This would be too much info for most "Beginning Java" threads, but I know the OP has a strong thirst for Deep Knowledge of Java from their posting history.

Some more words about Encapsulation in Java.

Most good programmers realize the tremendous long-term benefits of Strong Encapsulation for projects that will get large, will live a long time, or both.

They are seeking it however they can get it.

Just how you can go about getting it has evolved a lot over Java's long history.

Modern Java now finally has the Java Platform Module System (sometimes still called Project Jigsaw).

Let me describe briefly the problem it solved and then I will leave it to you to work out in code that targeted Java 8 and earlier the places and ways and workarounds they used to try to deal with the fact that it wasn't there for us yet.

In Java, you will very commonly see all but the smallest projects split into many packages.

The idea was supposed to be that everything that used a default accessibility (unfortunately spelled "" because there was no way to say it aloud!) can be seen by all other classes in the same package.

Well, that worked, except that you will also see most larger packages split into "sub-packages".

But that doesn't mean what it seems to for people coming from other languages.

Let's take an example using some "famous" Java packages we should all know about:
java.nio
...
java.nio.file


It would be reasonable to think that maybe java.nio.file can access those package-friendly, default or "no access modifier specified" components of java.nio, right?

"But NOOOOOO..." as John Belushi would have said, as far as access to each other goes they might as well be in:
shows.classic.snl

and

holidays.fun.snowy

But let's say they need to access stuff in each other, not sure for the example I gave because I am rushing, but it is VERY common.

So what did we used to do?

Anything that code in ANY other package in the world needed to access, even a "sub-package" that we just learned gets no special access privileges compared to any other package in the world, needed to be marked public or it couldn't be accessed.

But now, ANYONE who knows the package name can access it.  Oh, no!

Too bad.  There wasn't really a solution to this, we tried to do things like calling it "something.unsafe", "whatever.internal" or, in places I worked (this is not a joke) "mypackage.donotuse".

Did people listen?   Nooooo...

This caused much pain and suffering.  We needed to make changes or improvements and couldn't because there were people accessing stuff we didn't want them to, but they did and now it was OUR problem!!

So now we have the concept of modules, a higher level of organization than packages.
Modules can decide what of the multiple packages they contain can be seen by the outside world, and, in fact, by which modules if we know of a "Safe List" of those.
So all the implementations and stuff we might want to change can be safely marked public in the code and used within the module, and, optionally, some things can be shown to all or just select users of the module.

This is all wonderful and terrific and you should learn all about it.

BUT...this only came along relatively very recently!!  Java was around for no less than 22 years before we got these much-needed options for encapsulation.

All but the newest code projects you may see were started long before modules were actually usable (the Jigsaw project started way back but there were many difficult roadblocks to overcome before it actually saw the light of day and we could actually use it).

You will see many, many things in older code bases used to Desperately Seek Encapsulation for good reason that had no language support in Java for "modules" (JPMS is known both by the compiler and the JVM, it took a long time to get there but "the whole Java System" knows about, and respects them now)...

Some of these will involve Nested or Inner Classes.

Some of them would look neater or easier or cleaner implemented in other ways now that we know about and can use Modules to organize our code.

But what would we say "You should have waited another 16 years to release your popular open-source project so that it could use JPMS?"

So the point is, there are a lot of better ways to organize code and achieve great encapsulation in Modern Java using modules that we would be dumb not to avail ourselves of now.

But we can't fault others for not using what wasn't there yet for all the years before they had access to it.

Various different attempts to achieve such results might look clunky, awkward or complex BECAUSE THEY WERE.  But it wasn't their fault.

Having a very full knowledge of Java includes recognizing those paradigms and idioms so as to be able to work productively with such code.

It would be a Very Bad Idea to rely on such clunky solutions in new code that doesn't have to run on Java 8 or before, but there are billions of lines of Java and probably millions of classes (and probably even packages and sub-packages) that were in production and getting used heavily before we had any of these nifty ways to do things.

So, it is a bit like hand-cranked cars, horses-and-buggies or churning your own butter, except that you will actually see these things in Real Life Java Code.

Especially regarding dependency management at runtime and encapsulation as enforced by the compiler and JVM, best practices in the old days and now for new code that knows it is on say, at least Java 11 look VERY differently.

I'm not sure how much of this directly touches on Nested and Inner Classes, but some of it indeed does, and we did bring up Encapsulation, the notion of "Okay, it is great.  So how do I get it?" has changed a LOT between "Classical Java" and "Modern Java"...



Fantastic information. I have pasted this into a Word document for use in my Java notes for future reference! Many thanks for the time!
 
Jesse Silverman
Saloon Keeper
Posts: 1306
40
Eclipse IDE Postgres Database C++ Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You are very welcome.

It possibly strayed *slightly* off-topic, but did stay on "why did these people do things this way?
Were they just dumb?"

The interesting part to me is that there are many cases where the answer is NOT that they were dumb, or careless or rushing, but there may be much better ways to do things that we have available now.

Also, there are still cases where our neat nifty new options won't fit, and we are going to actually need to use bigger, clunkier things that we used to need all the time...

We don't need to go back and re-write the whole Universe, but we do want to be sure that we are both picking better, easier, more reliable solutions that are available to us now, and are able to work with older code without giving in to a temptation to try to re-write all of it, except where and as appropriate.  That part was added in case any hiring managers are reading this -- employers recognize and resist programmers who want to re-write everything, and sometimes even resist when the code seems to be screaming loudly for it...

Those things are not specific to Java, almost every language I work in except maybe C has cool, new, shiny, better more fun ways to do things.  We should use them all when writing new code if they don't break compatibility requirements, but many important projects consist primarily of code written before those nifty new options were available.  Both the desire to dig in and be a dinosaur and ignore them, and the opposite feeling of wanting to re-write tons of working code using "better, nicer" features are very understandable, but bad.


 
reply
    Bookmark Topic Watch Topic
  • New Topic