What members of the enclosing class can a static nested class access? - java

Java The Complete Reference says
A static nested class is one that has the static modifier applied. Because it is static, it must access the non-static
members of its enclosing class through an object. That is, it
cannot refer to non-static members of its enclosing class
directly. Because of this restriction, static nested classes are
seldom used.
What does it mean by "through an object", and "cannot ... directly"?
Java in a Nutshell says
• A static member type can access (only) the static members of the class that contains it.
• A static member type has access to all the static members (including any other static member types) of its
containing type.
Are the two sentences redundant to each other? What are the differences between the two sentences?
Do the quotes from the two books contradict each other? The first
quote says a static nested class can access non-static member of the
enclosing class, while the second quote says a static member type
can access only the static members of the enclosing class.
Thanks.

In Java nested non - static classes have a hidden reference to the instance of the parent class. That's why they can access all non-static members. The nested class doesn't have such an instance. However, its scope allows it to access the parent members if the parent class passes this.
So what the second quote is saying that the access doesn't happen automatically. You pass the reference to the enclosing class and the nested static class can access it. Otherwise, it doesn't know the address of the enclosing class.

No static method may access an instance field directly without first qualifying it with an object of the containing class.
class Foo {
int myField;
public void main(String[] args) {
Foo foo = new Foo();
access(foo);
}
public static void access(Foo obj) {
System.out.println(myField); // <-- error, can't access myField from static
//context.
System.out.println(obj.myField); // OK here
}
}
The same is true for accessing instance fields via inner static classes.

A java static nested class can access the static members of the nested class and the static members of the parent class. This makes sense when you understand the position of a class and object in memory – that there is only one class but multiple objects and you need to decide what each instance of an object needs absolutely necessarily and what is actually redundant and can stay in the class (doesn't need to be duplicated), so all methods (static and non static) and all static members

What members of the enclosing class can a static nested class access?
You can gain clarity to the answer for this question by assigning the following meaning for the Java keyword static:
"Static" in Java means without regard for or association with any instance of any class.
A static field belongs to the class in which it is declared and is not encapsulated by any instance of that class. Any instance of the class that is subsequently constructed (or any instance or any method of any class that is in scope) can access the static field (this is why static fields can be dangerous in concurrent environments).
A static method is defined for the class in which it is declared and has no associated instance of that class. A static method knows of no class instances and can not access any of them unless a reference to an instance is passed to it as an argument.
A static member class is in every way that matters the same as an ordinary top level class that has been packaged within an enclosing class for packaging convenience. Just like a top level class, its instances know nothing of any instance of the enclosing class (unless a reference to an enclosing class instance is passed to them during construction).
A static initializer block is used to initialize static fields for a class, but it knows nothing of any instances of that class. Therefore, they cannot initialize instance fields since they cannot access them.
Therefore, the answer becomes intuitive: a static nested class can access all members of an enclosing class that can be accessed without an instance of that class.
If an enclosing class instance is passed to the static nested class's constructor, then the members of that instance (including the private ones) will be in scope. Logically, passing an enclosing class instance to a static nested class constructor is very similar to using a nested member class. The difference is that for the former, the association is an explicit dependency injection; whereas for the latter, the association between instances is implicit.

Related

Inner classes inheritance and access to enclosing class methods/fields

Here are two statements I found concerning inner classes
JavaDocs:
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.
On another site I found this:
A nested class, for the most part, is just that—a class declared in
the definition of an enclosing class. It does not inherit anything
from the enclosing class, and an instance of the nested class cannot
be assigned to a variable reference to the enclosing class.
Aren't the bold marked lines contradicting?
How can you not inherit a surrounding objects fields and methods and at the same time have access to its fields and methods?
No, they do not conflict. Look at the following example:
public class A {
public void foo() {
//some code
}
public class B {
public void bar() {
foo();
}
}
}
In this example, the innerclass B can access the method of A (or any of its' fields, actually), but in no way does inheritance takes place.
For instance, the following change to B would result in a compilation error:
public class B {
public void bar() {
super.foo();
}
}
Because B does not inherit from A. It can access its' instance members, but it does not extend (inherit) from it.
Please do not see the terms nested class and inner class as an opposite or something similar. In fact, a nested class simply describes all sorts of classes that are declared inside another class:
Nested classes that are declared static are simply called static nested classes.
Non-static nested classes are called inner classes. There are three types of them (see JLS §8.1.3 for more info):
A non-static member class.
A local class.
An anonymous class.
The first paragraph you quoted explains that an inner class has access (read: access, not inherit) to the methods and fields of the enclosing instance. Note, it is about an instance, not the class.
The second paragraph tries to explain that there is no relationship between a class and a nested class inside it, except for their locations.

java best practice -outer class static variable accessed by inner class

class OuterClass {
static int j=99;
static class InnerClass {
public void doSomething() {
while(true)
OuterClass.j= 100;
}
}
}
}
Using the above code, is there any issue with garbage collection when the OuterClass needs to garbage collect but lets say doSomething is referencing a static variable will it be an issue ? What i'm concerned with is that the inner class has a reference to the outer class by accessing the variable j and im wondering if that will affect the OuterClass being GC.
Although you've named it InnerClass, it is not an inner class. It is simply a static nested class.
An instance of such a class has no reference to any instance of the enclosing class. What's more, you're referencing a static field of the enclosing class. There is absolutely no reference to any instance of OuterClass.
Nothing in your InnerClass can prevent an instance of the type OuterClass from being garbage collected.
Did I misunderstand your question? Are you asking about classes being garbage collected?
Classes aren't affected by GC, objects are. If you create an object of type InnerClass, GC will not touch anything referred to by it. However, because you are only referencing a static variable, you are not referencing any objects of type OuterClass (in that code fragment anyway). Thus, GC is free to remove any unneeded objects of type OuterClass without affecting, in any way, the functioning of objects of type InnerClass.
Note that if all you're doing is referring to a static variable in OuterClass from your InnerClass, you should probably not define InnerClass as a nested class.
Since the j field is static, it exists beyond the scope of a single instance of OuterClass. The fact that InnerClass is static decouples it from any instance of OuterClass.
As with class methods and variables, a static nested class is
associated with its outer class. And like static class methods, a
static nested class cannot refer directly to instance variables or
methods defined in its enclosing class: it can use them only through
an object reference.
Note: A static nested class interacts with the instance members of its
outer class (and other classes) just like any other top-level class.
In effect, a static nested class is behaviorally a top-level class
that has been nested in another top-level class for packaging
convenience.
Nested classes explained in the Java tutorial

Compile time constants in inner classes [duplicate]

class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Although it's not possible to access the static field with OuterClass.InnerClass.i, if I want to record something that should be static, e.g. the number of InnerClass objects created, it would be helpful to make that field static. So why does Java prohibit static fields/methods in inner classes?
EDIT: I know how to make the compiler happy with static nested class (or static inner class), but what I want to know is why java forbids static fields/methods inside inner classes (or ordinary inner class) from both the language design and implementation aspects, if someone knows more about it.
what I want to know is why java forbids static fields/methods inside inner classes
Because those inner classes are "instance" inner classes. That is, they are like an instance attribute of the enclosing object.
Since they're "instance" classes, it doesn't make any sense to allow static features, for static is meant to work without an instance in the first place.
It's like you try to create a static/instance attribute at the same time.
Take the following example:
class Employee {
public String name;
}
If you create two instances of employee:
Employee a = new Employee();
a.name = "Oscar";
Employee b = new Employee();
b.name = "jcyang";
It is clear why each one has its own value for the property name, right?
The same happens with the inner class; each inner class instance is independent of the other inner class instance.
So if you attempt to create a counter class attribute, there is no way to share that value across two different instances.
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
When you create the instance a and b in the example above, what would be a correct value for the static variable count? It is not possible to determine it, because the existence of the InnerData class depends completely on each of the enclosing objects.
That's why, when the class is declared as static, it doesn't need anymore a living instance, to live itself. Now that there is no dependency, you may freely declare a static attribute.
I think this sounds reiterative but if you think about the differences between instance vs. class attributes, it will make sense.
The idea behind inner classes is to operate in the context of the enclosing instance. Somehow, allowing static variables and methods contradicts this motivation?
8.1.2 Inner Classes and Enclosing Instances
An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).
InnerClass cannot have static members because it belongs to an instance (of OuterClass). If you declare InnerClass as static to detach it from the instance, your code will compile.
class OuterClass {
static class InnerClass {
static int i = 100; // no compile error
static void f() { } // no compile error
}
}
BTW: You'll still be able to create instances of InnerClass. static in this context allows that to happen without an enclosing instance of OuterClass.
From Java 16 onwards, this is no longer the case. Quoting from JEP 395 (on finalizing records):
Relax the longstanding restriction whereby an inner class cannot declare a member that is explicitly or implicitly static. This will become legal and, in particular, will allow an inner class to declare a member that is a record class.
Indeed, the following code can be compiled with Java 16 (tried with 16.ea.27):
public class NestingClasses {
public class NestedClass {
static final String CONSTANT = new String(
"DOES NOT COMPILE WITH JAVA <16");
static String constant() {
return CONSTANT;
}
}
}
Actually, you can declare static fields if they are constants and are written in compile time.
class OuterClass {
void foo() {
class Inner{
static final int a = 5; // fine
static final String s = "hello"; // fine
static final Object o = new Object(); // compile error, because cannot be written during compilation
}
}
}
class Initialization sequence is a critical reason.
As inner classes are dependent on the instance of enclosing/Outer class, so Outer class need to be initialized before the initialization of the Inner class.
This is JLS says about class Initialization. The point we need is, class T will be initialize if
A static field declared by T is used and the field is not a constant variable.
So if inner class have an static field accessing that will cause initializing the inner class, but that will not ensure that the enclosing class is initialized.
It would violate some basic rules. you can skip to the last section (to two cases) to avoid noob stuff
One thing about static nested class, when some nested class is static it will behave just like a normal class in every way and it is associated with the Outer class.
But the concept of Inner class/ non-static nested class is it will be associated with the instance of outer/enclosing class. Please note associated with instance not the class.
Now associating with instance clearly means that (from the concept of instance variable) it will exist inside a instance and will be different among instances.
Now, when we make something static we expect it will be initialized when the class is being loaded and should be shared among all instances. But for being non-static, even inner classes themselves (you can definitely forget about instance of inner class for now) are not shared with all instance of the outer/enclosing class (at least conceptually), then how can we expect that some variable of inner class will be shared among all the instance of the inner class.
So if Java allow us to use static variable inside not static nested class. there will be two cases.
If it is shared with all the instance of inner class it will violate the concept of context of instance(instance variable). It's a NO then.
If it is not shared with all instance it will violate the the concept of being static. Again NO.
Here is the motivation that I find best suitable for this "limit":
You can implement the behavior of a static field of an inner class as an instance field of the outer object;
So you do not need static fields/methods.
The behaviour I mean is that all inner class instances of some object share a field(or method).
So, suppose you wanted to count all the inner class instances, you would do:
public class Outer{
int nofInner; //this will count the inner class
//instances of this (Outer)object
//(you know, they "belong" to an object)
static int totalNofInner; //this will count all
//inner class instances of all Outer objects
class Inner {
public Inner(){
nofInner++;
totalNofInner++;
}
}
}
In simple words, non-static inner classes are instance variable for outer class, and they are created only when an outer class is created and an outer class object is created at run-time while static variables are created at class loading time.
So non-static inner class is runtime thing that's why static not the part of a non-static inner class.
NOTE: treat inner classes always like a variable for an outer class they may be static or non-static like any other variables.
Because it would cause ambiguity in the meaning of "static".
Inner classes cannot declare static members other than
compile-time constants. There would be an ambiguity about the meaning
of “static.” Does it mean there is only one instance in the virtual
machine? Or only one instance per outer object? The language designers
decided not to tackle this issue.
Taken from "Core Java SE 9 for the Impatient" by Cay S. Horstmann. Pg 90 Chapter 2.6.3
In the Java language designers' own words:
Since nested classes were first introduced to Java, nested class
declarations that are inner have been prohibited from declaring static
members... It simplifies the language's task of resolving and
validating references to in-scope variables, methods, etc.
There was never any particularly grand conceptual or philosophical reason to prohibit this.
Simplifying things for the language was deemed an insufficient reason to continue to maintain this restriction. Along with the introduction of records in Java 16, they made the decision to relax the restriction.
Class Inner will be initialize if a static field declared by Inner is used and the field is not a constant variable.
class Outer{
class Inner{
static Inner obj = new Inner();
}
public static void main(String[] args){
Inner i = Inner.obj; // It woulds violate the basic rule: without existing Outer class Object there is no chance of existing Inner class Object.
}
}
I guess it's for consistency. While there doesn't seem to be any technical limitation for it, you wouldn't be able to access static members of the internal class from the outside, i.e. OuterClass.InnerClass.i because the middle step is not static.

Static and non static fields

just to clarify I am thinking of this right, in java a static field is a variable/field which is used by a whole class, or can be used by all objects refering to that class? And a non static field is a variable defined by an object? And a second object refering to the same class as object 1 can have a different value to object 1's static field?
A static field, or static class variable within a class is accessible before an instance of that class is created unlike instance variables. Instance variables (non-static variables) within a class are created when an instance of that class is created at run-time. Hence, non-static variables cannot be accessed until an instance of that class is created. Whereas, static class members can be accessed before that class is created or instantiated.
All instances of that class can access the same static variable. On the other hand, instance variables are individual/encapsulated to each instance of a class.
static field shared and used by all the objects and loaded when class is loaded
non static fields are separate copies for every object and loaded when an object is created
And a non static field is a variable defined by an object?
Whenever you create a new objects, each object will have its own copy of instance i.e. non static fields
And a second object refering to the same class as object 1 can have a different value to object 1's static field?
Didn't really get your question, but
If object1 and object2 are instnaces of a class, then if object1 modifies static field of class, then object2 will get the updated value
An instance attribute is one that is specific to an instance, and its value isn't shared among other instances of the same class.
On the other hand, a class (or static) attribute is one that is common to all of the class' instances, as it belongs to the class, not to an instance in particular.
So you must be careful with the static attributes, because a change in one will be reflected on all of the code that uses it, sometimes causing unexpected results. In practice, I tend to avoid static attributes, except for the cases where they have constant, immutable values.
Similar considerations apply to instance methods and static methods: an instance method can "see" both instance and static methods and attributes, whereas a static method can only refer to static methods and attributes of the class, and can't "see" the instance methods and attributes (that is unless it instantiates an object and uses it to access its instance members).
Kind of... a static object is shared between instances of a class and a non-static is specific to the instance. Same goes for methods.
As said in the reference :
If a field is declared static, there exists exactly one incarnation of
the field, no matter how many instances (possibly zero) of the class
may eventually be created. A static field, sometimes called a class
variable, is incarnated when the class is initialized (§12.4).
Refer to JLS §8.3.1.1:
If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).
By contrast, each instance of a class contains its own unique values for non-static fields. Non-static fields are incarnated when the class is instantiated:
A field that is not declared static (sometimes called a non-static field) is called an instance variable. Whenever a new instance of a class is created (§12.5), a new variable associated with that instance is created for every instance variable declared in that class or any of its superclasses.

Java: Static vs inner class [duplicate]

This question already has answers here:
Java inner class and static nested class
(28 answers)
Closed 9 years ago.
What is the difference between static and non-static nested class?
An inner class, by definition, cannot be static, so I am going to recast your question as "What is the difference between static and non-static nested classes?"
A non-static nested class has full access to the members of the class within which it is nested. A static nested class does not have a reference to a nesting instance, so a static nested class cannot invoke non-static methods or access non-static fields of an instance of the class within which it is nested.
Let's look in the source of wisdom for such questions: Joshua Bloch's Effective Java:
Technically, there is no such thing as a static inner class. According to Effective Java, the correct terminology is a static nested class. A non-static nested class is indeed an inner class, along with anonymous classes and local classes.
And now to quote:
Each instance of a non-static nested class is implicitly associated
with an enclosing instance of its containing class... It is possible
to invoke methods on the enclosing instance.
A static nested class does not have access to the enclosing instance. It uses less space too.
There are two differences between static inner and non static inner classes.
In case of declaring member fields and methods, non static
inner class cannot have static fields and methods.
But, in case of static inner class, can have static and non static fields
and method.
The instance of non static inner class is created with the reference
of object of outer class, in which it has defined, this means it has
enclosing instance. But the instance of static inner class is
created without the reference of Outer class, which means it does
not have enclosing instance.
See this example
class A
{
class B
{
// static int x; not allowed here
}
static class C
{
static int x; // allowed here
}
}
class Test
{
public static void main(String… str)
{
A a = new A();
// Non-Static Inner Class
// Requires enclosing instance
A.B obj1 = a.new B();
// Static Inner Class
// No need for reference of object to the outer class
A.C obj2 = new A.C();
}
}
Static inner class cannot access non-static members of enclosing class. It can directly access static members (instance field and methods) of enclosing class same like the procedural style of getting value without creating object.
Static inner class can declare both static and non-static members. The static methods have access to static members of main class. However, it cannot access non-static inner class members. To access members of non-static inner class, it has to create object of non-static inner class.
Non-static inner class cannot declare static field and static methods. It has to be declared in either static or top level types. You will get this error on doing so saying "static fields only be declared in static or top level types".
Non-static inner class can access both static and non-static members of enclosing class in procedural style of getting value, but it cannot access members of static inner class.
The enclosing class cannot access members of inner classes until it creates an object of inner classes. IF main class in accessing members of non-static class it can create object of non-static inner class.
If main class in accessing members of static inner class it has two cases:
Case 1: For static members, it can use class name of static inner class
Case 2: For non-static members, it can create instance of static inner class.
Discussing nested classes...
The difference is that a nested class declaration that is also static can be instantiated outside of the enclosing class.
When you have a nested class declaration that is not static, Java won't let you instantiate it except via the enclosing class. The object created out of the inner class is linked to the object created from the outer class, so the inner class can reference the fields of the outer.
But if it's static, then the link does not exist, the outer fields cannot be accessed (except via an ordinary reference like any other object) and you can therefore instantiate the nested class by itself.
static inner class: can declare static & non static members but can only access static members of its parents class.
non static inner class: can declare only non static members but can access static and non static member of its parent class.
An inner class cannot be static, so I am going to recast your question as "What is the difference between static and non-static nested classes?".
as u said here inner class cannot be static... i found the below code which is being given static....reason? or which is correct....
Yes, there is nothing in the semantics of a static nested type that would stop you from doing that. This snippet runs fine.
public class MultipleInner {
static class Inner {
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Inner();
}
}
}
this is a code posted in this website...
for the question---> Can a Static Nested Class be Instantiated Multiple Times?
answer was--->
Now, of course the nested type can do its own instance control (e.g. private constructors, singleton pattern, etc) but that has nothing to do with the fact that it's a nested type. Also, if the nested type is a static enum, of course you can't instantiate it at all.
But in general, yes, a static nested type can be instantiated multiple times.
Note that technically, a static nested type is not an "inner" type.
A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

Categories