What is the purpose of an inner class - java

I am reading about inner classes in an interface and class. I could not understand about the real use. However I dont want to discuss anything about inner classes inside an interface in this post.
I have used inner classes as a callback till now. I can do the same declaring the class outside somewhere.
Suppose that I have a list of students and I want to sort them by id. I have to implement Comparator interface and provide it as an argument to Collections's sort method.
public class StudentList {
public static void main(String[] args) {
List<Student> students = new ArrayList<Student>();
Student student = new Student();
student.setId(1);
student.setName("Krishna");
students.add(student);
student = new Student();
student.setId(2);
student.setName("Chaitanya");
students.add(student);
Collections.sort(students, new StudentList().new MyComparator());
}
public class MyComparator implements Comparator<Student> {
#Override
public int compare(Student o1, Student o2) {
if (o1.getId() < o2.getId()) {
return 1;
} else if (o1.getId() > o2.getId()) {
return -1;
} else {
return 0;
}
}
}
}
I can do the same like this also
public class StudentList {
public static void main(String[] args) {
List<Student> students = new ArrayList<Student>();
Student student = new Student();
student.setId(1);
student.setName("Krishna");
students.add(student);
student = new Student();
student.setId(2);
student.setName("Chaitanya");
students.add(student);
Collections.sort(students, new MyComparator());
}
}
class MyComparator implements Comparator<Student> {
#Override
public int compare(Student o1, Student o2) {
if (o1.getId() < o2.getId()) {
return 1;
} else if (o1.getId() > o2.getId()) {
return -1;
} else {
return 0;
}
}
}
I dont think inner class in the above example adds any significant importance unless it is declared as a private class. When I declare it as private, only the enclosing class can use it. It means the class is strongly binded with the enclosing class and I see some advantage of having so.
Can anyone please explain me the true importance/significance of using/writing inner classes in an application.

You should inner classes if you need something specific to the class your working with. A good example of an inner class can be found here: java.awt.geom.Ellipse2D and the corresponding Ellipse2D.Double and Ellipse2D.Float (Ellipse2D source code). You could place those classes in a package, but they make a lot more sense as nested classes. They directly correspond to Ellipse2D and will have no use elsewhere; also, the fact that they are nested improves readability in code that uses them. On another note, if an inner class is very likely to be useful when more general, it is often better to generalize it and make a regular class.
Also, inner classes can directly access variables in the outer class. That means that an inner class can be used to change the outer class. It is still possible to get an instance of it to be used outside of either class. To illustrate what I am saying:
public class Example {
public static void main(String[] args) {
Foo foo = new Foo();
Foo.Bar bar = foo.getBar(); //note, cannot call new Foo.Bar(); as Bar is dependent on Foo
for (int i = 0; i < 50; i++){
System.out.println(bar.get());
}
}
}
class Foo {
int val;
Bar b;
public Foo(){
b = new Bar();
}
public Bar getBar(){
return b;
}
public class Bar{
public Bar(){
val++;
}
public int get(){
return val++;
}
}
}
Another possible use of inner classes is to create something like a wrapper class for an the truly wanted inner class, especially useful for a recursive class. This is used for implementing a LinkedList. At one time, I implemented such a list, not realizing that anything of the sort had been made before. The idea is that you have your LinkedList class, and a Node class within it (where each node only points to the next/previous node and holds a single value). Doing it this way simplifies the code. However, it doesn't make any sense for the Node class to be external to LinkedList, because what type of "node" would it be? Thus it should be an internal class.

There are two advantages that I see. I haven't used them myself too much so there are just my observations.
If inner class is very small, it might be more easy to define as inner rather than creating a separate file for it. It would help in manageability in big projects which already have too many files.
Second, if inner class can only be used in it's parent class's context, defining it as inner class would give it namespace containing parents class.
public class FileProcessor {
public class Output {
//will be namespaced as FileProcessor.Output, more readable.
}
}
From answer Inner Class. What is its purpose?
So what does this gain us? Well, the inner class instance has access
to the instance members of the containing class instance. These
enclosing instance members are referred to inside the inner class via
just their simple names, not via this (this in the inner class
refers to the inner class instance, not the associated containing
class instance)
Also see What are the uses of inner classes in Java? Are nested classes and inner classes the same?

Some classes don't make make much sense on their own - they only make
sense in the context of another class. Inner classes are helpful at
defining this kind of relationship - they allow the developer to
express the relation between highly cohesive classes more explicitly.
see more
As an example consider a Node in a Graph. A Node has a list of peer
Nodes which it can reach itself. It makes sense to define a Peer class
as an inner class of Node. For example:
public class Node
{
private String name;
private List peers = new ArrayList();
private Node( String name )
{
this.name = name;
}
/**
* Represents a peer node that is reachable from this node
*/
class Peer
{
private Node node;
private int distance;
}
}

Purpose of Inner class
Inner classes represent a special type of relationship that is it can access all the members (data members and methods) of outer class including private.
Nested classes can lead to more readable and maintainable code because it logically group classes in one place only.

An example of when inner classes are necessary
Suppose you have a Java GUI (Graphical User Interface) class that acts as a chat client like Gchat or Facebook Chat. Think about what methods would need to be present in a class like that which represents a chat client – you will need a method that will read user input from the chat box, methods to actually send the user input to the server and to whoever the user is chatting with, even a method that detects that you are typing so that Gchat can display the “XZY is typing” text to your friends, etc.
There are two types of methods needed in our example
So, it should be clear that there will need to be two different types of methods that will drive your chat client application: 1. Chat client specific methods like those that will read user input from the chat box and send user input to the server. 2. Event handling methods that will respond to actual events that occur in the chat client window – like hitting the “RETURN” key, detecting consistent typing, etc.
Because it’s clear that there will need to be two different types of methods, then from an Object Oriented Design perspective, it seems like we should have two different classes: one class for the chat client specific methods and one class for the event handling methods. That does follow the normal object oriented design practices – because we are creating classes that specialize in what they do.
The problem with having two separate classes
But, in this particular example, there is a problem with having two separate classes. And that problem is the fact that the event handling code is very much related/tied to the code that belongs to the chat client. This makes sense, as we talked about earlier with our GChat example; as soon as a user in GChat hits “RETURN” or “ENTER” on the keyboard that should trigger an event, which should then grab the text from the chat client window. And, the chat client window would be a particular instance (basically an object) of the chat client class. For example, if you are talking to your friend Bob in GChat, he will have one window in Gmail and you will have one window open in Gmail, and each window is an object of the chat client class. So there will be two separate objects of the chat client class – one for you and one for Bob.
Now, if Bob types something and hits the RETURN key, the event handler code that responds to the RETURN key being pushed will need to be able to communicate with Bob’s chat client class object so that it can grab the text from Bob’s chat client class window, or the text field where that text is actually stored. The key here is thinking in terms of objects – an object of the chat client class is created for each person using GChat, so you will have your own object and Bob will have his own object. This means that the event handling code will need to access an chat client object’s text field – which is a member of the class, and an instance variable. So, it should be clear that the event handling code needs access to the members of a chat client class object in order to be able to effectively help.
Why don’t we just combine the event handling code with the chat client code?
Combining the event handling methods with the chat client specific methods in one big class sounds like a good idea at first, but there is one big problem: If both the event handling code and the chat client code need to inherit some code from different classes then you are in trouble, because Java does not support multiple inheritance – meaning that our one “big class” can not inherit from two different classes.
Inner classes to the rescue
Now, this is why inner classes were created – for situations exactly like the one we described above. An instance of an inner class can access members of an instance of the outer class, because an inner class is just another member of the outer class. And, inner classes can even access the private members of the outer class – yes you did read that correctly!
Read this - When should inner classes be used in Java?

Static Inner class reaches private static fields of Outer classes. It means that if I extend Outer.Inner class anywhere,(because Inner is static, I don't have to make object before extend) I cannot reach the private fields of Outer class. This is perfectly good for context security.

1) Nested classes represent a special type of relationship that is it can access all the members (data members and methods) of outer class including private.
2) Nested classes are used to develop more readable and maintainable code because it logically group classes and interfaces in one place only.
3) Code Optimization: It requires less code to write.

I will give my explanation from a different point of view. Please first check out the memory model of Java's inner class. Then with some basic skills in programming, you will know why bother using inner class.
See How inner class object resides in memory?
Besides, usually you should instantiate the inner class object in outer class's constructor to "make sense", and sometimes you can provide a getter method to retrieve the inner class instance which resides in outer class instance if you really want to mess with that inner class instance.

Related

Java class hierarchy refactoring without changing the invoking code, is it possible?

Current situation:
in a Java system, we have a class named Passenger as below, let's say,
public Class Passenger{
//lots of member fields
private String firstName ;
private String lastName ;
private WhatEverAttribute att;
//lots of getters & setters
WhatEverAttribute getAtt(){ return att;}
void setAtt(WhatEverAttribute attIn){ this.att=attIn;}
...
//and lots of methods,for example
List<String> doWhatEverFuction(...){ return ... }
...
}
And in the application elsewhere there are a many places will create and use this class as:
Passenger p1 = new Passenger();
p.setFirstName("blablabla")
p.setAtt(xxx);
Passenger p2 = new Passenger();
p2.setAtt(yyy)
List retl = p2.doWhatEverFuction(...);
...
The system previously only manage Air/Flight passengers, so the Passenger
class is actually data model for air passengers,
Now the problem is, we need to extend the model and make a hierarchy, as the Passenger will be a generic Passenger model, holding common fields and functions, new model AirPassenger and SeaPassenger will extend it:
enter image description here
So some common fields and functions will be kept
in Passenger to share between AirPassenger and SeaPassenger, but most air passenger specific fields and functions will be pushed down to AirPassenger,
then everybody knows that I have to change the existing code accessing Passenger from
Passenger p = new Passenger();
p.xxxxxx();
to
AirPassenger p = new AirPassenger();
p.xxxxxx();
There are so many places and I don't want to manually change them in many places in existing code accessing Passenger from the whole application,
What I want is after making the hierachy, the rest of the code still working without any changes, by utilizing some tricks of technics, I could return
an AirPassenger through the new Passenger() constructor like:
Passenger{
Passenger(){
return Passenger("Air")
}
Passenger(String type){
Switch(type){
...
case "Air": return new AirPassenger();
...
}
}
}
by some dynamic features of Java, CGLIB or whatever, is it possible?
The approach you end up choosing will depend on many factors, largely how and where your code is being used. If all usages of this class are accessible to you, I would highly advise against your proposed solution - a proper inheritance hierarchy would help keep your code organized and make it possible to easily expand your program in the future. Many IDEs (e.g IntelliJ) offer great functionality for smart-refactoring of your code and extraction to new classes, that will do almost all the work automatically and ensure the code keeps running as intended.
If possible, your situation is a classic case for the use of an abstract parent class. Since there is no such thing as a "general passenger", a more correct design for your hierarchy would be to declare Passenger as an abstract class. This way instances of Passenger cannot be created directly, but the class itself can hold implementations which inheriting classes can use or override as necessary.
You can also add a factory method to this class, which will return a new Passenger of the correct type, according to input (as you suggested).
Edit:
Polymorphism and class hierarchy work in Java in a very particular way. That is, some limitations are put on the programmer to maintain code readability and modularity.
What you have asked for (in your clarification comments) is not possible in the way you are describing.
You create two new classes:
class AirPassenger extends Passenger {
...
public void doSomethingAir() {
...
}
...
}
class SeaPassenger extends Passenger {
...
public void doSomethingSea() {
...
}
...
}
You refactor some of its methods into the new AirPassenger class and leave some where they are.
The first thing you will notice, is that you cannot use the existing Passenger constructor to return instances of AirPassenger or SeaPassenger, since a constructor is a
void method and has no return value. You will therefore need to provide some construction Factory method to create instances of either AirPassenger or SeaPassenger.
Passenger createPassenger(String passengerType) {
switch (passengerType) {
case "sea":
return new SeaPassenger();
default:
return new AirPassenger();
}
}
You refactored methods out of Passenger and into AirPassenger. These methods no longer exist in the Passenger class, and they cannot be called by Passenger objects.
You can however use explicit type casting to re-cast all Passenger objects to AirPassenger, and then you will be able to use all the methods which are now in AirPassenger.
This can also be done using a single method:
AirPassenger convertToAirPassenger(Passenger passenger) {
return (AirPassenger) passenger;
}
Of course I can find & replace, and most IDE can do it,
but problem is in the system there are some configuration file, and txt file, work as dictionary, and templates you know, they use the Passenger word or add prefix and suffix, or lower case, you know, you can not just find and replace, so not only Java code changes needs to be made, so I would rather not change them if there is a way, that is my question.
//you create an instance of class
ClassA obj = new ClassA();
//you call method doIT() inside ClassA
obj.doIt();
Now I have to re-model it as ClassA becomes a superclass, and those methods push down into its subclass, let's say ClassB, so ClassB extends ClassA, method doIt() is inside
ClassB now,
everyone knows as usual I need to change the above code to
//you create an instance of ClassB,
ClassB obj = new ClassB();
//or ClassB obj = new ClassA(); you have little code in the ClassA constuctor, etc.
//then you call a method
obj.doIt();
I know that, but my question is, without make changes to it
ClassA obj = new ClassA();
obj.doIt();
is there any tricks that will make it works with the new model?

Why private members of nested class are accessible in outer class [duplicate]

I observed that Outer classes can access inner classes private instance variables. How is this possible? Here is a sample code demonstrating the same:
class ABC{
class XYZ{
private int x=10;
}
public static void main(String... args){
ABC.XYZ xx = new ABC().new XYZ();
System.out.println("Hello :: "+xx.x); ///Why is this allowed??
}
}
Why is this behavior allowed?
The inner class is just a way to cleanly separate some functionality that really belongs to the original outer class. They are intended to be used when you have 2 requirements:
Some piece of functionality in your outer class would be most clear if it was implemented in a separate class.
Even though it's in a separate class, the functionality is very closely tied to way that the outer class works.
Given these requirements, inner classes have full access to their outer class. Since they're basically a member of the outer class, it makes sense that they have access to methods and attributes of the outer class -- including privates.
If you like to hide the private members of your inner class, you may define an Interface with the public members and create an anonymous inner class that implements this interface. Example bellow:
class ABC{
private interface MyInterface{
void printInt();
}
private static MyInterface mMember = new MyInterface(){
private int x=10;
public void printInt(){
System.out.println(String.valueOf(x));
}
};
public static void main(String... args){
System.out.println("Hello :: "+mMember.x); ///not allowed
mMember.printInt(); // allowed
}
}
The inner class is (for purposes of access control) considered to be part of the containing class. This means full access to all privates.
The way this is implemented is using synthetic package-protected methods: The inner class will be compiled to a separate class in the same package (ABC$XYZ). The JVM does not support this level of isolation directly, so that at the bytecode-level ABC$XYZ will have package-protected methods that the outer class uses to get to the private methods/fields.
There's a correct answer appearing on another question similar to this:
Why can the private member of an nested class be accessed by the methods of the enclosing class?
It says there's a definition of private scoping on JLS - Determining Accessibility:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Thilo added a good answer for your first question "How is this possible?". I wish to elaborate a bit on the second asked question: Why is this behavior allowed?
For starters, let's just be perfectly clear that this behavior is not limited to inner classes, which by definition are non-static nested types. This behavior is allowed for all nested types, including nested enums and interfaces which must be static and cannot have an enclosing instance. Basically, the model is a simplification down to the following statement: Nested code have full access to enclosing code - and vice versa.
So, why then? I think an example illustrate the point better.
Think of your body and your brain. If you inject heroin into your arm, your brain gets high. If the amygdala region of your brain see what he believe is a threat to your personally safety, say a wasp for example, he'll make your body turn the other way around and run for the hills without You "thinking" twice about it.
So, the brain is an intrinsic part of the body - and strangely enough, the other way around too. Using access control between such closely related entities forfeit their claim of relationship. If you do need access control, then you need to separate the classes more into truly distinct units. Until then, they are the same unit. A driving example for further studies would be to look at how a Java Iterator usually is implemented.
Unlimited access from enclosing code to nested code makes it, for the most part, rather useless to add access modifiers to fields and methods of a nested type. Doing so is adding clutter and might provide a false sense of safety for new comers of the Java programming language.
An IMHO important use case for inner classes is the factory pattern.
The enclosing class may prepare an instance of the inner class w/o access restrictions and pass the instance to the outside world, where private access will be honored.
In contradiction to abyx declaring the class static doesn't change access restrictions to the enclosing class, as shown below. Also the access restrictions between static classes in the same enclosing class are working. I was surprised ...
class MyPrivates {
static class Inner1 { private int test1 = 2; }
static class Inner2 { private int test2 = new Inner1().test1; }
public static void main(String[] args) {
System.out.println("Inner : "+new Inner2().test2);
}
}
Access restrictions are done on a per class basis. There is no way for a method declared in a class to not be able to access all of the instance/class members. It this stands to reason that inner classes also have unfettered access to the members of the outer class, and the outer class has unfettered access to the members of the inner class.
By putting a class inside another class you are making it tightly tied to the implementation, and anything that is part of the implementation should have access to the other parts.
The logic behind inner classes is that if you create an inner class in an outer class, that's because they will need to share a few things, and thus it makes sense for them to be able to have more flexibility than "regular" classes have.
If, in your case, it makes no sense for the classes to be able to see each other's inner workings - which basically means that the inner class could simply have been made a regular class, you can declare the inner class as static class XYZ. Using static will mean they will not share state (and, for example new ABC().new XYZ() won't work, and you will need to use new ABC.XYZ().
But, if that's the case, you should think about whether XYZ should really be an inner class and that maybe it deserves its own file. Sometimes it makes sense to create a static inner class (for example, if you need a small class that implements an interface your outer class is using, and that won't be helpful anywhere else). But at about half of the time it should have been made an outer class.
Inner class is regarded as an attribute of the Outer class. Therefore, no matter the Inner class instance variable is private or not, Outer class can access without any problem just like accessing its other private attributes(variables).
class Outer{
private int a;
class Inner{
private int b=0;
}
void outMethod(){
a = new Inner().b;
}
}
Because your main() method is in the ABC class, which can access its own inner class.

How to deal with arrays of static objects?

I'm having an issue dealing with static object types in a parser I'm writing.
glob = new func("glob");
glob.addChild(new func("wrong"));
System.out.println(glob.name);
func is a static class that I'm referencing in the above code within main. When this code is run, the printed text is "wrong". I'm assuming that making func static as I did is causing there to only ever be one func allowed, and it's being overwritten since I can't create instances of func. Is there a way around this? Here's part of the code for the declaration of func for reference
static class func{
public func (String name){
//etc
}
}
This is becoming an issue because I want to be able to create a nest of these objects to use for determining scope within a parser. func would have children, and the idea was that a child node could look for a 'variable' (here just a string) that I add first within itself, then within its parent, and so on down the line. Creating children just overwrited the parent though.
Update: People wanted more code from func
static class func{
public static func[] children;
public String name;
public static func parent;
private static int child_index, var_index;
private static String[][] vars;
public func (String name, func parent){
children = new func[50];
//etc
}
}
You're right that I did have a static name. If I remove that, my worry is that the vars/children arrays will still continue to be overwritten, and removing those gives me a lot of 'non-static variables cannot be referenced...' messages.
The static modifier on a class doesn't do the same thing as static on other entities. First of all, you can't apply static to a top-level class at all. It's only useful for a class defined inside another class:
public class Outer {
public class Inner {
...
}
static public class Nested {
...
}
}
The difference is that whenever you create an object of class Inner, the object "belongs", in a sense, to some object of an Outer class. The Inner object contains a reference to some Outer object, and its methods can reference fields of the Outer object to which it belongs.
The Nested class, however, is more like a top-level class; the main difference is that outside classes can refer to it as Outer.Nested, which can be useful when you want several different nested classes all named Nested. It's a way to avoid "polluting the namespace" with top-level class names, and to make it clear that a Nested is somehow closely related to an Outer. Also, because of Java's rules about visibility, a Nested class's methods can access private members of Outer, which an outside top-level class can't do.
But it doesn't mean you can create only one Nested. If you want a class that can have only one object, use a singleton pattern. (But also think about whether you really want to do this and why; singleton patterns are disdained by some programmers, probably because they look too much like global variables, which reduces the flexibility to make certain kinds of changes to your program in the future.) (P.S. After trying to read your question more carefully, I'm not sure that a singleton is what you want, and in fact I'm not clear at all on what your design is supposed to look like.)
It is meant to be so, since a static variable is a variable owned by a Class and not instances of that Class and it is so for inner static classes.
Otherwise I can't see how did you manage to make your func class static since as far as I know Java do not allow Top-level classes to be static and only inner classes can be so.
I can't see clearely what you are aiming to achieve but you should reconsider your design. Maybe with better explanation someone could bring some help.

Instantiation of Outer Class From Inner Class Instance?

I have found below example in one of the answers:
Java inner class and static nested class
public class Container {
public class Item{
Object data;
public Container getContainer(){
return Container.this;
}
public Item(Object data) {
super();
this.data = data;
}
}
public static Item create(Object data){
// does not compile since no instance of Container is available
return new Item(data);
}
public Item createSubItem(Object data){
// compiles, since 'this' Container is available
return new Item(data);
}
}
I want to know why we do something like this: i.e. To get the instance of container why we create the instance of inner class? What is the use of this approach? Which design pattern it is?
The above approach is already being used in one of the maintainance project, and I still didnt get whats the use of it?
The main purpose of this construct is the management of data. That the inner class hands out references to the "container" is just an unimportant implementation detail.
The problem with abstract and abridged examples like yours is: You just transfer the "how" from the writer to the reader of the code. But the "why" is completely lost.
So you can just replace Container with FileSystem and Item with File and data with some more internal state to a file. Then you can see:
A filesystem can have one or more files.
A file is exactly in one filesystem.
The lifetime of the File cannot exceed the lifetime of the filesystem.
The implementation between File and Filesystem is tightly coupled - each one might call the other - even private methods.
The last point is IMO the most important one: You can offer the slim and safe public API to the real user while File and Filesystem can use dangerous private methods of each other. In case of a Filesystem you don't want to grant anyone else access to these dangerous methods.
These traits are common for some problems - hence they are used.
I want to know why we do something like this: i.e. To get the instance of container why we create the instance of inner class?
That is not what is happening.
In fact, you cannot create the instance of the inner class Item unless you already have an instance of the outer class Container on which you can call the createSubItem method. Creating the inner class instance doesn't create a new instance of the outer class. Rather it creates it in the context of the existing instance ... the one that is "available" when you invoke the inner classes constructor.
the method in question is defined as static so it can access only static members of the class and since the Item class is not declared as static inner class it can't be accessed from a static function.
I am not sure about this specific design pattern or why it is required but this can work:
public static Item create(Object data) {
Container c = new Container();
return c.new Item(data);
}
One of the places we have used such design is just for having additional Comparator classes.

Why can outer Java classes access inner class private members?

I observed that Outer classes can access inner classes private instance variables. How is this possible? Here is a sample code demonstrating the same:
class ABC{
class XYZ{
private int x=10;
}
public static void main(String... args){
ABC.XYZ xx = new ABC().new XYZ();
System.out.println("Hello :: "+xx.x); ///Why is this allowed??
}
}
Why is this behavior allowed?
The inner class is just a way to cleanly separate some functionality that really belongs to the original outer class. They are intended to be used when you have 2 requirements:
Some piece of functionality in your outer class would be most clear if it was implemented in a separate class.
Even though it's in a separate class, the functionality is very closely tied to way that the outer class works.
Given these requirements, inner classes have full access to their outer class. Since they're basically a member of the outer class, it makes sense that they have access to methods and attributes of the outer class -- including privates.
If you like to hide the private members of your inner class, you may define an Interface with the public members and create an anonymous inner class that implements this interface. Example bellow:
class ABC{
private interface MyInterface{
void printInt();
}
private static MyInterface mMember = new MyInterface(){
private int x=10;
public void printInt(){
System.out.println(String.valueOf(x));
}
};
public static void main(String... args){
System.out.println("Hello :: "+mMember.x); ///not allowed
mMember.printInt(); // allowed
}
}
The inner class is (for purposes of access control) considered to be part of the containing class. This means full access to all privates.
The way this is implemented is using synthetic package-protected methods: The inner class will be compiled to a separate class in the same package (ABC$XYZ). The JVM does not support this level of isolation directly, so that at the bytecode-level ABC$XYZ will have package-protected methods that the outer class uses to get to the private methods/fields.
There's a correct answer appearing on another question similar to this:
Why can the private member of an nested class be accessed by the methods of the enclosing class?
It says there's a definition of private scoping on JLS - Determining Accessibility:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Thilo added a good answer for your first question "How is this possible?". I wish to elaborate a bit on the second asked question: Why is this behavior allowed?
For starters, let's just be perfectly clear that this behavior is not limited to inner classes, which by definition are non-static nested types. This behavior is allowed for all nested types, including nested enums and interfaces which must be static and cannot have an enclosing instance. Basically, the model is a simplification down to the following statement: Nested code have full access to enclosing code - and vice versa.
So, why then? I think an example illustrate the point better.
Think of your body and your brain. If you inject heroin into your arm, your brain gets high. If the amygdala region of your brain see what he believe is a threat to your personally safety, say a wasp for example, he'll make your body turn the other way around and run for the hills without You "thinking" twice about it.
So, the brain is an intrinsic part of the body - and strangely enough, the other way around too. Using access control between such closely related entities forfeit their claim of relationship. If you do need access control, then you need to separate the classes more into truly distinct units. Until then, they are the same unit. A driving example for further studies would be to look at how a Java Iterator usually is implemented.
Unlimited access from enclosing code to nested code makes it, for the most part, rather useless to add access modifiers to fields and methods of a nested type. Doing so is adding clutter and might provide a false sense of safety for new comers of the Java programming language.
An IMHO important use case for inner classes is the factory pattern.
The enclosing class may prepare an instance of the inner class w/o access restrictions and pass the instance to the outside world, where private access will be honored.
In contradiction to abyx declaring the class static doesn't change access restrictions to the enclosing class, as shown below. Also the access restrictions between static classes in the same enclosing class are working. I was surprised ...
class MyPrivates {
static class Inner1 { private int test1 = 2; }
static class Inner2 { private int test2 = new Inner1().test1; }
public static void main(String[] args) {
System.out.println("Inner : "+new Inner2().test2);
}
}
Access restrictions are done on a per class basis. There is no way for a method declared in a class to not be able to access all of the instance/class members. It this stands to reason that inner classes also have unfettered access to the members of the outer class, and the outer class has unfettered access to the members of the inner class.
By putting a class inside another class you are making it tightly tied to the implementation, and anything that is part of the implementation should have access to the other parts.
The logic behind inner classes is that if you create an inner class in an outer class, that's because they will need to share a few things, and thus it makes sense for them to be able to have more flexibility than "regular" classes have.
If, in your case, it makes no sense for the classes to be able to see each other's inner workings - which basically means that the inner class could simply have been made a regular class, you can declare the inner class as static class XYZ. Using static will mean they will not share state (and, for example new ABC().new XYZ() won't work, and you will need to use new ABC.XYZ().
But, if that's the case, you should think about whether XYZ should really be an inner class and that maybe it deserves its own file. Sometimes it makes sense to create a static inner class (for example, if you need a small class that implements an interface your outer class is using, and that won't be helpful anywhere else). But at about half of the time it should have been made an outer class.
Inner class is regarded as an attribute of the Outer class. Therefore, no matter the Inner class instance variable is private or not, Outer class can access without any problem just like accessing its other private attributes(variables).
class Outer{
private int a;
class Inner{
private int b=0;
}
void outMethod(){
a = new Inner().b;
}
}
Because your main() method is in the ABC class, which can access its own inner class.

Categories

Resources