Subclassing Inner Class from Outer Class versus other Inner Class - java

I am befuddled why this is allowed
public class Foo {
class Bar extends Foo {
}
}
Yet this is not allowed
public class Foo {
class Bar extends Foo {
}
class Fooey extends Bar {
}
}
The compiler informed that it can not reference Fooey.this before supertype constructor has been called.
And this is allowed
public class Foo {
static class Bar extends Foo {
}
class Fooey extends Bar {
}
}
What is going on here? And where can I go to find more information on how inner class inheritance works?
EDIT I came upon both rather poor ideas; inner class extends outer class and inner class extends other static inner class. I wasn't sure what exactly was going and how I should refactor this. I ended up just yanking out the inner classes and encapsulating them in the outer class.

First of all: Don't do this sort of thing. It's evil. Really, Java 1.1 should have been specified very much more restrictively, IMO.
There is confusion about which this to use from the Foo.Fooey constructor. The outer this (Foo.this) would work. But the actual this is a Foo but it can't be passed to the superconstructor because of rules about using this before the superconstructor returns (and besides having an outer instance the same instance as the inner instance is fecked up). The outer this on the superclass "((Bar)this).this$0" (IIRC), is also inaccessible due to restrictions on use of this.
The solution is to be explicit. Explicit is usually a good thing in my book (unless it becomes boilerplate).
public class Foo {
class Bar extends Foo {
}
class Fooey extends Bar {
Fooey() {
Foo.this.super();
}
}
}
Better yet, don't have an inner class extend its own outer class, or extend any inner class.

I guess the JLS and the answers to this question are a starting point
Java inner class and static nested class
Inner Classes and Enclosing Instances

Tom Hawtin answer is correct.
Have also a look at java puzzler. The sample chapter contains this case and a few other "interesting" case you may want to have a look at.

(Can't comment yet - I need 50 rep)
I'm also befuddled that this is allowed. A (non-static) inner class of an outer class is actually a member of that outer class. Read: an inner object is a member of its outer object. (Incidentally, every outer object must own an inner object but this is besides the point.)
The analogy I like to use is this: let Car be the outer class and let Wheel be the inner class. Every instance of Car must, and does, have at least one instance of Wheel as a member.
Now it doesn't make conceptual sense for an inner class to extend an outer class. I can't think of any real-world situations that call for an object being both a member and a type of another object. Set Theorists will recall the Axiom of Regularity and its consequences.
Think of it this way: Let Honda extend Car, and let Honda be an inner class nested inside Car. What you're saying here is that every Honda object is a Car object (duh), and every Car object has a Honda object. Only one of these statements makes sense, but both are allowed to be true in Java.
Or back to the previous analogy, you shouldn't let Wheel extend Car because then a Wheel would be a Car, and by definition must have another Wheel, which by the way is a Car and so must have a Wheel and forever and ever Amen. Constructing a Car object would result in an infinite loop of nested objects.
I'm upset that this is legal and does not produce a compile-time error.

Related

Static inner class vs Companion's inner class

Reading chapter 20 of Ordesky's book on Scala, I found that inner classes are path dependant. Among other features, that implies that they can only be instantiated within the outer class or giving an outer class instance.
The question arises: I would like to implement an static inner class in Scala but the author suggest that is not possible.
I immediatelly thought of making the "inner class" (lets call it Inner) a member of Outer's companion object.
The accepted answer of this question seems to point towards that direction.
But that drives to a problem: Inner's type ins't Outer#Inner, I could try something like:
object Outer {
class Inner extends Outer#Inner { }
}
This doesn't work however. Do you know a work arround for this?
I have the hunch that it could be done with abstract types but I am not sure.
Note that making Inner an inner class of the companion objects is not exactly as having a non-path-dependant Inner class because of its type.
I immediatelly thought of making the "inner class" (lets call it Inner) a member of Outer's companion object.
Yes, that's the closest Scala equivalent.
But that drives to a problem: Inner's type ins't Outer#Inner
This isn't a problem, because Outer#Inner is equivalent to a non-static inner class of Outer in Java. I.e. it has a reference to an Outer object.
I would like to get a inner class which is not path dependant or, at least, to know if that is possible
If you want to create a non-companion inner class which can't be used path-dependently, it isn't possible. You are free to always write Outer#Inner instead of o.Inner in your code, of course.

Eclipse showing two THIS$0 fields for a nested class (Java)

I have been facing an odd phenomena that I don't quite understand. I have an abstract class that is extended by several other classes. the abstract class is a type of special collection and it has a nested abstract iterator class that fits it. Every class that extends the abstract collection class, also has a nester iterator class that extends the orginal abstract iterator.
The abstract class is something like this:
public abstract class AbstractMultiCollection<T> {
public AbstractMultiCollection() {
...
}
MultiIterator<T> iterator();
public abstract class AbstractMultiIterator {
public AbstractMultiIterator() {
...
}
The extending classes are something like this:
public class MajorityMultiCollection<T> extends AbstractMultiCollection<T> {
...
public MultiIterator<T> iterator() {
return new MajorityIterator();
}
...
public class MajorityIterator extends AbstractMultiIterator {
public MajorityIterator() {
super();
...
}
public T next() {
...
}
Simply put, the collections extend the abstract collection and their nested iterators extend the nested abstract iterator.
I have two problems that I don't understand and would appreciate clarification on:
When I debug my code, the "return new MajorityIterator();" lines raise a "Source Not Found" error and "ClassNotFound" exception in the eclipse debugger and a bunch of "ClassLoaderExt" exceptions that I don't understand.
I noticed that every "MajorityIterator" has two "This$0" fields, containing the collection he belongs to. one is null at first, but receives the collection once I invoke the "super();" builder.
I failed to find the reason for this, can anyone clarify? Thanks in advance!
Actually having two this references makes sense. One thing most people do not realize is how the Java compiler implements non-static nested classes:
It implicitly adds a new field with the type of the outer class, lets call it outer$object.
It implicitly adds a new argument for the outer class object to all constructors to fill in that field. Incidentally, that means that the default constructor of the inner class actually has a parameter, which makes using it via reflection significantly more complex.
It implicitly creates constructors and methods with wider visibility to get around any accessibility issues if e.g. the inner class is declared private.
Since the outer$object field needs to have the same type as the outer class, one will be added each time a nested class inherits from a class that is not nested within the same outer class.
Personally, I tend to avoid non-static non-anonymous inner classes, in order to keep everything explicitly on the surface, rather than let the compiler make a mess out of things...
A MajorityIterator object will indeed have two this$0 fields:
One (implicitly declared in MajorityIterator) for the reference to the enclosing instance of MajorityMultiCollection
One (implicitly declared in AbstractMultiIterator) for the reference to the enclosing instance of AbstractMultiCollection. This will be null until the super() call, as it'll be set in the constructor.
You might find it clearer to make these static nested classes, and explicitly pass in the reference to the enclosing instance instead - I suspect you only want one reference, and it'll be simpler to reason about.

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.

Java generics/abstract/innerclass syntax question

I've got the following:
public abstract class Foo<T>{
//contents of Foo //
...
public class Bar<Q> extends Foo<T>{
//contents of Foo.Bar //
...
}
}
Later, in another class and java file, I am trying to construct an instance of the inner Bar class above, using the outer abstract class as a supertype. To complicate things even more, the new class has it's own generic. The following does not work:
public class SomeOtherClass<A>{
private Foo<A> x;
public SomeOtherClass(){
x = Foo<A>.Bar<A>();
}
}
But this doesn't work; and neither do all the other combos that I've tried. So how do I go about instantiating x? Can it be done with out removing Foo's parameter? I don't want to remove Foo's parameter, because it's abstract methods have the generic parameter in their signatures.
To get an instance of the inner class you first need an instance of the outer class. As Foo in your example is abstract you can't instantiate the outerclass. Thus you also can't instantiate the innerclass.
For your example you can use the dirty trick (as there are no abstract methods to implement)
public class SomeOtherClass<A>{
private Foo<A> x;
public SomeOtherClass() {
//create anonymous extension of the abstract outer class
//for a real abstract class this would mean you have to
//implement all methods which are declared abstract
x = new Foo<A>(){};
x = x.new Bar<A>();
}
}
So actually you should ask yourself if your class structure is right, if you need access to a innerclass (Bar) of an abstract class (Foo) without really needing the enclosing class.
Aside from inquiry for exploration's sake, what's the motive for nesting Bar within Foo? This looks almost like how enum and Enum work, but without the behind-the-scenes compiler magic to hide most of the oddities.
If Foo is incomplete, it's meant to be extended from afar -- even if only from no farther than within its containing package (if the class wasn't declared public). The extensions being nested within the incomplete husk will only confuse potential clients.
If you share more detail about the actual problem domain, you'll likely summon plenty of specific replies as to how to better model the solution.
Bar is a non-static inner class of Foo. That means that you need an instance of Foo to construct an instance of Bar. If you don't want to need an instance of Foo, then Bar should be made a static inner class.

How do you resolve a circular dependency with an inner class?

(Java question)
If I reference a field in an inner class, does this cause a circular dependency between the enclosing class and the inner class?
How can I avoid this?
Here is an example:
public class Outer {
private Other o;
private Inner i;
public Outer() {
o = new Other();
i = new Inner() {
public void doSomething() {
o.foo();
}
};
}
}
Static vs instance class: If you declare the inner class as static then the instances of the inner class doesn't have any reference to the outer class. If it's not satic then your inner object efectivelly points to the outer object that created it (it has an implicit reference, in fact, if you use reflection over its constructors you'll see an extra parameter for receiving the outer instance).
Inner instance points outer instance: Circular reference is in case each instance points the other one. A lot of times you use inner classes for elegantly implementing some interface and accessing private fields while not implementing the interface with the outer class. It does mean inner instance points outer instance but doesn't mean the opposite. Not necesary a circular reference.
Closing the circle: Anyway there's nothing wrong with circular referencing in Java. Objects work nicely and when they're not more referenced they're garbage collected. It doesn't matter if they point each other.
The syntax you're using in the example is a little off there is no declaration of the class or interface Inner. But there isn't anything wrong with the concept of the example. In Java it will work fine.
I'm not sure what you're doing here, but you may want to consider a more simple design for maintainability etc.
It's a common pattern for anonymous event handlers to reference elements of their parent class, so no reason to avoid it if that's the case, that's how Java was designed instead of having function pointers.
(Not sure if this is what you are asking...)
At runtime, the inner class has an implicit reference to the instance of the outer class it belongs to. So whenever you pass the inner class instance around, you are also passing the outer class instance around.
You can avoid that by declaring the inner class as "static", but that means that the inner class can't access member variables of the outer class. So in that case if you want to access a member of the outer class, you need to pass it explicitly to the inner class (using a setter or using the constructor of the inner class).

Categories

Resources