Why static final variables are accepted in inner classees? - java

I know that it's possible to do the following:
public class Indeed{
private class inner {
static final int try1 = 10;
}
}
Why? what's the point of allowing such a declaration?
Moreover it's still possible do the same thing in a local class:
public void doThing() {
class LocalClass {
static final int try1 = 10;
}
}
What's the use of a static final in those bits of code?
I am pretty sure I'll never use them, however I need to understand why they are used as I have an OCPJP7 exam to do.
Thanks in advance.

The purpose of a static variable is to be shared by all instances of the class. In both examples, you can have several instances of your private class / local class, so as specified they will share static variables among instances. What would be pointless is if you could only instantiate your class once.
JLS 8.1.3. : Inner Classes and Enclosing Instances
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
The way I see it in the specs, is not having to answer the following dilemma:
static variables of an inner class are shared amongst all instances of the same outer class instance (but they can have different values from an outer class instance to another)
static variables of an inner class are shared amongst all existing instances in the VM, whatever their outer class instances.
Fortunately, when you declare it final, you know it will be the same for every instance, so you don't have to worry about this problem. That's why it is allowed.

For the question "why do static fields of inner classes have to be final":
This restriction is stated in the JLS as
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
But this doesn't tell us why. Let's think about how we use inner classes. Imagine I write (try to) this.
public class A{
private class B{
static x;
}
public void updateX(int y){
B.x=y;
}
public void printX(){
System.out.println(x);
}
}
What happens when I do this
A one = new A();
A two = new A();
one.doStuff(1);
two.doStuff(2);
one.printX();
two.printX();
What should be printed? 1 then 2 or 2 twice? x is static so it should only exist in one place (in the Klass object of B) but as B is an inner class it should be specific to that instance of A. If we allowed static non final fields we would need to create an instance-specific Klass object per instance of the outer class. Which we don't want to have to do!
Static final fields are therefore allowed as they can live in the Klass object of B happily, and be shared across all instances of the outer class, because they can never change (being final).

Related

Why does java not initialise static nested class fields at the same time as static outter fields?

Java initializes outer class static field when that class is interacted with, but does not initialize nested static class field.
So I have read the nested class documentation: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html and I think it comes down to this line here:
In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
If my understanding is correct that means that java views my two classes below as separate entities;
public class OutterClass {
private static final OutterClass outterField = new OutterClass("outterField");
private OutterClass(String string) {
System.out.println(string + " has been initialised");
}
private static class InnerClass {
private static final OutterClass innerField = new OutterClass("innerField");
}
public static void foo() {}
}
Meaning that when I interact with the OuterClass by calling the Outer.foo(), java will initialize my static field as it is part of the OuterClass. But since it views the InnerClass as a separate top level class, InnerClass's fields don't get initialized.
1) Is my understanding correct?
2) Has this got anything to do with the JIT compiler or the class loader? Is the InnerClass loaded when the OuterClass is loaded?
Thanks
1) Is my understanding correct?
Basically yes. Consider what happens with your static member outerField :
public class OutterClass {
private static final OutterClass outterField = new OutterClass("outterField");
Theoretically, it's possible that the JVM could create that static final object when the program starts running, or when the class is loaded, but it doesn't. Instead, it'll only initialise it when needed - basically :
Instance of class is created, or
One of the Class's static fields or methods is accessed
(see https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 )
So also with the static inner class. As you say, the JVM regards it as a top level inner class, so will only initialise its members when it also is needed.
2) Has this got anything to do with the JIT compiler or the class loader?
No and no. Initialisation of static members does not take place at class load time, but later (as we said, when the class is accessed). This is not a matter of compiler optimisation, but explicitly specified behaviour. After all, when you load a possibly-large class library, you would not want your JVM to consume memory or time initialising all the static members of classes that your program never touches; only-on-demand is a much better approach.
Is the InnerClass loaded when the OuterClass is loaded?
Yes (but not initialised then)

Breaking encapsulation and information hiding in Java

Consider the following snippet.
package breakoop;
public class BreakOOP {
public static class A{
private int a;
}
public static class B extends A{
public int f(){
return super.a;
}
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.f());
}
}
The example only compiles if A and B are encapsulated within the BreakOOP class.
This seems to go against some of the fundamental concepts of OOP. Can someone explain why this compiles? What is the reasoning behind it?
Check this: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html. It says it increases encapsulation by allowing the static class to access private members of the top level class (sometimes you may need to do that). And a is private member of class A, which is in the scope of BreakOOP, which in turn makes it accessible inside class B.
The Java Language Specification states:
A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Since classes A and B are defined within the body of BreakOOP that rule applies and B can see private members of A.
As for the OOP concepts: since A and B are static inner classes they don't have the special life-cycle relation with BreakOOP that true inner classes have (i.e. you don't need an instance of BreakOOP to create a new instance of A or B but they still have a somewhat special relation in that they have access to private members. If they should not have that kind of relationship then they shouldn't be inner classes but true top level classes.

static variables in inheritance

public class A
{
public static int i;
}
public class B extends A
{
public static void main(String[] args)
{
System.out.println("print i=" + B.i); // referred to A.i
}
}
My question here is how B.i is referred to the A.i?
If the static variable i is inherited why java allows to define another variable i in B class also?
A public or protected member of A is visible in all subclasses of A.
If the static variable i is inherited why java allows to define another variable i in B class also?
It's hard to speculate as to why. One possible reason is that this allows one to add members to a base class without breaking any derived classes that already happen to have a member with the same name.
Note that, if you define another i in B, it will shadow A.i, making it difficult to access the latter. I've seen people expecting this to behave polymorphically, but it doesn't (your case is slightly different anyway, since A.i is static).
i here is a static variable.A static variable,in layman terms,means a single copy being accessed by all classes.So,since your class B extends A,B has an access to the static variable of A.
If you define the variable locally,then the local value of the variable hides the parent class value.
there are 2 different things, scope and visibility. you can not redefine a variable in same scope twice (though you can redefine them in nested scopes).
But in case of inheritance, the subclass is out of scope of superclass, but yet has the visibility to that variable because of inheritance. So sub class allows you to define variable i again, though it will hide super class's variable. you wont be able to see its value. (unless used any getter from superclass)
Java allows you to change the specific variable value for the extended class.
This is because, static variables are shared between all objects of the same class.
It is a variable which belongs to the class and not to object(instance).
So, when extending the static variables of the parent class are not actually part of the extended class BUT are accessible (as long as they were not private).
Additionally, this can be used to do things such as:
using different STATIC CONSTANT for extended classes.
A use for this is to identify classes based on a STATIC integer as apposed to utilizing instanceof. This can be further combined with a switch to change behavior based on an objects type.
So, in the most basic example imagine we want to create a variable represent TYPE.
class A
{
public static final int NODE_TYPE = NODE_PERSON;
public static final int NODE_PERSON = 0;
public static final int NODE_CAR = 1;
}
class B extends Class A
{
public static int NODE_TYPE = NODE_CAR;
}
This has been used in many frameworks including Eclipse Abstract Syntax Trees:
http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTNode.html
You will see a list of STATIC INTEGERS which represent different Node Types.

Why can I access the private members of an enclosing class reference

I have seen many questions about accessing private members of an enclosing class. However, my question is the opposite.
If I have (as an example), the following code:
public class A {
private String outerString = "silly string";
static class B {
private final A someA = new A();
public void foo() {
String b = someA.outerString ;
}
}
}
I'm wondering why this compiles? I would have expected an error by virtue of the way in which I am accessing the 'outerString' instance variable from class A (via someA.outerString). I know that an inner class can access the enclosing class members directly by an implicit 'this' reference. But here, class B is static, so the 'this' reference won't apply.
B is a member of A and therefore has access to A's private fields and methods.
In this case, although B is static it is using an instance of A to access the field A.outerString.
static methods of a class can access private members of the same class through the same class instance. This behavior is consistent for static classes as well.
static void b(A someA) {
String b = someA.outerString;
}
1. this only works with non-static member, thats right..... But you are not using this but instance of the Outer Class.
2. And you can very well access the Outer class private member from the (Top level) inner static class.
3. Outer to Inner and from Inner to Outer has the ability to access the private member of each other..only difference is that, non static inner class has implicit reference to the Outer class, and for static inner class you must access using the Instance.

Static nested class in Java, why?

I was looking at the Java code for LinkedList and noticed that it made use of a static nested class, Entry.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
What is the reason for using a static nested class, rather than an normal inner class?
The only reason I could think of, was that Entry doesn't have access to instance variables, so from an OOP point of view it has better encapsulation.
But I thought there might be other reasons, maybe performance. What might it be?
Note. I hope I have got my terms correct, I would have called it a static inner class, but I think this is wrong: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
The Sun page you link to has some key differences between the two:
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.
There is no need for LinkedList.Entry to be top-level class as it is only used by LinkedList (there are some other interfaces that also have static nested classes named Entry, such as Map.Entry - same concept). And since it does not need access to LinkedList's members, it makes sense for it to be static - it's a much cleaner approach.
As Jon Skeet points out, I think it is a better idea if you are using a nested class is to start off with it being static, and then decide if it really needs to be non-static based on your usage.
To my mind, the question ought to be the other way round whenever you see an inner class - does it really need to be an inner class, with the extra complexity and the implicit (rather than explicit and clearer, IMO) reference to an instance of the containing class?
Mind you, I'm biased as a C# fan - C# doesn't have the equivalent of inner classes, although it does have nested types. I can't say I've missed inner classes yet :)
There are non-obvious memory retention issues to take into account here. Since a non-static inner class maintains an implicit reference to it's 'outer' class, if an instance of the inner class is strongly referenced, then the outer instance is strongly referenced too. This can lead to some head-scratching when the outer class is not garbage collected, even though it appears that nothing references it.
Static inner class is used in the builder pattern. Static inner class can instantiate it's outer class which has only private constructor. You can not do the same with the inner class as you need to have object of the outer class created prior to accessing the inner class.
class OuterClass {
private OuterClass(int x) {
System.out.println("x: " + x);
}
static class InnerClass {
public static void test() {
OuterClass outer = new OuterClass(1);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass.InnerClass.test();
// OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
}
}
This will output x: 1
static nested class is just like any other outer class, as it doesn't have access to outer class members.
Just for packaging convenience we can club static nested classes into one outer class for readability purpose. Other than this there is no other use case of static nested class.
Example for such kind of usage, you can find in Android R.java (resources) file.
Res folder of android contains layouts (containing screen designs), drawable folder (containing images used for project), values folder (which contains string constants), etc..
Sine all the folders are part of Res folder, android tool generates a R.java (resources) file which internally contains lot of static nested classes for each of their inner folders.
Here is the look and feel of R.java file generated in android:
Here they are using only for packaging convenience.
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.techpalle.b17_testthird;
public final class R {
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class layout {
public static final int activity_main=0x7f030000;
}
public static final class menu {
public static final int main=0x7f070000;
}
public static final class string {
public static final int action_settings=0x7f050001;
public static final int app_name=0x7f050000;
public static final int hello_world=0x7f050002;
}
}
Well, for one thing, non-static inner classes have an extra, hidden field that points to the instance of the outer class. So if the Entry class weren't static, then besides having access that it doesn't need, it would carry around four pointers instead of three.
As a rule, I would say, if you define a class that's basically there to act as a collection of data members, like a "struct" in C, consider making it static.
From http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html:
Use a non-static nested class (or inner class) if you require access
to an enclosing instance's non-public fields and methods. Use a static
nested class if you don't require this access.
Simple example :
package test;
public class UpperClass {
public static class StaticInnerClass {}
public class InnerClass {}
public static void main(String[] args) {
// works
StaticInnerClass stat = new StaticInnerClass();
// doesn't compile
InnerClass inner = new InnerClass();
}
}
If non-static the class cannot be instantiated exept in an instance of the upper class (so not in the example where main is a static function)
One of the reasons for static vs. normal have to do with classloading. You cannot instantiate an inner class in the constructor of it's parent.
PS: I've always understood 'nested' and 'inner' to be interchangeable. There may be subtle nuances in the terms but most Java developers would understand either.
Non static inner classes can result in memory leaks while static inner class will protect against them. If the outer class holds considerable data, it can lower the performance of the application.
JVM knows no nested classes. Nesting is just syntactic sugar.
Below images shows Java file:
Below images show class files representation of the java file :
Notice that 2 class files are generated, one for parent and another for nested class.
Non-static nested class' objects have access to the enclosing scope. That access to the enclosing scope is maintained by holding an implicit reference of the enclosing scope object in the nested object
Nested class is a way to represent the intent that the nested class type represents a component of the parent class.
public class Message {
private MessageType messageType; // component of parent class
public enum MessageType {
SENT, RECEIVE;
}
}
class Otherclass {
public boolean isSent(Message message) {
if (message.getMessageType() == MessageType.SENT) { // accessible at other places as well
return true;
}
return false;
}
}
private static nested class represents Point#3 & the fact the nested type can only be the subcomponent to the parent class. It can't be used separately.
public class Message {
private Content content; // Component of message class
private static class Content { // can only be a component of message class
private String body;
private int sentBy;
public String getBody() {
return body;
}
public int getSentBy() {
return sentBy;
}
}
}
class Message2 {
private Message.Content content; // Not possible
}
More details here.
I don't know about performance difference, but as you say, static nested class is not a part of an instance of the enclosing class. Seems just simpler to create a static nested class unless you really need it to be an inner class.
It's a bit like why I always make my variables final in Java - if they're not final, I know there's something funny going on with them. If you use an inner class instead of a static nested class, there should be a good reason.
Using a static nested class rather than non-static one may save spaces in some cases. For example: implementing a Comparator inside a class, say Student.
public class Student {
public static final Comparator<Student> BY_NAME = new ByName();
private final String name;
...
private static class ByName implements Comparator<Student> {
public int compare() {...}
}
}
Then the static ensures that the Student class has only one Comparator, rather than instantiate a new one every time a new student instance is created.
Adavantage of inner class--
one time use
supports and improves encapsulation
readibility
private field access
Without existing of outer class inner class will not exist.
class car{
class wheel{
}
}
There are four types of inner class.
normal inner class
Method Local Inner class
Anonymous inner class
static inner class
point ---
from static inner class ,we can only access static member of outer class.
Inside inner class we cananot declare static member .
inorder to invoke normal inner class in static area of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inorder to invoke normal inner class in instance area of outer class.
Inner i=new Inner();
inorder to invoke normal inner class in outside of outer class.
Outer 0=new Outer();
Outer.Inner i= O.new Inner();
inside Inner class This pointer to inner class.
this.member-current inner class
outerclassname.this--outer class
for inner class applicable modifier is -- public,default,
final,abstract,strictfp,+private,protected,static
outer$inner is the name of inner class name.
inner class inside instance method then we can acess static and instance field of outer class.
10.inner class inside static method then we can access only static field of
outer class.
class outer{
int x=10;
static int y-20;
public void m1() {
int i=30;
final j=40;
class inner{
public void m2() {
// have accees x,y and j
}
}
}
}

Categories