In a previous blog, I talked about why we can not define an outer class using private or protected keywords. If you have not read it, please go ahead and give it a look.

In this article I will talk what is the use of the static keyword, why an outer Java class can’t be static, why it is not allowed in Java to define a static outer class. In order to understand that first, we need to understand what is the static keyword used for, what purpose it solves and how does it work.

What does static keyword do

Every Java programmer knows that if we need to define some behaviour (method) or state (field) which will be common to all objects we define it as static. Because static content (behaviour or state) does not belong to any particular instance or object, it will common to all objects and all objects are free to change any static field and every change will be visible to every object.

We do not need to create an object of the class to access a static field or method, we can directly refer a static field or method by using class name and dot operator e.g. Class.forName(“ClassName”).
This happens because JVM creates a Class level object for every class when Classloader loads the class into memory. And all static content of that class belongs this Class object and all other objects of that class refer to this class level object for all static content. A class-level object is actually an object of java.lang.Class and it is referred by your_class_name.class syntax.

For Example for the below statement, two objects will get created

Employee emp =  new Employee();

One is ‘emp’ (the new Employee();) itself and another one is the ‘class level object’ of Employee class which will get created while JVM will load Employee class into memory and we can refer it by Employee.class. And this class level object holds all the static content of the Employee class either it is a variable or method. If we are accessing any static content through emp object it automatically points to Employee.class object to access that.

That is the reason why a static variable got changed for every object even if we change it for a single emp object because all emp objects are pointing same copy of that variable from Employee.class object, for more information read Why Java is Purely Object-Oriented Language Or Why Not.

Why an outer Java class can’t be static

From above we can conclude that we should define members as static which
  1. Should be common to all objects of the class.
  2. Should belong to the class and accessible by class name.
  3. Should not need an object of the class to access them.
Now suppose we are defining an outer class as static and suppose we are allowed to do so. Will this serve any purpose or provide any advantage to a developer or it will create ambiguity and complications for both developers and language creators?

Let’s check, defining an outer class as static will serve purposes which we have defined above or not?
  1. Every class is already common to all of its objects and there is no need to make it static to become available to all of its objects.
  2. We need a class name to access its static members because these members are part of class while an outer class is part of the package and we can directly access the class by just writing package_name.class_name (similar to class_name.static_field_name), So again there is no need to do which is already there by default.
  3. We do not need any object to access a class if it is visible, we can simply write package_name.class_name to access it. And by definition, a class is a blueprint for its objects and we create a class to create objects from it (exception will always be there e.g. java.lang.Math), again there is no need to define an outer class as static.
From the above points, we can say Java creators had not allowed an outer class to be static because there is no need to make it static. Allowing to make the outer class static will only increase complications, ambiguity and duplicity.

You can find the complete source code for this article on this Github Repository and please feel free to provide your valuable feedback.
As soon as we try to use private or protected keyword while declaring an outer class compiler gives a compilation error saying “Illegal modifier for the class your_class_name; only public, abstract & final are permitted”.

Here in this article, we are going to study why we are not allowed to use these keywords while declaring outer classes. But before understating the reason behind this we need to understand Java access specifiers and their use cases. There is total 4 access specifier in Java mentioned below in the order of their accessibility.

  1. private: anything (field, class, method, interface etc.) defined using private keyword is only accessible inside the entity (class or package or interface) in which it is defined. 
  2. default: only accessible inside the same package and it is also known as package-private (No modifiers needed).
  3. protected: only accessible inside the same package plus outside the package within child classes through inheritance only. 
  4. public: can be accessed from anywhere.

Why an outer class can not be private

As we already know a field defined in a class using private keyword can only be accessible within the same class and is not visible to outside world.

So what will happen if we will define a class private, that class will only be accessible within the entity in which it is defined which in our case is its package?

Let’s consider below example of class A

package com.example;
class A {
    private int a = 10;

    // We can access a private field by creating object of same class inside the same class
    // But realy no body creates object of a class inside the same class
    public void usePrivateField(){
        A objA =  new A();
        System.out.println(objA.a);
    }
}

Field ‘a’ is declared as private inside ‘A’ class and because of it ‘a’ field becomes private to class ‘A' and can only be accessed within ‘A’. Now let’s assume we are allowed to declare class ‘A’ as private, so in this case class ‘A’ will become private to package ‘com.example’ and will not be accessible from outside of the package.

So defining private access to the class will make it accessible inside the same package which default keyword already do for us, Therefore there is no benefit of defining a class private it will only make things ambiguous.

Why an outer class can not be protected

Access specifier protected is sometimes got confused with the default keyword, for some programmers it becomes hard to identify the exact difference between default and protected accesses. But it is very clear as mentioned below

    default → only accessible within the same package.
    protected → accessible within the same package as well as outside of the package in child classes  through inheritance only.

Let’s consider below example of class A

package com.example;
public class A {
    protected int a = 10;
}

And suppose there is one more class in another package

package com.experiment;
public class B extends A {

    // Outside of the package protected field can be accessed through inheritance
    public void printUsingInheritance() {
        System.out.println(a);
    }

    // In child class we can access protected field through instantiation of child class
    // But should we do that ? .... No
    public void printUsingInstantiation() {
        B b = new B();
        System.out.println(b.a);

        // But not through instantiation of the class which contains the protected field
        A a = new A();
        System.out.println(a.a); // Compilation error “The field A.a is not visible”
    }
}

And suppose there is one more class in the same package

package com.experiment;
public class C {

    // We can not access protected field outside of the child class through instantiation
    public void printUsingInstantiation() {
        B b = new B();
        System.out.println(b.a); // Compilation error “The field B.a is not visible”
    }
}

And if same class 'C' extends 'B', Then again we will be able to access 'a' the same way we are able to access it in B class

package com.experiment;
public class C extends B {

    // outside of the package protected field can only be accessed through inheritance
    public void printUsingInheritance() {
        System.out.println(a);
    }

    // In child class we can access protected field through instantiation as well
    public void printUsingInstantiation() { 
        C c = new C();
        System.out.println(c.a);
    }
}

Because ‘a’ field is protected, we can access it in any way we want to inside the package but outside of the package ‘com.example’ it is only accessible through inheritance and because class ‘B’ is extending class ‘A’ we can use field ‘a’ inside class ‘B’ only as we are doing in printUsingInheritance() method. And we can not use ‘a’ outside of class ‘B’ without inheriting 'B' in another class.

Field ‘a’ will be accessible inside class B in through inheritance only but if we try to create an instance of class ‘B’ in ‘B’ class and then try to access ‘a’ from that instance we will able to use it in a similar manner we can use a private variable in the same class by instantiation of same class.

So If we are allowed to make a class protected then we can access it inside the package very easily but for accessing that class outside of the package we first need to extend that entity in which this class is defined which is again is its package.

And since a package can not be extended (can be imported) defining a class protected will again make it similar to defining it as default which we can already do. So again there is no benefit of defining a class protected.

Please feel free to reach me if you face any problem in understanding it or found any problem in the article.
Complete explanation of Object Oriented JavaScript

01:50 JavaScript Objects
02:36 Objects in Objects
04:12 Constructor Functions
05:58 instanceof
06:28 Passing Objects to Functions
08:09 Prototypes
09:34 Adding Properties to Objects
10:44 List Properties in Objects
11:38 hasOwnProperty
12:42 Add Properties to Built in Objects
14:31 Private Properties
18:01 Getters / Setters
21:20 defineGetter / defineSetter
24:38 defineProperty
27:07 Constructor Function Getters / Setters
29:40 Inheritance
37:13 Intermediate Function Inheritance
39:14 Call Parent Functions
41:51 ECMAScript 6
47:31 Singleton Pattern
49:32 Factory Pattern
52:53 Decorator Pattern
54:52 Observer Pattern



Next Post Newer Posts Previous Post Older Posts Home