Packages and Static Keyword in Java - OOP 2

Introduction👋🏻

Welcome back to the Object Oriented Programming series, hope you are doing great. This will be the second blog in the OOP blog series and in this article, we will be talking about packages and static keyword in Java. In the last blog, we have already covered what are classes and objects, constructors, this keyword, if you haven't read the article yet go and give it a read you will definitely love it and it is also important to understand this blog.

Packages

Packages in Java are nothing but folders under which you can store classes. They are like containers that holds classes in it. The creation of packages prevents multiple classes of the same name to collide with each other. You can have multiple classes of the same name but they should be stored in different packages.

Let's look at how we can create a package. It's really nothing all you need to do is create a folder.

In the image above I have a folder named 'JavaQuestions' inside which I have another folder named 'OOP' inside which I created a folder named 'PackageExample' which is our package. Now if I show it to you in IntelliJ Idea.

You can see I have two packages, one is PackageExample and another is Polymorphism inside the folder OOP. As mentioned above we can have classes of the same name but they should be stored in different packages. Let's try creating a class Main in the PackageExample package.

In the above image, you can see we have the same class Main but in two different packages. The editor shows no red underlines means no error.

The import statement

The import statement can be used to import an entire package or sometimes import certain classes and interfaces inside the package. When you import a package you can use the functionalities of it inside the class you have imported it.

For example, let's create a function count inside the Main class of the PackageExample package, which will print numbers till the user entered value and we will import this function inside the Main class of the Polymorphism package.

package PackageExample;

public class Main {
    public static void main(String[] args) {
        System.out.println("I'm in PackageExample package");
    }

    public static void count(int n) {
        int c = 0;
        for (int i = 1; i <= n; i++) {
            c++;
            System.out.println(c);
        }
    }
}

In the PackageExample package, we created a function in the Main class for counting numbers up to user-entered value.

package Polymorphism;

import static PackageExample.Main.count;

public class Main {
    public static void main(String[] args) {
        int n = 5;
        count(5);
    }
}

Now we are importing the count method in the Main class of the Polymorphism package from the Main class of the PackageExample package.

Now you may have questions like what is static and why we are using public in the method name. We will be covering static in this blog only and public is known as access modifiers which we will learn about in upcoming blogs. Java imports only those methods which are public.

We can also import non-static methods, which I will show you how after we have learnt about the static keyword. So let's jump right into the static keyword.

The static keyword

The static keyword in Java enables a function/method or variable to be accessed without the creation of the object of the class in which it is contained. The best example is the main method in a Java Program, it is the starting point of a Java program and hence it should run before any object is created or it should not depend on the creation of an object.

Static members belong to the class and not to the object. Hence to access the static members we need not create any object. You can also say that static methods are object independent.

When and where Static members can be called?

Let's look at a code:

class Main {
    public static void main(String[] args){
        System.out.print(digits(253));
    }

    static int digits(int n) {
        int count = 0;
        while(n > 0) {
            count++;
            n /= 10;
        }
        return count;
    }
}

In the above example in which we have a function that counts the number of digits and is declared as static. Why? because one static method can only call another static method directly. In order to call a non-static method its object has to be created first.

The reason is simple since static members do not depend on objects hence they cannot call something that depends on the object. But the reverse is not true, a non-static function can call a static function because a static function does not depend on the object and hence can be directly called.

Let's look at each of these cases one by one again for better understanding.

  1. Static function inside a static function: As discussed earlier, anything static does not depend on an object hence it can be directly called inside static or non-static function.

     class Main {
         public static void main(String[] args){
             System.out.print(digits(253));
         }
    
         static int digits(int n) {
             int count = 0;
             while(n > 0) {
                 count++;
                 n /= 10;
             }
             return count;
         }
    
  2. Static function inside a Non-static function: A non-static function can call a static function directly, again the reason remains the same as static functions do not depend on objects.

     class Main {
         public static void main(String[] args){
             // Creating object of the Main class to access 
             //the function sayHello()
             Main obj = new Main();
             obj.sayHello();
         }
    
         void sayHello() {
             digits(253);
         }
         static int digits(int n) {
             int count = 0;
             while(n > 0) {
                 count++;
                 n /= 10;
             }
             return count;
         }
    
  3. Non-static inside Static: A static function cannot call a non-static function directly an object has to be instantiated in order to use the non-static function inside a static function.

     class Main {
         public static void main(String[] args){
             // Creating object of Main to access the digit function
             // which is non static and is to be called 
             // inside the static function main
             Main obj = new Main();
             System.out.print(obj.digits(253));
         }
    
         int digits(int n) {
             int count = 0;
             while(n > 0) {
                 count++;
                 n /= 10;
             }
             return count;
         }
     }
    
  4. Non-static inside Non-static: A non-static function can call a non-static function directly without object creation of the class in which the called function is contained. It is so because in the end a non-static function will ultimately be called inside a static function (main method) where its object will be created. Let's understand with the code below.

     class Main {
         public static void main(String[] args){
             Main obj = new Main();
             obj.printDigits();
         }
    
         void printDigits() {
             // No need to create object for the digit function
             // as it will ultimately be
             // created when this function is called in the main
             // method.
             digits(2364);
         }
         int digits(int n) {
             int count = 0;
             while(n > 0) {
                 count++;
                 n /= 10;
             }
             return count;
         }
     }
    

Static variables

Static variables are declared as:

class Main {
    int num;
    static String name;
}

Since anything static does not depend on objects hence the static members are accessed by the class name instead of the object name.

Hence during the creation of a constructor, we don't use this keyword to initialize the static variables in a class instead we use the class name.

class Main {
    int num;
    static String name;

    Main(int num, String name) {
        this.num = num;
        Main.name = name;
    }
}

But what if you use this keyword? Well, it won't throw any error but, look at this code:

class Main {
    int num;
    static String name;

    Main(int num, String name) {
        this.num = num;
        Main.name = name;
    }

    Main obj1 = new Main(0, "Steve Rogers");
    Main obj2 = new Main(1, "Tony Stark");

    System.out.println(ojb1.name);
    System.out.println(ojb2.name);
}

Can you predict the output? Both the print statements will print the same name i.e. Tony Stark. Because static does not depend on objects hence there is nothing like obj1.name or obj2.name, any change made via any of these two objects will change the value for every object. Hence we follow the convention of calling static variables by the class name.

Even if you want to access the static variables in some other function you have to follow the same convention that is use the class name.

class Main {
    int num;
    static String name;

    Main(int num, String name) {
        this.num = num;
        Main.name = name;
    }

    public static void main(String[] args) {
        Main obj = new Main(0, "Bruce Banner");
        System.out.print(Main.name);
    }
}

Importing non-static functions from a different package.

Remember? We talked about importing non-static methods above, now is the time. Let's learn how to import non-static methods from a different package.

The word non-static implies dependence on the object. Hence to import a non-static method we first have to instantiate it from the class in which it is contained.

Suppose we have a class named 'Test' inside a package named 'PackageExample' inside the class we have a function 'count' which is non-static and in order to access it in a different package we have its access modifier as 'public'

Now inside another package named 'Polymorphism' we have a class 'Main'. Using the import statement we first import the class 'Test' from the package 'PackageExample' so that we can instantiate an object out of it in order to use the non-static function. Now we will create an object named 'obj' of the class 'Test' and now using this object we can easily access the non-static function 'count'.

Static Class (Inner classes)

A class inside a class is called an inner class. We can declare an inner class as static but the outermost class cannot be static, because it is at the outermost level and by common sense it is itself independent of any other class. If you try to create an outer class as static it will throw an error.

Let's try creating a class inside a class

You can see in the image above that IntelliJ idea is showing an error that says, Innerclass cannot be referred from a static context. It is because, since now the Innerclass is inside the Outerclass hence it now depends on the object of the Outerclass, hence in order to be accessed we need to create the object of the class in which it is contained or declare it as static.

As soon as we declare Innerclass as static the error is gone!

What if the Innerclass were outside the Outerclass?

We have already discussed above, that the outermost class depends on nothing hence its object can be created from anywhere, without the static keyword.

Wrapping up🎉

That will be enough for this blog, let's have a quick recap of what we talked about in this blog. First, we talked about packages in Java which are nothing but folders under which classes are stored and it helps us create multiple classes with the same name. Then we learnt about the static keyword which helps us in accessing members of a class without creating its object. We saw different scenarios in which a static method can be called. In the end, we learnt about innerclasses and how they cannot be called without being static. That's it!

In the next blog, we will be learning about the Principle of OOP. If you read the blog till here that means you absolutely loved it so please like the blog and you can also follow me here on Hashnode for more such amazing blogs. You can also follow me on Twitter. Till then Happy Coding🧑🏻‍💻.

0
Subscribe to my newsletter

Read articles from Sreejit Sengupto directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sreejit Sengupto
Sreejit Sengupto

I'm Sreejit Sengupta, an aspiring developer, currently building frontend webapps using React, Taiwind and other tech stacks. Loves to write and talk Tech.