Contents

Keyword

Java Keywords

In Java, keywords or reserved words are predefined terms that are used by the language for specific internal processes or actions. As such, these keywords cannot be used as variable names or identifiers; doing so will result in a compile-time error.

Example of Using Java Keywords as Variable Names

				
					// Java Program to Illustrate the Consequences of Using Keywords as Variable Names

// Driver Class
class Example {
    // Main Function
    public static void main(String[] args) {
        // Note "public" is a reserved word in Java
        String public = "Hello, Java!";
        System.out.println(public);
    }
}

				
			

Output:

				
					./Example.java:6: error: illegal start of expression
        String public = "Hello, Java!"; 
        ^
1 error

				
			
Java Keywords List

Java contains a set of keywords that are typically highlighted in different colors in an IDE or editor to distinguish them from other words. Here’s a table summarizing the keywords and their associated actions:

KeywordUsage
abstractSpecifies that a class or method will be implemented later in a subclass.
assertIndicates that a condition is assumed to be true at a specific point in the program.
booleanA data type that can hold true and false values.
breakA control statement used to exit from loops or switch statements.
byteA data type that can hold 8-bit data values.
caseUsed in switch statements to define code blocks.
catchHandles exceptions thrown by try statements.
charA data type that can hold a single 16-bit Unicode character.
classDeclares a new class.
continueSkips the current iteration of a loop and proceeds to the next iteration.
defaultSpecifies the default block of code in a switch statement.
doBegins a do-while loop.
doubleA data type for 64-bit floating-point numbers.
elseSpecifies the alternative branch in an if statement.
enumUsed to declare an enumerated type.
extendsIndicates that a class is derived from another class or interface.
finalIndicates that a variable holds a constant value or that a method cannot be overridden.
finallyA block of code in a try-catch structure that will always execute.
floatA data type for 32-bit floating-point numbers.
forUsed to start a for loop.
ifTests a condition and executes code based on the result.
implementsSpecifies that a class implements an interface.
importReferences other classes or packages.
instanceofChecks whether an object is an instance of a specific class or implements an interface.
intA data type that can hold a 32-bit signed integer.
interfaceDeclares an interface.
longA data type that can hold a 64-bit signed integer.
nativeSpecifies that a method is implemented in platform-specific code.
newCreates new objects.
nullIndicates that a reference does not point to any object.
packageDeclares a Java package.
privateAn access specifier that restricts access to the class where it is declared.
protectedAn access specifier that allows access to subclasses and classes in the same package.
publicAn access specifier that makes a class, method, or variable accessible throughout the application.
returnSends control and possibly a return value back from a called method.
shortA data type that can hold a 16-bit signed integer.
staticIndicates that a method or variable belongs to the class rather than an instance.
strictfpEnsures floating-point calculations follow strict rules for precision.
superRefers to the superclass of the current object.
switchA statement that executes code based on a specified value.
synchronizedIndicates that a method or block is synchronized for thread safety.
thisRefers to the current object within a method or constructor.
throwUsed to explicitly throw an exception.
throwsSpecifies which exceptions a method can throw.
transientIndicates that a variable is not part of an object’s persistent state.
tryStarts a block of code that will be tested for exceptions.
voidSpecifies that a method does not return a value.
volatileIndicates that a variable may be changed unexpectedly, used in multithreading.
whileStarts a while loop.
sealedDeclares a class that restricts which classes can extend it.
permitsUsed within a sealed class declaration to specify permitted subclasses.

Important Notes on Java Keywords

The keywords const and goto are reserved for potential future use but are not currently utilized in Java.

  • const: Reserved for future use.
  • goto: Reserved for future use.

Important Keywords in Java

Keywords are a reserved set of words in a programming language that are used for specific predefined actions.

  • abstract: This non-access modifier is used for classes and methods to achieve abstraction. For more information, see the abstract keyword in Java.

  • enum: This keyword is used to define an enumeration in Java.

  • instanceof: This keyword checks whether an object is an instance of a specified type (class, subclass, or interface).

  • private: This access modifier restricts visibility; anything declared as private is not accessible outside its class.

  • protected: Use this keyword to allow access to an element outside of its package, but only to classes that directly subclass your class.

  • public: Anything declared as public can be accessed from anywhere in the application. For more information on access modifiers, refer to Access Modifiers in Java.

  • static: This keyword is used to create members (blocks, methods, variables, nested classes) that can be accessed without a reference to a specific instance. For more details, refer to the static keyword in Java.

  • strictfp: This keyword restricts floating-point calculations, ensuring consistent results across different platforms. For more information, refer to the strictfp keyword in Java.

  • synchronized: This keyword can be applied to methods or blocks to achieve synchronization in Java. For more details, see Synchronized in Java.

  • transient: This variable modifier is used during serialization. When we don’t want to save the value of a particular variable in a file during serialization, we use the transient keyword. For more information, refer to the transient keyword in Java.

  • volatile: The volatile modifier indicates to the compiler that the variable can be modified unexpectedly by other parts of the program. For more details, see the volatile keyword in Java.

Example Program Using Some Keywords

				
					// Java Program to Demonstrate the Use of Various Keywords

// Abstract class definition
abstract class Animal {
    abstract void sound(); // Abstract method
}

// Enum definition
enum Color {
    RED, GREEN, BLUE
}

// Class implementing the abstract class
class Dog extends Animal {
    void sound() {
        System.out.println("Bark");
    }
}

// Main class
public class KeywordExample {
    // Static variable
    static int count = 0;

    // Synchronized method
    synchronized void increment() {
        count++;
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound(); // Outputs: Bark

        Color myColor = Color.RED; // Using enum
        System.out.println("Color: " + myColor); // Outputs: Color: RED

        KeywordExample example = new KeywordExample();
        example.increment();
        System.out.println("Count: " + count); // Outputs: Count: 1
    }
}

				
			

Output:

				
					Bark
Color: RED
Count: 1

				
			

Super Keyword in Java

Characteristics of the super Keyword in Java

In Java, the super keyword is utilized to refer to the parent class of a subclass. Here are some key characteristics:

  • Calling Superclass Constructors: When a subclass is instantiated, its constructor must invoke the constructor of its parent class using super().

  • Calling Superclass Methods: A subclass can invoke a method defined in its parent class using the super keyword, which is helpful when the subclass wants to execute the parent class’s implementation of that method as well.

  • Accessing Superclass Fields: A subclass can reference a field from its parent class using the super keyword. This is useful in cases where both the subclass and parent class have a field with the same name.

  • Placement in Constructor: The super() statement must be the first line in the constructor of the subclass when invoking a superclass constructor.

  • Static Context Restriction: The super keyword cannot be used in a static context, such as within static methods or static variable initializers.

  • Optional Use for Method Calls: While the super keyword can be used to call a parent class method, it is not necessary if the method is not overridden in the subclass. In such cases, calling the method directly will invoke the parent class’s version.

Overall, the super keyword is a powerful tool for subclassing in Java, allowing subclasses to inherit and extend the functionality of their parent classes.

Uses of the super Keyword in Java

The super keyword is primarily used in the following contexts:

1. Using super with Variables
2. Using super with Methods
3.Using super with Constructors

1. Using super with VariablesThis situation arises when both a derived class and its base class have identical data members, leading to potential ambiguity.

Example:

				
					// Example of super keyword with variables

// Base class Animal
class Animal {
    String type = "Mammal";
}

// Subclass Dog extending Animal
class Dog extends Animal {
    String type = "Canine";

    void display() {
        // Print type from base class (Animal)
        System.out.println("Animal Type: " + super.type);
    }
}

// Driver Program
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.display();
    }
}

				
			

Output:

				
					Drawing a circle.
Drawing a shape.

				
			

In this example, both the base class and subclass have a member type. The super keyword allows us to access the type variable of the base class.

2. Using super with Methods : This usage occurs when we need to call a method from the parent class. If both the parent and child classes have methods with the same name, the super keyword resolves ambiguity.

Example:

				
					// Example of super keyword with methods

// Superclass Shape
class Shape {
    void draw() {
        System.out.println("Drawing a shape.");
    }
}

// Subclass Circle extending Shape
class Circle extends Shape {
    void draw() {
        System.out.println("Drawing a circle.");
    }

    void display() {
        // Calls the current class draw() method
        draw();
        // Calls the parent class draw() method
        super.draw();
    }
}

// Driver Program
public class Test {
    public static void main(String[] args) {
        Circle circle = new Circle();
        circle.display();
    }
}

				
			

In this example, when calling the draw() method, the current class’s implementation is executed, but the super keyword allows us to invoke the superclass’s method as well.

3. Using super with Constructors : The super keyword can also be employed to access the constructor of the parent class. It can call both parameterized and non-parameterized constructors, depending on the situation.

Example 1:

				
					// Example of super keyword with constructors

// Superclass Animal
class Animal {
    Animal() {
        System.out.println("Animal class Constructor");
    }
}

// Subclass Dog extending Animal
class Dog extends Animal {
    Dog() {
        // Invoke the parent class constructor
        super();
        System.out.println("Dog class Constructor");
    }
}

// Driver Program
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}

				
			

Output:

				
					Animal class Constructor
Dog class Constructor

				
			
Advantages of Using the super Keyword in Java

The super keyword in Java offers several advantages in object-oriented programming:

  • Code Reusability: Using super allows subclasses to inherit functionality from their parent classes, promoting code reuse and reducing redundancy.

  • Supports Polymorphism: Subclasses can override methods and access fields from their parent classes using super, enabling polymorphism and allowing for more flexible and extensible code.

  • Access to Parent Class Behavior: Subclasses can utilize methods and fields defined in their parent classes through super, allowing them to leverage existing behavior without needing to reimplement it.

  • Customization of Behavior: By overriding methods and using super to invoke the parent implementation, subclasses can customize and extend the behavior of their parent classes.

  • Facilitates Abstraction and Encapsulation: The use of super promotes encapsulation and abstraction by allowing subclasses to focus on their own behavior while relying on the parent class to manage lower-level details.

final Keyword in Java

The final keyword in Java is a non-access modifier that can be applied to variables, methods, or classes. It is used to impose restrictions on the element to which it is applied.

Key Uses of final in Java:

1. Using super with Variables
2. Using super with Methods
3. Using super with Constructors

By exploring these uses in detail, the Java programming course allows developers to understand how and when to apply the final keyword effectively.

Characteristics of final in Java:

1. Final Variables: When a variable is declared as final, its value cannot be changed once it is initialized. This makes it ideal for defining constants.
2. Final Methods: Declaring a method as final prevents subclasses from modifying or overriding that method, ensuring its behavior is consistent.
3. Final Classes: A final class cannot be extended, meaning no other class can inherit from it. This is useful for creating classes that are intended to be used as-is.
4. Initialization of Final Variables: Final variables must be initialized when they are declared or in a constructor. If not, the program will not compile.
5. Performance: The use of final can sometimes improve performance, as the compiler optimizes final variables or methods better since their behavior is predictable.
6. Security: By making certain variables or methods final, you can prevent malicious code from altering critical parts of your program.

Example of final Variable:

The final keyword in Java is a non-access modifier that can be applied to variables, methods, or classes. It is used to impose restrictions on the element to which it is applied.

Key Uses of final in Java:

1. Variables : A variable declared with final cannot have its value changed after initialization.
2. Methods : A method declared with final cannot be overridden by subclasses.
3. Classes:  A class declared with final cannot be subclassed or extended.

By exploring these uses in detail, the Java programming course allows developers to understand how and when to apply the final keyword effectively.

Characteristics of final in Java:

1. Final Variables: When a variable is declared as final, its value cannot be changed once it is initialized. This makes it ideal for defining constants.
2. Final Methods: Declaring a method as final prevents subclasses from modifying or overriding that method, ensuring its behavior is consistent.
3. Final Classes: A final class cannot be extended, meaning no other class can inherit from it. This is useful for creating classes that are intended to be used as-is.
4. Initialization of Final Variables: Final variables must be initialized when they are declared or in a constructor. If not, the program will not compile.
5. Performance: The use of final can sometimes improve performance, as the compiler optimizes final variables or methods better since their behavior is predictable.
6. Security: By making certain variables or methods final, you can prevent malicious code from altering critical parts of your program.

Example of final Variable:

				
					public class Example {
    public static void main(String[] args) {
        // Declaring a final variable
        final double CONSTANT = 3.14;

        // Printing the value
        System.out.println("Constant value: " + CONSTANT);

        // Attempting to change the value would cause a compile-time error
        // CONSTANT = 3.15;
    }
}

				
			

Output:

				
					Constant value: 3.14

				
			

Different Ways to Use final Variable:

1. Final Variable Initialization at Declaration:

				
					final int MAX_LIMIT = 100;

				
			

2. Blank Final Variable:

				
					final int MAX_LIMIT; // Must be initialized later in the constructor

				
			

3. Static Final Variable:

				
					static final double E = 2.718;

				
			

4. Static Blank Final Variable Initialized in Static Block:

				
					static final int MAX_VALUE;
static {
    MAX_VALUE = 999;
}

				
			
Initialization of Final Variables:

Final variables must be initialized either at declaration or inside constructors. The Java compiler ensures that once a final variable is initialized, it cannot be reassigned.

Example of Blank Final Variable:

				
					class Demo {
    final int THRESHOLD;
    
    // Constructor to initialize blank final variable
    public Demo(int value) {
        this.THRESHOLD = value;
    }
    
    public static void main(String[] args) {
        Demo demo = new Demo(10);
        System.out.println("Threshold: " + demo.THRESHOLD);
    }
}

				
			

Output:

				
					Threshold: 10

				
			
Final Reference Variable (Non-Transitivity):

In the case of reference variables declared as final, you can modify the internal state of the object, but the reference cannot be reassigned.

Example of Final Reference Variable:

				
					class Example {
    public static void main(String[] args) {
        final StringBuilder message = new StringBuilder("Hello");
        System.out.println(message);
        
        // Modifying the internal state of the final object
        message.append(", World!");
        System.out.println(message);
        
        // Reassigning the reference would cause a compile-time error
        // message = new StringBuilder("Hi");
    }
}

				
			

Output:

				
					Hello
Hello, World!

				
			
Final Local Variable:

A final variable inside a method is called a local final variable. It can be initialized once, and any attempt to reassign it will result in an error.

				
					class Example {
    public static void main(String[] args) {
        final int LIMIT;
        LIMIT = 100;  // Variable initialized
        System.out.println("Limit: " + LIMIT);
        
        // LIMIT = 200; // This line would cause a compile-time error
    }
}

				
			

Output:

				
					Limit: 100

				
			
Final Classes:

A class declared as final cannot be extended by any subclass. This is useful when you want to ensure the class’s functionality remains intact and is not modified by other developers.

Example of Final Class:

				
					final class Car {
    void start() {
        System.out.println("Car is starting");
    }
}

// The following class would cause a compile-time error
// class SportsCar extends Car { }

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.start();
    }
}

				
			

Output:

				
					Car is starting

				
			
Final Methods:

When a method is declared as final, it cannot be overridden by any subclass.

				
					class Parent {
    final void show() {
        System.out.println("This is a final method.");
    }
}

class Child extends Parent {
    // The following method would cause a compile-time error
    // void show() {
    //     System.out.println("Trying to override.");
    // }
}

				
			

static Keyword in Java

The static keyword in Java is primarily utilized for memory management. It allows variables or methods to be shared across all instances of a class. Users can apply the static keyword to variables, methods, blocks, and nested classes. Unlike instance members, static members belong to the class itself rather than any particular instance, making them ideal for defining constants or methods that should remain consistent across all objects of the class.

Key Uses of static in Java:

1. Blocks
2. Variables
3. Methods
4. Classes

Characteristics of the static Keyword:

The static keyword plays a crucial role in memory management by enabling class-level variables and methods. For a comprehensive understanding of how to effectively use static, the Java Programming Course offers detailed explanations and practical examples. Here are some key characteristics of the static keyword in Java:

  • Shared Memory Allocation: Static variables and methods are allocated memory space only once during the program’s execution. This shared memory space is accessible by all instances of the class, making static members ideal for maintaining global state or shared functionality.

  • Accessible Without Object Instantiation: Static members can be accessed without creating an instance of the class. This makes them useful for utility functions and constants that need to be accessible throughout the program.

  • Associated with the Class, Not Objects: Static members are tied to the class itself, not to individual objects. Therefore, any changes to a static member are reflected across all instances of the class. Static members can be accessed using the class name rather than an object reference.

  • Cannot Access Non-Static Members: Static methods and variables cannot directly access non-static members of a class because they are not associated with any particular instance of the class.

  • Can Be Overloaded, but Not Overridden: Static methods can be overloaded (multiple methods with the same name but different parameters), but they cannot be overridden since they are linked to the class rather than any instance.

  • Early Access: Static members can be accessed before any objects of the class are created and without referencing any object. For example, in the Java program below, the static method displayMessage() is called without creating an object of the Utility class.

Example Program Accessing Static Method Without Object Creation

				
					// Java program to demonstrate accessing a static method without creating an object

class Utility {
    // Static method
    static void displayMessage() {
        System.out.println("Welcome to the Utility class!");
    }

    public static void main(String[] args) {
        // Calling the static method without creating an instance of Utility
        Utility.displayMessage();
    }
}

				
			

Output:

				
					Welcome to the Utility class!

				
			
Static Blocks

Static blocks are used for initializing static variables or executing code that needs to run once when the class is loaded. They are executed in the order they appear in the class.

Example of Static Block Usage

				
					// Java program to demonstrate the use of static blocks

class Configuration {
    // Static variables
    static String appName;
    static int version;

    // Static block
    static {
        System.out.println("Initializing Configuration...");
        appName = "MyApp";
        version = 1;
    }

    public static void main(String[] args) {
        System.out.println("Application Name: " + appName);
        System.out.println("Version: " + version);
    }
}

				
			

Output:

				
					Initializing Configuration...
Application Name: MyApp
Version: 1

				
			
Static Variables

Static variables, also known as class variables, are shared among all instances of a class. They are typically used to store common properties or constants.

Important Points about Static Variables:
  • Class-Level Scope: Static variables are declared at the class level and are shared by all instances.
  • Initialization Order: Static blocks and static variables are executed in the order they appear in the program.

Example Demonstrating Static Variable Initialization Order

				
					// Java program to demonstrate the initialization order of static blocks and variables

class InitializationDemo {
    // Static variable initialized by a static method
    static int initialValue = initialize();

    // Static block
    static {
        System.out.println("Inside static block.");
    }

    // Static method
    static int initialize() {
        System.out.println("Initializing static variable.");
        return 50;
    }

    public static void main(String[] args) {
        System.out.println("Value of initialValue: " + initialValue);
        System.out.println("Inside main method.");
    }
}

				
			

Output:

				
					Initializing static variable.
Inside static block.
Value of initialValue: 50
Inside main method.

				
			
Static Methods

Static methods belong to the class rather than any particular instance. The most common example of a static method is the main() method. Static methods have several restrictions:

  • They can only directly call other static methods.
  • They can only directly access static data.
  • They cannot refer to this or super keywords.

Example Demonstrating Restrictions on Static Methods

				
					// Java program to demonstrate restrictions on static methods

class Calculator {
    // Static variable
    static int total = 0;

    // Instance variable
    int count = 0;

    // Static method
    static void add(int value) {
        total += value;
        System.out.println("Total after addition: " + total);

        // The following lines would cause compilation errors
        // count += 1; // Error: non-static variable cannot be referenced from a static context
        // displayCount(); // Error: non-static method cannot be referenced from a static context
    }

    // Instance method
    void displayCount() {
        System.out.println("Count: " + count);
    }

    public static void main(String[] args) {
        Calculator.add(10);
        Calculator.add(20);
    }
}

				
			

Output:

				
					Total after addition: 10
Total after addition: 30

				
			
When to Use Static Variables and Methods
  • Static Variables: Use static variables for properties that are common to all instances of a class. For example, if all students share the same school name, the school name can be a static variable.

  • Static Methods: Use static methods for operations that do not require data from instances of the class. Utility or helper methods that perform tasks independently of object state are ideal candidates for static methods.

Example Illustrating Static Variables and Methods

				
					// Java program to demonstrate the use of static variables and methods

class School {
    String studentName;
    int studentId;

    // Static variable for school name
    static String schoolName;

    // Static counter to assign unique IDs
    static int idCounter = 1000;

    public School(String name) {
        this.studentName = name;
        this.studentId = generateId();
    }

    // Static method to generate unique IDs
    static int generateId() {
        return idCounter++;
    }

    // Static method to set the school name
    static void setSchoolName(String name) {
        schoolName = name;
    }

    // Instance method to display student information
    void displayInfo() {
        System.out.println("Student Name: " + studentName);
        System.out.println("Student ID: " + studentId);
        System.out.println("School Name: " + schoolName);
        System.out.println("--------------------------");
    }

    public static void main(String[] args) {
        // Setting the static school name without creating an instance
        School.setSchoolName("Greenwood High");

        // Creating student instances
        School student1 = new School("Emma");
        School student2 = new School("Liam");
        School student3 = new School("Olivia");

        // Displaying student information
        student1.displayInfo();
        student2.displayInfo();
        student3.displayInfo();
    }
}

				
			

Output:

				
					Student Name: Emma
Student ID: 1000
School Name: Greenwood High
--------------------------
Student Name: Liam
Student ID: 1001
School Name: Greenwood High
--------------------------
Student Name: Olivia
Student ID: 1002
School Name: Greenwood High
--------------------------

				
			
Static Classes (Nested Static Classes)

A class can be declared as static only if it is a nested class. Top-level classes cannot be declared as static. Static nested classes do not require a reference to an instance of the outer class and cannot access non-static members of the outer class.

Example of a Static Nested Class

				
					// Java program to demonstrate the use of static nested classes

class OuterClass {
    private static String outerMessage = "Hello from OuterClass!";

    // Static nested class
    static class NestedStaticClass {
        void display() {
            System.out.println(outerMessage);
        }
    }

    public static void main(String[] args) {
        // Creating an instance of the static nested class without an instance of OuterClass
        OuterClass.NestedStaticClass nestedObj = new OuterClass.NestedStaticClass();
        nestedObj.display();
    }
}

				
			

Output:

				
					Hello from OuterClass!

				
			

enum in Java

What is an Enum in Java?

In Java, Enum is a special data type used to define collections of constants. It allows you to represent a fixed set of predefined constants, such as the days of the week, the four seasons, etc. An enum is more than just a list of constants—it can contain methods, constructors, and variables, just like any other Java class.

Enums are particularly useful when you know all possible values at compile time and want to prevent invalid values from being used.

Key Properties of Enums
  • Enum Constants: Each enum constant is an object of the enum type.
  • Implicit Modifiers: Enum constants are public, static, and final.
  • Switch Compatibility: You can use enums with switch statements.
  • Constructor: An enum can contain a constructor that is invoked once for each constant.
  • Method Support: Enums can have methods like regular classes, including abstract methods that must be implemented by each enum constant.
Enum Declaration in Java

Enums can be declared both inside or outside a class, but not inside a method.

1. Declaration Outside the Class

				
					// Enum declared outside the class
enum Direction {
    NORTH,
    SOUTH,
    EAST,
    WEST
}

public class TestEnum {
    public static void main(String[] args) {
        Direction direction = Direction.NORTH;
        System.out.println("The direction is: " + direction);
    }
}

				
			

Output:

				
					The direction is: NORTH

				
			

2. Declaration Inside the Class

				
					// Enum declared inside a class
public class Weather {
    enum Season {
        SPRING,
        SUMMER,
        FALL,
        WINTER
    }

    public static void main(String[] args) {
        Season current = Season.WINTER;
        System.out.println("The current season is: " + current);
    }
}

				
			

Output:

				
					The current season is: WINTER

				
			
Enum in Switch Statements

Enums can be used in switch statements to handle different cases based on enum values.

				
					// Enum in a switch statement
public class DaysOfWeek {
    enum Day {
        MONDAY,
        TUESDAY,
        WEDNESDAY,
        THURSDAY,
        FRIDAY,
        SATURDAY,
        SUNDAY
    }

    public static void main(String[] args) {
        Day today = Day.FRIDAY;

        switch (today) {
            case MONDAY:
                System.out.println("It's the start of the work week.");
                break;
            case FRIDAY:
                System.out.println("Almost the weekend!");
                break;
            case SATURDAY:
            case SUNDAY:
                System.out.println("It's the weekend!");
                break;
            default:
                System.out.println("It's a regular workday.");
        }
    }
}

				
			

Output:

				
					Almost the weekend!

				
			
Looping Through Enum Constants

You can iterate over the constants in an enum using the values() method, which returns an array of all enum constants.

				
					// Looping through enum constants
public class ColorExample {
    enum Color {
        RED, GREEN, BLUE, YELLOW
    }

    public static void main(String[] args) {
        for (Color color : Color.values()) {
            System.out.println("Color: " + color);
        }
    }
}

				
			

Output:

				
					Color: RED
Color: GREEN
Color: BLUE
Color: YELLOW

				
			
Enum with Constructor and Method

Enums can contain constructors and methods, making them more powerful than just simple constants.

				
					// Enum with constructor and method
public class CarTypeExample {
    enum CarType {
        SEDAN(4), SUV(6), TRUCK(8);

        private int seats;

        // Enum constructor
        CarType(int seats) {
            this.seats = seats;
        }

        public int getSeats() {
            return seats;
        }
    }

    public static void main(String[] args) {
        CarType myCar = CarType.SUV;
        System.out.println("My car type is: " + myCar + " with " + myCar.getSeats() + " seats.");
    }
}

				
			

Output:

				
					My car type is: SUV with 6 seats.

				
			
Enum with Abstract Methods

Enums can also contain abstract methods that each constant must implement.

				
					// Enum with abstract method
public class PlanetExample {
    enum Planet {
        MERCURY {
            public String getOrbitalPeriod() {
                return "88 days";
            }
        },
        EARTH {
            public String getOrbitalPeriod() {
                return "365 days";
            }
        },
        MARS {
            public String getOrbitalPeriod() {
                return "687 days";
            }
        };

        public abstract String getOrbitalPeriod();
    }

    public static void main(String[] args) {
        Planet planet = Planet.EARTH;
        System.out.println("The orbital period of " + planet + " is " + planet.getOrbitalPeriod());
    }
}

				
			

Output:

				
					// Using EnumSet to iterate over a specific range of enum values
import java.util.EnumSet;

public class DaysRangeExample {
    enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }

    public static void main(String[] args) {
        EnumSet<Day> workdays = EnumSet.range(Day.MONDAY, Day.FRIDAY);

        for (Day day : workdays) {
            System.out.println("Workday: " + day);
        }
    }
}

				
			

Output:

				
					The orbital period of EARTH is 365 days

				
			

transient keyword in Java

The transient keyword in Java is used to indicate that a particular field should not be serialized when the object is written to a stream. During serialization, if a field is marked as transient, its value is not saved, and when the object is deserialized, that field is assigned its default value according to its data type.

The transient keyword is especially useful for sensitive data that you don’t want to store, such as passwords or fields that can be recalculated at runtime, such as a person’s age or a timestamp.

Usage of transient Keyword

When an object is serialized, all its fields are saved unless they are marked with the transient modifier. If a field is marked as transient, it is skipped during the serialization process, and its value will be reset to the default when the object is deserialized.

This is often used to protect sensitive data, such as passwords, or for fields that can be derived from other fields.

Example of transient Keyword:

				
					// A simple class to demonstrate the use of the transient keyword
import java.io.*;

class Example implements Serializable {
    // Regular fields
    private String username;
    private String email;

    // Password field marked as transient for security
    private transient String password;

    // Age field marked as transient because it can be recalculated
    transient int age;

    // Constructor
    public Example(String username, String email, String password, int age) {
        this.username = username;
        this.email = email;
        this.password = password;
        this.age = age;
    }

    // Display user information
    public void displayInfo() {
        System.out.println("Username: " + username);
        System.out.println("Email: " + email);
        System.out.println("Password: " + password);
        System.out.println("Age: " + age);
    }
}

public class TestTransient {
    public static void main(String[] args) throws Exception {
        // Create an instance of the class
        Example user = new Example("JohnDoe", "john@example.com", "secretPassword", 30);

        // Serialization process
        FileOutputStream fileOut = new FileOutputStream("user_data.txt");
        ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
        objectOut.writeObject(user);
        objectOut.close();
        fileOut.close();

        // Deserialization process
        FileInputStream fileIn = new FileInputStream("user_data.txt");
        ObjectInputStream objectIn = new ObjectInputStream(fileIn);
        Example deserializedUser = (Example) objectIn.readObject();
        objectIn.close();
        fileIn.close();

        // Display the deserialized object's info
        System.out.println("After Deserialization:");
        deserializedUser.displayInfo();
    }
}

				
			

Output:

				
					Username: JohnDoe
Email: john@example.com
Password: null
Age: 0

				
			

In this example:

  • The password and age fields are marked as transient, so they are not serialized.
  • When deserialized, the password field becomes null, and the age field is set to 0 (the default value for integers).
transient and static Fields

The transient keyword has no effect on static fields because static fields are not serialized as part of the object state. Similarly, marking a static field as transient has no impact, as static variables belong to the class and not the instance.

Example with static and final Fields:

				
					// A simple class to demonstrate transient with static and final variables
import java.io.*;

class TestStaticFinal implements Serializable {
    // Regular fields
    int x = 100, y = 200;

    // Transient field
    transient int z = 300;

    // Transient has no effect on static variables
    transient static int a = 400;

    // Transient has no effect on final variables
    transient final int b = 500;

    public static void main(String[] args) throws Exception {
        TestStaticFinal object = new TestStaticFinal();

        // Serialize the object
        FileOutputStream fos = new FileOutputStream("static_final.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(object);
        oos.close();
        fos.close();

        // Deserialize the object
        FileInputStream fis = new FileInputStream("static_final.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        TestStaticFinal deserializedObject = (TestStaticFinal) ois.readObject();
        ois.close();
        fis.close();

        // Display the values after deserialization
        System.out.println("x = " + deserializedObject.x);
        System.out.println("y = " + deserializedObject.y);
        System.out.println("z = " + deserializedObject.z);  // Will be 0 (default value)
        System.out.println("a = " + TestStaticFinal.a);     // Will be 400
        System.out.println("b = " + deserializedObject.b);  // Will be 500
    }
}

				
			

Output:

				
					x = 100
y = 200
z = 0
a = 400
b = 500

				
			

volatile Keyword

The volatile keyword in Java is used to ensure that updates to a variable are immediately visible to all threads. This is essential in a multithreaded environment to prevent inconsistencies due to threads caching variable values locally, which can lead to stale data being used. Let’s consider an example to better understand its behavior.

Problem Without volatile:

When multiple threads are operating on the same variable, they may maintain a local copy of the variable in their own cache. Changes made by one thread may not be immediately visible to the other threads, leading to unpredictable results.

For instance:

				
					class SharedResource {
    // Without volatile, changes made by one thread
    // may not reflect immediately in others.
    static int sharedValue = 10;
}

				
			

With volatile, the sharedValue is always read from the main memory and never from the thread’s cache, ensuring that all threads have the most up-to-date value.

Difference Between volatile and synchronized:
  • Mutual Exclusion: The synchronized keyword ensures that only one thread can access a critical section of code at any time.
  • Visibility: Both volatile and synchronized ensure that changes made by one thread are visible to other threads.

However, if you only need to ensure visibility and don’t require atomic operations (such as incrementing), volatile can be used to avoid the overhead of synchronization.

Example Using volatile:

				
					// Java program to demonstrate the use of volatile keyword
public class VolatileDemo {
    private static volatile int counter = 0;

    public static void main(String[] args) {
        new UpdateThread().start();
        new MonitorThread().start();
    }

    // Thread that monitors changes to the volatile variable
    static class MonitorThread extends Thread {
        @Override
        public void run() {
            int localCounter = counter;
            while (localCounter < 5) {
                if (localCounter != counter) {
                    System.out.println("Detected change in counter: " + counter);
                    localCounter = counter;
                }
            }
        }
    }

    // Thread that updates the volatile variable
    static class UpdateThread extends Thread {
        @Override
        public void run() {
            int localCounter = counter;
            while (counter < 5) {
                System.out.println("Incrementing counter to " + (localCounter + 1));
                counter = ++localCounter;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

				
			

Output (With volatile):

				
					Incrementing counter to 1
Detected change in counter: 1
Incrementing counter to 2
Detected change in counter: 2
Incrementing counter to 3
Detected change in counter: 3
Incrementing counter to 4
Detected change in counter: 4
Incrementing counter to 5
Detected change in counter: 5

				
			

Output (Without volatile):

				
					Incrementing counter to 1
Incrementing counter to 2
Incrementing counter to 3
Incrementing counter to 4
Incrementing counter to 5

				
			

final, finally and finalize in Java

Here’s the modified version of the content with different examples, and the output remains as requested:
final Keyword in Java

In Java, final is a reserved keyword, meaning we cannot use it as an identifier (variable name, method name, etc.). It serves distinct purposes depending on where it is applied — whether to variables, methods, or classes.

1. final with Variables

When a variable is declared as final, its value cannot be modified once initialized. Any attempt to change its value will result in a compile-time error.

				
					class Example1 {
    public static void main(String[] args) {
        // Non-final variable
        int x = 10;

        // Final variable
        final int y = 20;

        // Modifying non-final variable: Allowed
        x++;

        // Modifying final variable: Gives a compile-time error
        y++;  // Error: Cannot assign a value to a final variable 'y'
    }
}

				
			

Here, attempting to modify the value of the final variable y will cause a compile-time error.

2. final with Classes

If a class is declared final, it cannot be subclassed. In other words, no class can extend a final class.

				
					final class SuperClass {
    public void display() {
        System.out.println("This is a final class.");
    }
}

// The following class will cause a compile-time error as `SuperClass` is final and cannot be extended
class SubClass extends SuperClass {
    // Compile-time error: Cannot inherit from final 'SuperClass'
}

				
			

3. final with Methods

When a method is declared as final, it cannot be overridden by subclasses.

				
					class ParentClass {
    final void show() {
        System.out.println("Final method in the parent class.");
    }
}

class ChildClass extends ParentClass {
    // The following method will cause a compile-time error
    void show() {
        // Compile-time error: Cannot override the final method from 'ParentClass'
        System.out.println("Trying to override the final method.");
    }
}

				
			

In this case, the subclass ChildClass cannot override the final method show() from ParentClass.

Note: final with Classes and Methods

If a class is declared final, all its methods are implicitly final by default. However, its variables are not.

				
					final class FinalClass {
    // Method is final by default
    void display() {
        System.out.println("Final class method.");
    }

    // Static variables can still be modified
    static int value = 50;

    public static void main(String[] args) {
        // Modifying the static variable
        value = 60;
        System.out.println("Value: " + value);  // Output: 60
    }
}

				
			
finally Keyword

The finally keyword is associated with try and catch blocks. It ensures that a block of code will always be executed, regardless of whether an exception occurs or not. The finally block is generally used for cleanup operations like closing resources (e.g., file handles, database connections).

Example: finally with Exception Handling

				
					class ExampleFinally {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            throw new RuntimeException("Exception in try");
        } finally {
            System.out.println("Finally block always executes");
        }
    }
}

				
			

In this example, even though an exception is thrown, the finally block still executes.

Cases Involving finally Block:

Case 1: No Exception Occurs

				
					class NoException {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int result = 10 / 2;
        } finally {
            System.out.println("Finally block executed");
        }
    }
}

				
			

Output:

				
					Inside try block
Finally block executed

				
			

Here, no exception occurs, but the finally block still executes.

Case 2: Exception Occurs and is Caught

				
					class CatchException {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            System.out.println("Caught ArithmeticException");
        } finally {
            System.out.println("Finally block executed");
        }
    }
}

				
			

Output:

				
					Inside try block
Caught ArithmeticException
Finally block executed

				
			

Case 3: Exception Occurs but No Catch Block

				
					class NoCatchBlock {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int result = 10 / 0;
        } finally {
            System.out.println("Finally block executed");
        }
    }
}

				
			

Output:

				
					Inside try block
Finally block executed
Exception in thread "main" java.lang.ArithmeticException: / by zero

				
			

Case 4: System.exit(0) in try Block

				
					class ExitExample {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            System.exit(0);
        } finally {
            System.out.println("Finally block not executed");
        }
    }
}

				
			

Output:

				
					Inside try block

				
			
Finalize Method

The finalize method is called by the garbage collector just before an object is destroyed. It is meant for resource cleanup before an object is deleted.

Example: Garbage Collector Calling finalize

				
					class GarbageCollectorExample {
    public static void main(String[] args) {
        GarbageCollectorExample obj = new GarbageCollectorExample();
        obj = null;
        System.gc();
        System.out.println("Main method ends");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Finalize method called");
    }
}

				
			

Output:

				
					Main method ends
Finalize method called