I have class A with its inner class defined A1 and class B with its inner class defined B1. Do you think it is alright that class A in its implementation refers to B1 and class B refers to A1. Is it not a bad programming style? Its just A1 is very A specific class and B1 very B specific, that's why I coupled them. Is it Ok to leave it like that or its better to have A1 and B1 as separate classes? What do you think? Thx.
I believe that if you need to refer to inner classes of another class, in one of your classes, it is because possibly the class which holds the inner class should be providing some methods to avoid this problem.
If the problem is not like that, then the inner class is probably generic enough to be of use in both other classes, and as such should be an independant class, which should be probably part of the same package which specifies its context of application/use.
You could - though I would think the point of inner classes is because they should be used within the outer classes. In other words, I am not a big fan of public inner classes.
I would actually just put A1 and B1 out as its own class - seem to me A1 and B1 are not that specific to A and B after all since A1 is used by B and B1 is used by A.
Look at this post Why/when should you use nested classes "Use a nested class when the class you are nesting is only useful to the enclosing class"
I would possibly try to two things:
Move inner classes to the separate ones, as they are not inner any more in logical way.
Create some interfaces to make A and B not to know at least where the A1 and B1 classes are.
I'd say if both classes are in the same package, extract the inner classes and make them package private. That way, both classes (A and B) can refer to them but still they are invisible to other classes outside the package.
I think you've asked two separate design questions in one. The first question is about referring to another class's inner classes. The second question is about the circular dependency between A/A1 and B/B1.
Exposed Inner Classes
There are many reasons to use Java inner classes.
Group classes that are only relevant to one-another and the outer class. (a.k.a mini-package)
Reduce boilerplate code in passing and referring to outer class instances
Add an additional level of scoping beyond package
Expanding the semantics of Java's access scope... for example, private has a different meaning for outer-class -- inner-class interactions.
Reduce the explosion of source files... especially in (source) code generation scenarios.
Access to outer class internals for testing (the inner class can be removed during packaging of JAR).
Under many of these circumstances, referring to the inner class by name is perfectly reasonable.
Circular Dependency
This is more often a tell tale sign of needing to extract interfaces, or needing extract other specialized classes. If A1, B1 are too simple to extract interfaces etc, then perhaps you can use inner classes in a different way: Have outer class C, containing A1, B1.
Related
I have a Java class that is about 4,000 lines long (lots of methods). This class then uses about 200 small classes that only it needs, so another 4,000 lines of code.
If this was C# I would put those other in a partial class file so different file, but they would remain private nested classes only visible to the parent class.
Is there a way to do this in Java? I'm not asking for some methods to be in a distinct file, but for private nested classes to be in a distinct file.
thanks - dave
You can't make a class private to only another class while putting it in a different file.
Use no class access modifier
What you can do is put the classes in separate files with no access modifiers (omit "public"), which will make them package-private, i.e. visible only within its own package. See also the official Access Control tutorial.
UtilClasses.java:
package OurPackage;
class UtilClass1
{
}
class UtilClass2
{
}
MainClass.java:
package OurPackage;
public class MainClass
{
UtilClass1 iAmAUtilClass;
}
Use interfaces or inheritance
You can also achieve something similar with either interfaces or inheritance, by omitting the access modifier from the nested class. This would also be package-private, but this might be preferable to the above in some circumstances, since it avoids having all the nested classes at the top level.
BaseInterface.java:
package OurPackage;
interface BaseInterface
{
class UtilClass1
{
}
}
MainClass.java:
package OurPackage;
public class MainClass implements BaseInterface
{
UtilClass1 iAmAUtilClass;
}
You can also use a base class instead of an interface and extend that with roughly the same effect.
You don't need to implement BaseInterface gain access to its nested classes, but, if you don't, you'd need to use BaseClass.UtilClass1 instead of just UtilClass1.
Inner private classes can't be "extracted" and still be visible only to one particular class. One solution is already mentioned in the comments: Create a package that contains the "main" class and all the previously inner classes and make the inner classes package visible. This would also allow you to create unit tests testing for the correct functionalities of the inner classes, which is something that is most likely currently not happening simply because the inner classes can't be "reached" by a unit test at the moment.
Concepts like declaring "friendships" between classes like in C++ don't exist in Java.
You can replace the inner classes with top-level ones, but you'll have to rewrite a lot of things by hand that the compiler auto-wires for you with the inner-class relationship. To the Virtual Machine, an inner class is nothing special, it's just another class in the same package as the outer class with a fancy name. But the compiler creates a lot of helper constructs under the hood, that you have to reconstruct by hand (or have some refactoring tool do that for you):
The inner class can refer to the outer this instance, by prefixing it with the outer class name. You need to pass the outer this into your inner constructor and store it in a field like outerThis to get access.
In the source code, you can call the outer-class methods directly. You need to rewrite it like outerThis.method(). The same applies to fields.
For private outer methods and fields to become accessible, the compiler creates bridge constructs for you. You have to either change access modifiers or create package-private bridge methods yourself.
In the end, you'll have the former inner classes at least package-visible and being more verbose than the original ones, but on the other hand you'll get better isolation and testability.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I was reading Thinking in Java, about why inner classes exist and what problem they help solve.
The most compelling reason the book tries to give is:
Each inner class can independently inherit from an implementation.
Thus, the inner class is not limited by whether the outer class is
already inheriting from an implementation.
Please help review my understanding:
Inner classes exist since Java doesn't support Multiple Inheritance. This (multiple inheritances) can be done within an Inner class which it is that the Outer class can have multiple inner classes, and each of them can inherit from different classes. So in this way, The multiple inheritances can be implemented. Another reason I can think of is Inner classes address the OOP design principle composition better than inheritance.
Updated
Most of the explanation I found just like the answers below. for example, Inner class used in the GUI framework to deal with the event handler. Not mentioned the reason quoted in the book.I am not saying the answers below are not the good. Actually. I really appreciated them(+1). I just want to know Is there something problem with the book?
It is a little puzzling why you thought of the idea of multiple inheritance after reading the most compelling reason you have quoted from the book. Multiple inheritance comes into question when a class (inner or not) wants to inherit behavior from more than one concrete implementation. Thus, unlike some other languages, in Java, you can not define a class like:
class Child extends Father, Mother {
// Child wants to inherit some behavior from Father and some from Mother
}
As you can see, nothing that only inner classes do can rectify or work around this Java decision (not to support multiple inheritance) in a straightforward way.
Then why do they exist, you may wonder! Well, in Java every class is either top-level or inner (also called nested). Any class that is defined inside another class is an inner class and any class that isn't so is a top-level class.
Naturally, one might wonder why to define classes (i.e. behavior) inside other classes. Aren't top-level classes enough?
The answer is yes. Java could always have only top-level classes. But the idea (perhaps) was there was no good reason to restrict classes from being members of other classes! Just like any predefined type (e.g. Integer, String etc.) can be a member of a class:
class Person {
private String name; // a field the models a Person's name
}
a programmer should be able to define a behavior of one's interest inside the class:
class Person {
private String name; // a field the models a Person's name
private Address address; // address is a type defined here
static class Address {
String street;
String city;
}
}
There's a lot going on here, especially with these things like private, static etc. which are called the modifiers. There are many technical details about them, but let us come back to them later. The essential idea is to be able to define behavior as a part of another class. Could the Address class be defined outside Person class, as a top-level class? Of course. But having this facility comes in handy.
Now, since this facility was introduced, it started serving another purpose and that purpose is called providing code as data. This is how design patterns emerge and it was thought until about 10 years ago that inner classes can be used to provide the data in the form of code. Perhaps this is somewhat puzzling to you. Consider the following code that I have taken almost verbatim from the JDK class: java.lang.String.java:
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator
implements Comparator<String> {
public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
// details excluded for brevity
// return -1, 0, 1 appropriately
}
}
What has happened here?
We need a way to compare a String to another String and we need to be able to do a case-insensitive comparison. So, we created an implementation of the Comparator interface right inside the outer class: String! Isn't this handy? If inner class wouldn't be there, this would have to be:
public class String {
// ... the whole String class implementation
}
class CaseInsensitiveComparator
implements Comparator<String> {
// implements the comparator method
}
and that's not 'bad' per se, but it means a lot of classes polluting the name space. Inner classes restrict the scope of a behavior to the outer class. That comes in handy, as you'd perhaps see. The data in this case is the implementation of the Comparator interface and the code is well, the same, because we are _new_ing up the inner class we defined.
This feature was exploited further using the anonymous inner classes (especially in the cases where you wanted the code to serve as data) up until Java 7 and they were effectively replaced by Lambda Expressions in Java 8. Nowadays, you might not see any new code that uses anonymous inner classes (in other words, language evolves).
Why Use Nested Classes?
Compelling reasons for using nested classes include the following:
It is a way of logically grouping classes that are only used in one
place: If a class is useful to only one other class, then it is
logical to embed it in that class and keep the two together. Nesting
such "helper classes" makes their package more streamlined.
It increases encapsulation: Consider two top-level classes, A and B,
where B needs access to members of A that would otherwise be declared
private. By hiding class B within class A, A's members can be declared
private and B can access them. In addition, B itself can be hidden
from the outside world.
It can lead to more readable and maintainable code: Nesting small
classes within top-level classes places the code closer to where it is
used.
Oracle Documentation: Understanding inner classes
Below SO question might be interesting to you -
What is the reason for making a nested class static in HashMap or LinkedList?
UPDATE
Not mentioned the reason quoted in the book. ... I just want to know
Is there something problem with the book?
I don't think there is any problem with the statement you have highlighted.
Each inner class can independently inherit from an implementation: That's true right. Just like an outer class, it can inherit from an implementation independently. Just think both of them as separate class.
Thus, the inner class is not limited by whether the outer class is already inheriting from an implementation: As both are separate class, it doesn't matter whether outer class is already inheriting from an implementation. Inner class can inherit from an implementation too. After all it's a class too.
If you are looking for use-cases, I can only tell you what I use them for frequently, which are basically these 2 things:
Static inner classes I use for helping to implement some internal logic. These are usually some form of tuples, or some simple containers. For example: Maps have "Entries" in them which are basically just pairs.
Representing runtime parent-child relationships. These are non-static inner classes. For example: I have a Job class which may instantiate multiple Task inner classes that need to see the data in the job for their processing.
There may be more use-cases of course...
I have a question regarding UML. I have a class which simply contains an inner class with the private access modifier - cannot be accessed from anywhere else... Normally in order to present an inner class relation I can use a (+) relation like here (InnerOddIterator):
(taken from http://www.uml-diagrams.org/nested-classifier.html)
I have not found anywhere any information about how can clearly emphasize that this class is private. Do you know if such a method exist at all? If yes I'll be grateful you give me some link here or something?
Just to keep things clear, a sample code:
public class DataStrucure {
// fields, methods, etc
private class InnerOddIterator{
// ...
};
}
From UML point of view. If classifier (Class also) is nested in other class, nesting class plays role of namespace. In this case nested classes are hidden (private) in context namespace. it means, your diagram implicitly defines private inner class definition.
here is part of definition from UML Superstructure section structred classifiers:
"A class acts as the namespace for various kinds of classifiers defined within its scope, including classes. Nesting of
classifiers limits the visibility of the classifier to within the scope of the namespace of the containing class and is used for
reasons of information hiding. Nested classifiers are used like any other classifier in the containing class."
First of all: You have something in your code and asking for an UML representation. But, IMHO, you should look at it the other way round: How can that UML-idea be represented in code. (Some programming languages don't even offer private nested classes...).
As for private nested classes: I suggest using a Composition. It is stronger as Association but not as strong as inheritance. And the composed class can not exist without its composer. Pretty much exactly a private nested class.
The drawing is taken from http://www.uml-diagrams.org/association.html:
In order to indicate that your inner class is privete the best, for me, is to use - character as depicted below but of course in this case you miss the internal structure of your inner class..
I have been facing so many problem using the anonymous class like I can't perform the instanceOf test neither can I implements multiple interface, so could someone please explain what I can or can not do with the anonymous class in java ?
The purpose of an anonymous inner class is to extend and instantiate an existing class or implement a single interface in one step.
Its limitations can be derived from the above:
Only one non-final class can be extended or one interface implemented.
Only final local variables of the enclosing method can be accessed. (This is due to the fact that normal local variables will be out of scope by the time any methods of the inner class will be invoked.)
You can't define a constructor. (The class has no name.)
If you need multiple interfaces, you can use a local inner class, which is like a normal inner class, with its own name, but defined within a method. I have to admit I've never seen it used in practice and I see very little reason for anyone to do so, hopefully someone will come up with an example.
Anonymous classes work whenever
you never need to refer to the class itself
you only need to extend a single class or implement a single interface
...but other than that there aren't really any significant constraints. This works fine in a lot of cases: for example, many cases when you're defining callbacks, listeners, or the like.
I have an anonymous inner class inside another class (SomeClass).
Both SomeClass.class.getClasses() and SomeClass.class.getDeclaredClasses() return empty arrays.
I couldn't find some hints on this in Class' Javadocs.
Can anonymous inner classes be retrieved using reflection in some way?
What else are notable differences between anonymous inner classes and normal inner classes?
You could try a brute force search of Class$1 ... Class$n until you can't find any more.
If it's using reflection, it's probably a really bad idea. Leaving that aside, I believe you can additional inner classes at runtime, so it doesn't make sense to list classes that may not have been thought of yet. Listing currently loaded classes would, I guess, require going through Java agents or similar.
Anonymous inner classes have made up names, an enclosing method and additional synthetic fields for copying external local variables that have been copied. One class is pretty much the same as another at runtime. Remember that 1.1 introduced inner classes, but class files have barely changed since 1.0.