java - a nonstatic field inside a static class - java

It's my first time coming across such pattern of code, it might be fairly familiar to advanced gurus out there:
public static class Myclass{
public static class myChildClass{
public int a =1; //this doesn't give an error although I expected it should be declared static
}
}
I can't instantiate the static inner class and I can't access the variable int a outside the class, so does this variable become private to the class? Why does java allow this instead of complaining it be declared static?

I can't instantiate the static inner class
Of course you can:
Myclass.myChildclass m = new Myclass.myChildclass();
and I can't access the variable int a outside the class
Yes you can:
System.out.println(m.a);
so does this variable become private to the class?
No, because it's not private.
Why does java allow this instead of complaining it be declared static?
I think you misunderstand what a static class is: it's merely a nested class without an implicit reference to an instance of the enclosing class that created it. There is no requirement for its members to be static.

Related

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.

Using "this" keyword inside nested static class java

I have a class say A, and a static nested class say B.
public class A {
public static class B {
B(Temp x) {
x.reg(this); // need to pass the nested class reference.
}
}
}
Is the above code correct? Can we use this keyword inside nested static class constructor?
Please help me on this. Thanks.
yes, it is. For the runtime, inner classes are just another, separate class. If the inner class is not static it will just have a reference to the outer class, but in your case it's static so not even, so it is exactly as if you created a new class in a new file
Just make sure that you write "public", not "Public"
1) Nested static class doesn’t need reference of Outer class, but Non-static nested class or Inner class requires Outer class reference.
2) Inner class(or non-static nested class) can access both static and non-static members of Outer class. A static class cannot access non-static members of the Outer class. It can access only static members of Outer class.
3) An instance of Inner class cannot be created without an instance of outer class and an Inner class can reference data and methods defined in Outer class in which it nests, so we don’t need to pass reference of an object to the constructor of the Inner class. For this reason Inner classes can make program simple and concise.
for More information please refer this http://www.geeksforgeeks.org/static-class-in-java/
The behavior of the static class in just like a static method. This class belongs to the class but not the instance. Hence, this has no meaning in the static context.

Why and when to use static inner class or instance inner class? [duplicate]

This question already has answers here:
Static nested class in Java, why?
(14 answers)
Closed 9 years ago.
I have been studying about static inner class in java. But i am not clear whats the point of using static inner class or inner class.
class A{
static class B{
}
public static void main(String[] args) {
B b=new B();
}
}
or
class B{}
class A{
public static void main(String[] args) {
B b=new B();
}
}
Non-static inner classes have an automatic reference to their enclosing class. A static inner classes only relationship to its enclosing class is that you have to reference it via the enclosing class' name: EnclosingClass.StaticInnerClass.
Non-static inner classes are good when you want to reference some of the data from the parent class.
A static inner class is good when you just want to associate the inner class with the enclosing class without dragging it along for the ride.
In other words, a non-static inner class can prevent the enclosing class from being garbage collected, since it has that reference, while a static inner class will never do that.
There is technical difference:
class A {
private static int x = 42; //the answer
public static class B {
int showX() {
return x; // only static class can it
}
}
}
But it isn't the main point. If class B is used only by class A it's good to make it inner because some classes in one package may want to have utility class with same name.
The result is the same, but if B is a little Class that A uses it just makes more sense to put it into A.
By making a nested classes can be static, you can use the nested class without having an instance of the outer class.
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
...
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.
See tutorial here
When your inner class is considered as part of your "object", use inner class.
Indeed, you would be able to access private,package,protected and public fields from your wrapping class.
"Drawback" is: An inner class can't exist without it's wrapping class instantiated, that is logically due to the first sentence.
Otherwise, if you consider:
The behaviour of your nested(called also static inner) class isn't considered as reusable by external class since maybe too specific.
some related fields of one class as being so much related that you want to make
a class wrapping them. This will get your code more understandable and cleaner.
then choose to make a static class.
Moreover, since static (meaning outside the life cycle of any object), a nested class may instantiate without regarding its wrapping class/object.

Java nested classes- under the hood?

I have a couple of questions relating to nested classes within Java.
How do nested classes appear "under the hood", with regards to memory allocations?
You cannot declare a static variable within a nested class (I think the exact error was that static attributes can only be declared at the top level class). Why is this and what other restrictions are there for nested classes?
If possible, please say whether your answer is Java-specific, or whether C++ also follows the same rules?
Inner classes are exactly the same as regular classes as far as memory and compilation are concerned. (Perhaps there is some difference in the way they're managed in memory, but it's not visible to the average Java developer) In fact, when you compile a class that has an inner class, you can see the compiled .class file as OuterClass$InnerClass.class. So as far as I know, the JVM treats them the same.
As far as static variables are concerned, I'm not certain what the issue is. For example, this runs for me:
public class Tester {
public static void main(String[] args) {
System.out.println(InnerTester.MY_STRING);
}
public class InnerTester {
public static final String MY_STRING = "MY_STRING";
}
}
EDIT
As Jeffery pointed out, this does NOT compile:
public class Tester {
public static void main(String[] args) {
System.out.println(InnerTester.MY_STRING);
}
public class InnerTester {
public static String MY_STRING = "MY_STRING";
}
}
The difference is, I had the first static variable listed as final.
After thinking about this awhile, I agree with #Eugene. They allow static fields on inner classes to be final because then there's no problem with initialization. The value cannot change, you just initialize it to its value. If, however, the static field is not final, you then require an instance of the outer class to be created in order to initialize the field, and static members can't be tied to particular instances.
I found this discussion on it as well.
Basically a nested class is just a class with a field referencing the enclosing instance.
Unless it's a static nested class (inside which you can declare static fields/methods).
In this case it's just a class with another path element in the name (package + enclosing class name).
In other words. Non-static nested class (inner class) - cannot exists without enclosing instance (e.g. page inside a book). And you instantiate as follows:
Book book = ... // a book instance;
Book.Page page = book.new Page(); // requires an enclosing instance
But the static nested class - is completely independent, it's like just a question of name space. You can instantiate it as:
Outer.NestedStatic instance = new Outer.NestedStatic(); // just name-space
More information here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
A nested class is simply the definition of a type inside another class. Java does not care in what scope a new type is defined, and you do not need to "handle" this inner class in any special way.
It wouldn't make sense to have a non-static inner class with static fields, since any reference to a non-static inner class is necessarily an instance variable. Only if the inner class is made static would it even be possible to statically assign it -- in this case, the static inner class is a standalone class, with the enclosing class name acting as yet another namespace level.

java nested interfaces and inner classes

Why can't a java nested Interface be non-static ? And why can't an inner class contain static non final members ?
I came across the questions while going through Gosling and haven't been able to figure out the answer yet.
If an nested class is non-static (i.e. an inner class), this means that each instance of it is bound to an instance of the outer class. As an interface has no instances of its own, it seems to not be useful for the implementing classes to be bound to an outer object, so having it static by default seems reasonable.
I'm not sure why you can't have static non final members in an inner class but since static members aren't bound to any particular object instance it makes no difference whether it is in the inner or outer class.
E.g.
class OuterClass {
private static int staticMember;
class InnerClass {
void incStatic() {
staticMember++;
}
}
}
You can access the static member from the inner class as if it were within the inner class.

Categories