Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm so confused that how could it be written like this... It creates an instance from another instance
st.new FirstLevel();
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
ShadowTest.FirstLevel mali = st.new FirstLevel();
}
}
Here, FirstLevel is a so-called inner class – that's because it is defined inside another class. Both relations (the 'outer' and the 'inner') are plain jane classes (and not interfaces, enums, or records). In this case, unless the inner class has the modifier static on it (and, in your code, it doesn't), then you get an instance inner class.
Such classes have a hidden field of the outer type associated with them. It is as if your FirstLevel class has this field:
private final ShadowTest outerInstance;
And each and every constructor of ShadowTest has a parameter for this field, but, it is hidden and a bit special.
Because this secret field exists, you can do things like invoke non-static methods from ShadowTest from within FirstLevel.
If you type new FirstLevel(), that just works... but only within non-static contexts inside ShadowTest. Anywhere else and the compiler will tell you that it doesn't know what instance of ShadowTest to pass along for that secret field. You can explicitly define which instance of ShadowTest. But not with new FirstLevel(shadowTestInstance), but with the somewhat weird-looking syntax shadowTestInstance.new FirstLevel(). But, it's the same thing: A parameter being passed to a constructor.
I generally advise that you do not use instance inner classes unless you really know they are the best fit for the case; this hidden field tends to cause confusion and surprises. I'd go so far as to say that you should never have instance inner classes; if you must hold a reference to an instance of the outer class, make it explicit (add an actual field, and make an actual parameter in your constructor). That way you avoid the surprises and confusion, at least. In other words, mark your FirstLevel class as static. By making your outer reference explicit, the shadowing thing also goes away; now you just have x or this.x referring to the x field in FirstLevel, and outerInstance.x for the outer field:
static class FirstLevel {
final ShadowTest shadow;
int x;
public FirstLevel(ShadowTest shadow) { this.shadow = shadow; }
}
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.ref.javaOO_nested
As per java syntaxes, unless it's a private or static class you could initialize it in the following way
class OuterClass {
...
class InnerClass {
...
}
}
Then a sample initialisation can be done so:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
NOTE: I have referred the block to the oracle java docs. You can read more there
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 months ago.
Improve this question
I have read multiple posts about how to instantiate one object of the type of the inner class after instantiating one from the outer class; for example: here and here.
However, non of them actually explain if you can have multiple instances of the inner class with a single outer class instance and, if so, what the use cases are.
For example, would it be beneficial to have a controller/handler class be an outer class and the class we want to handle the inner class? What are the pros and cons of this or similar approaches with not one but multiple instances of the inner classes over the pillars of OOP (using inheritance, abstraction, polymorphism, and encapsulation)?
I am specifically asking about multiple instances; all of this is covered for single objects of the inner classes here.
ps* all of the links are StackOverflow questions.
With both types of classes contained within another class, you're free to instantiate as many instances of the class as you want.
The only real difference between static and non-static (inner) classes is that inner classes have direct access to non-static members of a parent/containing class instance. You have to instantiate an inner class within the context of an instance of the containing class to allow for that association. Both types have access to static members of the containing class.
Said another way, inner classes contain a reference to the instance of the containing class that created them. They can therefore access members of the containing class that, being instance members, require a reference to an instance of that class.
Can non-static nested classes be instantiated multiple times. if so what are the use cases?
(1) To the first question, the answer is yes. And has been stated they have access to the enclosing classes instance fields.
(2) To the second question, because of (1) above, they are perfect for such things as creating an interator for a home grown data structure. Here is an example.
Note that the inner class has it's own index so it won't be shared among instantiations.
And it also has access to the private array in the enclosing class.
The Iterable interface allows support for the enhanced for loop.
public class MyDataDemo {
public static void main(String[] args) {
MyDataStructure<Integer> mds = new MyDataStructure<>(new Integer[] {1,2,3,4,5});
for(int val :mds) {
System.out.println(val);
}
System.out.println();
// or via an iterator instance.
Iterator<Integer> iter = mds.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
}
}
class MyDataStructure<T> implements Iterable<T> {
private T[] values;
public MyDataStructure(T[] values) {
this.values = values;
}
public class MyIterator implements Iterator<T>{
int index = 0;
#Override
public boolean hasNext() {
return index < values.length;
}
#Override
public T next() {
return values[index++];
}
}
#Override
public Iterator<T> iterator() {
return new MyIterator();
}
}
prints
1
2
3
4
5
1
2
3
4
5
If I have three classes as follows:
package com.Bob.Marley;
public class SuperClass{
protected int x = 0;
}
package com.Bob.Marley;
public class SubClass extends SuperClass{
protected int x = 1;
}
package com.Bob.Marley;
public class TestClass{
public static void main (String[] args){
SubClass s = new SubClass();
//print 1
System.out.println(s.x);
//how do I print the superclass variable?
//I know inside SubClass I can access it with plain old super.x
//but what about outside the subclass with a new object.
}
}
So the question is how would I print out 0 from the superclass of the new object s created in a separate class. System.out.println(s.super.x); does not work. I don't think it changes anything but I am using java 8.
The expression s.super.x is invalid here. Whenever you prefix a super.x with something, it should be a type name, not a variable name, e.g. SuperClass.super.x. However, this would be valid only inside the subclass for accessing the superclass of the enclosing class, which does not exist here.
Cast x to be a SuperClass so you can access the x declared in Superclass.
System.out.println( ((SuperClass) s).x);
or
SuperClass sc = (SuperClass) s;
System.out.println(sc.x);
This works because variable access is statically binded. The type of the variable or expression determines the scope searched for variable access.
TL;DR: if you introduce a new field in a subclass, don't re-use a field name from the parent class. You gain nothing, only confusion and problems.
If I understand correctly, you want SubClass instances to have two fields, one inherited from the SuperClass (for the discussion, let's rename that to superX to make things clearer), and one from the subclass itself (let's rename that to subX).
For a given SubClass instance, you want to be able to access both fields, superX and subX (of course, using different expressions). What makes things difficult in your code sample, is the fact that you chose to give both of them the same name x.
So, if you really want your instances to carry both fields, I'd recommend to rename them, so you don't have to use ugly tricks like casting to the SuperClass.
public class SuperClass{
protected int superX = 0;
}
public class SubClass extends SuperClass{
protected int subX = 1;
}
But, if x stands for the same property with the same meaning for both the super and the sub class, just with different initial values, then it doesn't make sense to have two different fields, and you should change the code to become:
public class SuperClass{
protected int x = 0;
}
public class SubClass extends SuperClass{
// constructor initializes the x field with 1.
public SubClass(){
x = 1;
}
}
Of course, then it's impossible to get two different values from a single instance of SubClass.
Hopefully this question hasn't already been asked. I've had a look around but haven't found a similar post.
Experimenting in Java I've noticed that there is no restriction on having duplicate method signatures in a nested class, which seems counter-intuitive.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
}
}
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
Edit: I appreciate that the core of the question is the same as this post, however, I was more interested in understanding why this behaviour is allowed as it wasn't immediately clear to me.
Where a class is defined doesn't matter so much. Keep in mind, in the end you have
class A { int x()
and
class A.B { int x()
Two (almost) independent classes. The only relationship that we have here is that any instance of B needs an "enclosing" instance of A to which it belongs (because it is a non-static inner class).
And of course, you can access the "enclosing" A "stuff" from within B, for example using A.this.x().
This should be available somewhere in the JLS - but ultimately it boils down to scope. Each of them has a different scope - thus the compiler does not complain.
Why would the compiler complain? They are two different classes, they just happen to be nested.
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
A.this.x()
At first method signature is not the combination of return type and method name it is method name and parameters.
if you call x() it will run x() inside the B
A.this.x(); it will run x() in A
Its scope, it's similar to have an instance variable called foo and then a local one in the method called foo as well.
Its worth reading about scope in java
Inner class in java can access all the members (i.e variables and methods) including private one, but outer class can not access member of inner class directly.
To access x() method of class B inside class A you can either create B's instance and call it or call like this A.this.x();
To access x() method outside class A you can do something like this:
B b = a.new B();
b.x();
If you are using non-static nested class (inner class) then it wouldn't be able to access to x method of B class from other classes. But if you are using static nested class you will be able to access that method from other classes. Example:
public class A {
int x() {
new A.B().x();
return 1;
}
static class B {
int x() {
new A().x();
return 2;
}
}
}
public static void main(String[] args) {
A a = new A();
a.x();
B b = new A.B();
b.x();
}
I hope this example answering your question... ☺
B is nested inside A. According to scope rules we can do the following:
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
int xOfA(){
return A.this.x();
}
}
public static void main(String[] args) {
final A objA = new A();
final B objB = objA.new B();
System.out.println(objA.x());
System.out.println(objB.x());
System.out.println(objB.xOfA());
}
}
that is because B is visible from an instance of A.
Moreover B can reference methods in the containing class through their full paths.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
When you define something in a nest scope which is otherwise in an outer scope, this is hiding.
What is important is that -: The version of a method that is executed will NOT be determined by the object that is used to invoke it. In fact it will be determined by the type of reference variable used to invoke the method
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
So as it is clear from above we can access it using class name, eg A.x
Hope this helps!!
I want to know how many instances of a static member class can be created by the enclosing class. I assume one only, but then the following extract from Bloch doesn't make sense to me.
Quoting Joshua Bloch's Effective Java - Item 22*: Favor static member classes over nonstatic.
A common use of private static member classes is to represent components of the object represented by their enclosing class. For example, consider a Map instance, which associates keys with values. Many Map implementations have an internal Entry object for each key-value pair in the map. While each entry is associated with a map, the methods on an entry (getKey, getValue and setValue) do not need access to the map. Therefore, it would be wasteful to use a nonstatic member class to represent entries: a private static member class is best. If you accidentally omit the static modifier in the entry declaration, the map will still work, but each entry will contain a superfluous reference to the map, which wastes space and time.
He states that the map creates an Entry object for each key-value pair in the map, i.e. multiple instances of the static member class.
So my assumption is wrong! That means my understanding of static member classes is wrong. Everyone knows how a static member variable behaves, the classic static final string for instance - there is only one instance of the object.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API? Every other Collections class could then just provide it's own implementation.
[*] Just realised that it's item 18 in the PDF version of the book I have
This is a common misinterpretation of the static keyword.
When you use static with a variable it means there will be only one of these for all objects of this class or something like that.
static Object thereWillBeOnlyOne = new Object();
However, in the context of inner classes it means something completely different. A static inner class has no connection with an object of the enclosing class while a non-static inner class does.
A static inner class:
public class TrieMap<K extends CharSequence, V> extends AbstractMap<K, V> implements Map<K, V> {
private static class Entry<K extends CharSequence, V> implements Map.Entry<K, V> {
The Map.Entry class used by my TrieMap class does not need to refer to the object that created it so it can be made static to save the unnecessary reference.
A non-static inner class:
public final class StringWalker implements Iterable<Character> {
// The iteree
private final String s;
// Where to get the first character from.
private final int start;
// What to add to i (usually +/- 1).
private final int step;
// What should i be when we stop.
private final int stop;
// The Character iterator.
private final class CharacterIterator implements Iterator<Character> {
// Where I am.
private int i;
// The next character.
private Character next = null;
CharacterIterator() {
// Start at the start.
i = start;
}
public boolean hasNext() {
if (next == null) {
if (step > 0 ? i < stop : i > stop) {
next = s.charAt(i);
i += step;
}
}
return next != null;
}
The CharacterIterator inside a StringWalker object refers to the string to be iterated as s which only exists once in the StringWalker object. I can therefore create many iterators of a StringWalker and they all walk the same string.
Why this weirdness?
This seemingly illogical duality derives from the use of the static keyword in C.
In C you can (or at least used to be able to) do:
void doSomething () {
static int x = 1;
if ( x < 3 ) {
} else {
}
x += 1;
}
and each time you called the function, x would be as you left it last time around - incremented in this case.
The concept was that the static keyword indicated that the variable was scopefully enclosed by its enclosing block but semantically enclosed by its parent block. I.e. the above code was roughly equivalent to:
int x = 1;
void doSomething () {
if ( x < 3 ) {
} else {
}
x += 1;
}
but x was only allowed to be referenced inside the function.
Take that concept forward into Java and things now make a little more sense. A static inner class behaves exactly like it was declared outside the class while a non-static inner bonds much more tightly to its enclosing instance - in fact it can refer to the instance directly.
Also:
class Thing {
static Object thereWillBeOnlyOne = new Object();
behaves much like
Object thereWillBeOnlyOne = new Object();
class Thing {
if it were legal.
Here endeth the lesson.
I think the Java team messed up the naming on this one. A static inner class (strictly speaking their correct name is "static nested class") is in no way different from an ordinary class except it has a fancy name (Something.MyClass instead of MyClass) and can be made private (i.e. not instantiable from other classes).
In case of Map, it was solely chosen because the name Map.Entry makes it clear that Entry relates to Map. As you suggest, it would have been perfectly reasonable to just use an ordinary class for this. The only difference is you don't get to write Map.Entry.
I think what they should have done is to use the syntax for "non-static" inner classes (i.e. just class in an enclosing class) for static nested classes, and instead invent a new keyword to create "non-static" inner classes, because it's these that behave different from normal classes. Maybe something like attached class. AFAIK the keyword static was chosen in order to avoid having too many reserved keywords, but I think it just encouraged confusion.
Yes, you can have many instances of the nested class, no matter that the nested class is static.
When the nested class is static you can create instances of it without having an instance of the enclosing class, this is one of the benefits, and basically the main difference between static and non-static nested classes.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
It's instantiated when it's constructor is called. Not any different from non-static classes. The nested class itself is loaded by the JVM, when the code first accesses it. Again this is not any different when compared to other classes, I think (not 100% sure of this though, but you can test it yourself). So I think you're kind of mixing the terms "loading the class by the JVM" and "instantiating the class".
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API?
As said, it's easier to create instances of static nested classes. You don't need an enclosing instance which is sometimes (maybe most of the times) exactly what you want.
See also:
(1) Nested Classes
(2) How can the JVM decide if a class is nested into another class?
(3) Loading of a nested class by the JVM
You can search for other references along these lines.
The reference (2) seems advanced and kind of peripheral to your question.
what's the point of Map using a static member class for Entry?
That's because, it makes the package structure logically correct.
Why not just use an interface on the API?
Now, this is a design discussion nobody would like to be dragged into.
This question already has answers here:
Are static methods inherited in Java?
(15 answers)
Closed 4 years ago.
I've read Statics in Java are not inherited. I've a small program below which compiles and produces 2 2 as output when run. From the program it looks like k (a static variable) is being inherited !! What am I doing wrong?
class Super
{
int i =1;
static int k = 2;
public static void print()
{
System.out.println(k);
}
}
class Sub extends Super
{
public void show()
{
// I was expecting compile error here. But it works !!
System.out.println(" k : " + k);
}
public static void main(String []args)
{
Sub m =new Sub();
m.show();
print();
}
}
The scope in which names are looked up in includes the super class.
The name print is not found in Sub so is resolved in the Super.
When the compiler generates bytecode, the call will be made to Super.print, rather than a call on a method in Sub.
Similarly the k is visible in the sub-class without qualifying it.
There is no polymorphism here, only inheritance of the contents of a name space. Static methods and all fields do not have polymorphic dispatch in Java, so can only be hidden by sub-classes, not overridden. The post you link to in your comments is using 'inheritance' in a somewhat unconventional way, mixing it up with polymorphism. You can have polymorphism without inheritance and inheritance without polymorphism.
Sub extends Super so it can see all the public/protected/package (static) members of Super.
I guess this is what you described as "Statics in Java are not inherited"
change
static int k = 2;
to
private static int k = 2;
and your Sub program won't see 'k' anymore and won't compile;
also try to create a new 'static int k=3;' in Sub, and see what happens.
It's pretty much the same as accessing Math.PI or any other global constant (which also have public and final modifiers).
In your case you have default (package) scope.
It's independed of inheritance only the scope restricts whether it is visible.
I think you might be wrong about static variables not being inherited. I suppose some properties of it are not inherited. For instance a static var normally means that all instances of the class have access to the same place in memory.
When you inherit, the derived class does not refer to the same memory as the base class.
Static member can be static data member and static method which can be accessed without using the object. It is used by nested class