Non-Access Modifiers In Java

We have discussed the access modifiers in Java which controls visibility and accessibility. This post will discuss the Non-access modifiers of Java. Non-access modifiers change the default behaviour of a Java class and its members.

Non-access and access modifiers can be used together, but not all non-access modifiers can be used with access modifiers.

We have 8 non-access modifiers.

Non aceess modifiers

Let’s look at each of them one by one.

abstract non access modifier
Which Java entities can use abstract non-access modifier?

We can use abstract keyword with Java classes, interfaces and methods. We cannot use abstract modifier with Java variables.

The abstract modifier changes the default behaviour of the class, interface, or method. As abstract is a non-access modifier, it won’t change the accessibility of a class, interface, or method.

Abstract class

When we use the abstract keyword with a class, it changes it to an abstract class. An abstract class may or may not have abstract methods.

Below is a simple example of an abstract class

abstract class Codekru{
  private String tutorial;
}

We cannot instantiate an abstract class; in other words, we cannot create the object of an abstract class. So, the below code will not compile.

Codekru c = new Codekru();  // this won't compile
Abstract interface

An interface is an abstract entity by default. Java compiler automatically adds the abstract keyword to the definition of the interface. So, below two statements are the same.

interface Codekru{}
abstract interface Codekru{}
Abstract method

An abstract method doesn’t have a body. The derived class will provide an abstract method implementation.

Below is an example of the abstract method.

abstract method getTutorial(String name);

Remember, a method with an empty body is not an abstract method. All abstract methods will have an abstract keyword in the method declaration.

Abstract variables

We cannot have abstract variables.

static non access modifier
Which Java entities can use static non-access modifier?

We can use static keyword with classes, interfaces, methods and variables.

Static class

We cannot use a static keyword with a top-level class. Java compiler wouldn’t allow us, but we can use the static keyword with a nested class. A nested class is a class within another class.

public class Codekru {

	static class Employee {

	}
}

We can create the objects of an inner static class using the below syntax.

OuterClass.InnerClass variableName  = new OuterClass.InnerClass();

So, our Employee class object can be made using the below line.

Codekru.Employee emp = new Codekru.Employee();

The inner static class can only access the static member of the outer class. It won’t be able to access the non-static member of the outer class.

public class Codekru {

	String name = "codekru"; // this is not accessible to
							// "Employee" class

	static String tutorial; // this is accessible to
							// "Employee" class

	static class Employee {

	}
}

Code Example

public class Codekru {

	String name = "codekru"; // this is not accessible to
								// "Employee" class

	static String tutorial = "java"; // this is accessible to
										// "Employee" class

	static class Employee {
		String getTutorial() {
			return tutorial;
		}
	}

	public static void main(String[] args) {
		Codekru.Employee emp = new Codekru.Employee();
		System.out.println("Tutorial name: " + emp.getTutorial());
	}
}

Output –

Tutorial name: java
Static interface

Like classes, we can only have nested static interfaces, not top-level ones.

public class Codekru {

	static interface Employee {

	}
}
Static methods

Below is an example of the static method.

static void test(){

}
  • Static methods aren’t associated with the objects and can’t use any of the instance variables of a class. Static methods can only use static variables.
  • Static methods can be accessed directly using the class name. We don’t have to make objects to call the static methods. Below is the syntax for calling the static methods.
ClassName.methodName()

Code Example –

public class Codekru {

	String name = "codekru"; // this is not accessible to
								// "getTutorial" method

	static String tutorial = "java"; // this is accessible to
										// "getTutorial" method

	static String getTutorial() {
		return tutorial;
	}

	public static void main(String[] args) {
		System.out.println("Tutorial name: " + Codekru.getTutorial());
	}
}

Output –

Tutorial name: java
Static variables

We can also use the static keyword with the variable. Static variables are associated with the class instead of the objects. The static variable will be allocated memory only once, whereas instance variables will be allocated memory every time an object is created.

We can access the static variable by using the class name directly.

ClassName.variableName

Code Example

public class Codekru {

	String name = "codekru"; // this is not accessible to
								// "getTutorial" method

	static String tutorial = "java"; // this is accessible to
										// "getTutorial" method

	public static void main(String[] args) {
		Codekru c1 = new Codekru();
		c1.tutorial = "golang";

		System.out.println(Codekru.tutorial);
	}
}

Output –

golang

We can see that an object updated the static variable’s value, which was reflected when we accessed the same variable via class name. This is because a static variable is shared across objects, and no new copy is made for various objects.

final non access modifier
Which Java entities can use the final non-access modifier?

The final non-access modifier can be used with the class, method and variable. It cannot be used with the interface.

final class

Another class cannot extend a class marked as final.

final class Codekru{

}

The below statement won’t compile.

class Derived extends Codekru
final interface

An interface cannot be marked as final.

final methods

A derived class cannot override a method marked as final.

public class Codekru {

	String name = "codekru";

	final String getName() {
		return name;
	}
}

A derived class cannot override a final method.

public class Codekru {

	String name = "codekru";

	final String getName() {
		return name;
	}
}

class Derived extends Codekru {

	// this won't be compiled
	String getName() {
		return name;
	}

}
final variables

Variables marked as final cannot be changed. It kind of acts like a constant value in Java. So, if you have such a requirement where you want the value to be constant and don’t want accidental updates anywhere in the program, then you can use the final keyword with that variable.

public class Codekru {

	final String name = "codekru";

	String getName() {
		return name;
	} '
}

If we try to change the value of a final variable, then the code will not compile.

public class Codekru {

	final String name = "codekru";

	String getName() {
		name = "tutorial";  // this won't compile
		return name;
	}
}.
synchronized non access modifier

A race condition might occur in a multi-threaded environment when two or more threads try to update a single resource. Synchronized keyword helps in executing only one thread at a given time.

Which Java entities can use the synchronized non-access modifier?

synchronized non-access modifier can be used with –

  • instance methods
  • static methods
  • code blocks

We can’t use synchronized keyword with variables, interfaces or classes.

The synchronized keyword can be paired with any of the access modifier.

Synchronized methods

We can use the below syntax to synchronise a method so that a single thread can only access it.

[ public | protected | private] synchronized [return_type] method_name () {

}

Here, we have used void, but you can use any return type.

Let’s see two example side by side.

  • The left one doesn’t have synchronization.
  • whereas right-side code uses synchronized keyword.
class Loop {

	void executeForLoop() {
		for (int i = 0; i < 10; i++) {
			System.out.println(i);
		}
	}

}

class ThreadClass extends Thread {
	Loop loop;

	ThreadClass(Loop loop) {
		this.loop = loop;
	}

	@Override
	public void run() {
		loop.executeForLoop();
	}
}

public class Codekru extends Thread {

	public static void main(String[] args) {
		Loop loop = new Loop();

		ThreadClass thread1 = new ThreadClass(loop);
		ThreadClass thread2 = new ThreadClass(loop);
		ThreadClass thread3 = new ThreadClass(loop);

		thread1.start();
		thread2.start();
		thread3.start();
	}

}

Output –

0
1
2
3
0
1
2
3
4
5
6
7
8
9
0
1
4
5
6
7
8
9
2
3
4
5
6
7
8
9
class Loop {

	synchronized void executeForLoop() {
		for (int i = 0; i < 10; i++) {
			System.out.println(i);
		}
	}

}

class ThreadClass extends Thread {
	Loop loop;

	ThreadClass(Loop loop) {
		this.loop = loop;
	}

	@Override
	public void run() {
		loop.executeForLoop();
	}
}

public class Codekru extends Thread {

	public static void main(String[] args) {
		Loop loop = new Loop();

		ThreadClass thread1 = new ThreadClass(loop);
		ThreadClass thread2 = new ThreadClass(loop);
		ThreadClass thread3 = new ThreadClass(loop);

		thread1.start();
		thread2.start();
		thread3.start();
	}

}

Output –

0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

We can see that the numbers are printed in order after using the synchronised keyword. This is because we restricted the method’s access to one thread at a time.

native non access modifier
Which Java entities can use the native non-access modifier?

Only methods can use the native keyword. Classes, variables and interfaces can’t use the native keyword.

Native methods

A native method is a method whose implementation is written in another language like C or C++.

Native methods don’t have a body and will always end with a semi-colon ( ; ), just like an abstract method.

Syntax of the Native methods –

[ public | protected | private] native [return_type] method_name ();
strictfp non access modifier

strictfp stands for strict floating-point.

Which Java entities can use the strictfp non-access modifier?
  • Interfaces, classes and methods can use the strictfp keyword.
  • If the strictfp keyword is used with a class, then all methods in the class will be implicitly strictfp.
  • We cannot use strictfp with the variables.
  • We cannot use strictfp with abstract methods.
strictfp methods

Floating point calculations are platform-dependent. This means that the calculations will depend on the machine on which the class file is being executed.

Thus, we can use the strictfp keyword to make the calculations consistent on different platforms.

public class Codekru {

	public static void main(String[] args) {
		System.out.println(sum());
	}

	static strictfp double sum() {
		double num1 = 23e10;
		double num2 = 98e17;

		return (num1 + num2);
	}

}

Output –

9.800000230000001E18

We can be sure that this result would be the same on every machine or platform.

strictfp classes

We can mark a class with strictfp, and all its methods will inherently be strictfp too.

public strictfp class Codekru {

	public static void main(String[] args) {
		System.out.println(sum());
	}

	static double sum() {
		double num1 = 23e10;
		double num2 = 98e17;

		return (num1 + num2);
	}

}

Output –

9.800000230000001E18
strictfp interfaces

We can also use the strictfp keyword with the interface but not on the interface methods.

strictfp variables

We cannot use strictfp with the variables.

transient non access modifier
Which Java entities can use the transient non-access modifier?

The transient keyword can only be used with variables. It cannot be applied to classes, interfaces, or methods.

transient variables

transient variables are useful when we don’t want to store a particular variable value during serialization. Instead, it will store the default value of that data type.

If we don’t want to store the password value during serialization, we can use the transient keyword with the password variable.

transient data_type variable_name;

Let’s do an exercise where we first store an object in a file and then read the same object again from that file.

We will take an Employee class object to store in the file and make the password a transient variable.

class Employee implements Serializable{
	String name;
	String email;
	transient String password;

	public Employee(String name, String email, String password) {
		this.name = name;
		this.email = email;
		this.password = password;
	}

}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Employee implements Serializable {
	String name;
	String email;
	transient String password;

	public Employee(String name, String email, String password) {
		this.name = name;
		this.email = email;
		this.password = password;
	}

}

public class Codekru {

	public static void main(String[] args) throws IOException, ClassNotFoundException {

		Employee e1 = new Employee("Codekru", "[email protected]", "Codekru1234");

		// writing the object into a file
		FileOutputStream f = new FileOutputStream("file.txt");
		ObjectOutputStream out = new ObjectOutputStream(f);
		out.writeObject(e1);
		out.flush();
		out.close();
		f.close();

		// reading the object from the file
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("file.txt"));
		Employee e2 = (Employee) in.readObject();
		System.out.println("Name: " + e2.name);
		System.out.println("Email: " + e2.email);
		System.out.println("Password: " + e2.password);
		in.close();

	}

}

Output –

Name: Codekru
Email: [email protected]
Password: null

We can see that the password value was stored as null during serialization; thus, the default value of the string data type is printed in the output.

volatile non access modifier
Which Java entities can use the volatile non-access modifier?

volatile keyword can only be used with the variables. It cannot be applied to classes, interfaces, or methods.

volatile variables

Different threads can safely modify a volatile variable’s value. volatile keyword is another way of achieving synchronization.

Let’s think of two threads running on two different processors.

  • These two threads share a common variable.
  • And each thread will have its copy of the variable in the local memory.
  • So, when one thread changes the value of the variable, then it might not be visible to the second thread.
  • And thus, the second will still be working on the variable’s old value.

The above scenario will cause inconsistencies.

When we use the volatile keyword with a variable, the variable value is stored in the main memory, and all read and write operations are done using the main memory.

This helps remove the inconsistencies in the variable’s value.

We hope that you have liked this article. If you have any doubts or concerns, please feel free to write us in the comments or mail us at [email protected]

Related Article –

Liked the article? Share this on

Leave a Comment

Your email address will not be published.