Java Exam Preparation

Created by
BBorhan
Last edited time
Tag

Resources : Slides, ChatGPT, TutorialsPoint

Inheritance

Problem

A:

Boolean Data Type: Represents a binary value, typically denoted as true or false. 1 byte.

public class BooleanExample {
    public static void main(String[] args) {
        boolean isJavaFun = true;
        System.out.println("Is Java fun? " + isJavaFun);
        if (isJavaFun) {
            System.out.println("Yes, Java is fun!");
        } else {
            System.out.println("No, Java is not fun.");
        }
    }
}

A: A concise way to iterate over all elements in an array or a collection. It simplifies the syntax and make it easier to traverse because it doesn’t requires indexing. Syntax:

for (element_type element : array_or_collection) {
    // Code to be executed for each element
}
/*Here, element_type is the data type of the elements in the array or 
collection, and array_or_collection  is the array or collection you 
want to iterate over.*/
public class ForEachExample {
    public static void main(String[] args) {
        // Declare an array of integers
        int[] numbers = {1, 2, 3, 4, 5};

        for (int number : numbers) {
            System.out.println(number);
        }
    }
}

A: Java is not considered a pure object-oriented programming language.

While Java itself is platform-independent, the JVM is platform-dependent. This is because the JVM is specific to each operating system and hardware architecture. When you write Java code, you compile it into bytecode, and this bytecode can be run on any system with the appropriate JVM for that system.

The reason JVM is not platform-independent is that it needs to be implemented differently for each operating system and hardware combination to interact with the underlying system resources.

public class UnequalSize2DArrayExample {
    public static void main(String[] args) {
        int[][] unevenArray = new int[3][]; // Array with 3 "rows"

        unevenArray[0] = new int[3];  // First row with 3 elements
        unevenArray[1] = new int[4];   // Second row with 4 elements
        unevenArray[2] = new int[2];   // Third row with 2 elements

    }
}

In this example, unevenArray is a two-dimensional array where each "row" is an array with a different size. The first row has 3 elements, the second row has 4 elements, and the third row has 2 elements. The program then prints the elements of the two-dimensional array using nested loops.

This flexibility allows you to create a jagged array, which is a two-dimensional array with varying row sizes. It's worth noting that each "row" is a separate array object, and they can have different lengths.

A: In Java, the new keyword is used to dynamically allocate memory for an object at runtime. It is an essential part of the process of object creation.

  • Memory Allocation: allocates memory spaces on the heap
  • Object initialization: called the constructor
  • Return reference: returns a reference to the newly created object

In Java, when a class is declared with the final keyword, it means that the class cannot be subclassed or extended by other classes. The final keyword, when applied to a class, indicates that the class is complete and cannot be further modified in terms of inheritance.

A: The trim() method in Java is used to remove leading and trailing whitespace from a string. Whitespace includes spaces, tabs, and line breaks.

public class TrimExample {
    public static void main(String[] args) {
        String originalString = "   Hello, Trim!   ";
        String trimmedString = originalString.trim();

        // Displaying the results
        System.out.println("Original String: \"" + originalString + "\"");
        System.out.println("Trimmed String: \"" + trimmedString + "\"");
    }
}
/*Output
Original String: "   Hello, Trim!   "
Trimmed String: "Hello, Trim!"
*/

A: Bytecode

Java uses Unicode for character representation to ensure consistent handling of characters across different platforms and languages. Unicode is a standardized character encoding that assigns a unique numeric value to each character, regardless of the platform, program, or language.

In Java, the char type is often categorized as an integer type because it represents 16-bit Unicode characters. While int, short, long, and byte are integral data types used to store integer values, char is specifically designed to store Unicode characters, which are essentially numeric representations of characters from various writing systems.

Yes.

Initialization is the process of providing value to a variable at declaration time. Dynamic initialization of object refers to initializing the objects at run time i.e. the initial value of an object is to be provided during run time. Dynamic initialization can be achieved using constructors and passing parameters values to the constructors.

public class Car {
    String make;
    String model;
    int year;

    public Car(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public static void main(String[] args) {
        Car myCar = new Car("Toyota", "Camry", 2022);
        myCar.displayInfo();
    }
}

FeatureClassObject
DefinitionA blueprint or template for creating objects.An instance of a class; a concrete realization based on the class blueprint.
NatureAbstract, representing a type.Concrete, representing an instance.
PropertiesDefines attributes and behaviors but does not have specific values for them.Has specific values for attributes and can perform actions defined by behaviors.
CreationUsed to create objects.Created based on a class.
InstantiationA class itself cannot be instantiated; it needs to be instantiated to create objects.Represents a specific instance created from a class.
UsageUsed to structure and organize code.Used to model and represent real-world entities.
ExampleIf Car is a class, it might define attributes like make, model, and year, and behaviors like startEngine.If myCar is an object of the Car class, it has specific values for make, model, and year and can perform actions like starting the engine.
MemoryClass definition does not occupy memory at runtime.Each object created from a class consumes memory space to store its state.
KeywordNo keyword associated directly; the class keyword is used in the class definition.No specific keyword; the instance is created using the new keyword followed by the class constructor.

this keyword

public class Car {
    String make;
    String model;
    int year;

    public Car(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public void displayInfo() {
        // Use of 'this' to access instance variables
        System.out.println("Car Make: " + this.make);
        System.out.println("Car Model: " + this.model);
        System.out.println("Manufacturing Year: " + this.year);
    }

    public static void main(String[] args) {
        Car myCar = new Car("Toyota", "Camry", 2022);

        myCar.displayInfo();
    }
}

In this example:

Method overloading is a feature in Java that allows a class to have multiple methods with the same name but different parameters. The parameters can differ in terms of the number, type, or order. Overloaded methods provide flexibility and improve code readability.

public class MathOperations {

    public int add(int a, int b) {
        return a + b;
    }

    public int add(int a, int b, int c) {
        return a + b + c;
    }

    public double add(double a, double b) {
        return a + b;
    }

    public static void main(String[] args) {
        MathOperations mathOps = new MathOperations();

        int result1 = mathOps.add(5, 10);
        int result2 = mathOps.add(3, 7, 12);
        double result3 = mathOps.add(2.5, 3.5);

        System.out.println("Result 1: " + result1);
        System.out.println("Result 2: " + result2);
        System.out.println("Result 3: " + result3);
    }
}

Constructor overloading is a concept similar to method overloading, but it involves having multiple constructors in a class with different parameter lists.

public class OverloadingExample {

    // Constructor Overloading
    public OverloadingExample() {
        System.out.println("Default Constructor");
    }

    public OverloadingExample(int value) {
        System.out.println("Parameterized Constructor with one int parameter: " + value);
    }

    public OverloadingExample(double value1, double value2) {
        System.out.println("Parameterized Constructor with two double parameters: " + value1 + ", " + value2);
    }

    // Method Overloading
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }

    public String add(String str1, String str2) {
        return str1 + str2;
    }

    public static void main(String[] args) {
        // Constructor Overloading
        OverloadingExample defaultConstructor = new OverloadingExample();
        OverloadingExample intConstructor = new OverloadingExample(42);
        OverloadingExample doubleConstructor = new OverloadingExample(3.14, 2.7);

        System.out.println("-------------------------");

        // Method Overloading
        OverloadingExample example = new OverloadingExample();

        int sumInt = example.add(5, 10);
        double sumDouble = example.add(3.5, 2.5);
        String concatenatedString = example.add("Hello, ", "World!");

        // Displaying results
        System.out.println("Sum (int): " + sumInt);
        System.out.println("Sum (double): " + sumDouble);
        System.out.println("Concatenated String: " + concatenatedString);
    }
}

class VisibilityExample {
    public String publicMessage = "This is a public message.";
    private String privateMessage = "This is a private message.";
    protected String protectedMessage = "This is a protected message.";
    String defaultMessage = "This is a default message.";

    public void displayPublicMessage() {
        System.out.println("Public Message: " + publicMessage);
    }

    private void displayPrivateMessage() {
        System.out.println("Private Message: " + privateMessage);
    }

    protected void displayProtectedMessage() {
        System.out.println("Protected Message: " + protectedMessage);
    }

    void displayDefaultMessage() {
        System.out.println("Default Message: " + defaultMessage);
    }
}

class Subclass extends VisibilityExample {
    void displayProtectedFromSubclass() {
        System.out.println("Protected Message from Subclass: " + protectedMessage);
    }

    void displayProtectedMethodFromSubclass() {
        displayProtectedMessage();
    }
}

public class VisibilityControlsExample {
    public static void main(String[] args) {
        VisibilityExample example = new VisibilityExample();

        System.out.println("Public Message: " + example.publicMessage);
        example.displayPublicMessage();

        System.out.println("-------------------------");

        Subclass subclass = new Subclass();
        subclass.displayProtectedFromSubclass();
        subclass.displayProtectedMethodFromSubclass();

        System.out.println("-------------------------");

        // Uncommenting the lines below will result in compilation errors
        // because private and default members are not accessible from outside the class and package.
        
        // System.out.println("Private Message: " + example.privateMessage);
        // example.displayPrivateMessage();

        // System.out.println("Default Message: " + example.defaultMessage);
        // example.displayDefaultMessage();
    }
}

An abstract class in Java is a class that cannot be instantiated on its own and may contain both abstract methods (methods without a body) and concrete methods. • To declare an abstract class, the abstract keyword is used.

True. If a class contains at least one abstract method, it must be declared as abstract itself.

abstract class Shape {
    // Abstract method (no body)
    public abstract double calculateArea();

    // Concrete method with implementation
    public void display() {
        System.out.println("This is a shape.");
    }
}

This is important, because it’s a way of achieving runtime polymorphism or dynamic method dispatch.

When a method is called on an object through a reference variable, the actual method that gets executed is determined at runtime based on the type of the object, not the type of the reference variable. It enables the execution of the overridden method in the subclass, even if the reference variable is of the superclass type.

class Animal {
    void makeSound() {
        System.out.println("Some generic sound");
    }
}

class Dog extends Animal {
    void makeSound() {
        System.out.println("Bark! Bark!");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.makeSound();
    }
}

Inheritance is a mechanism that allows a new class (subclass or derived class) to inherit properties and behaviors from an existing class (base class or superclass).

Benefits:

// Base class (Superclass)
class Vehicle {
    String brand;
    int year;

    // Constructor
    public Vehicle(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }

    // Method
    void start() {
        System.out.println("The vehicle is starting.");
    }
}

// Subclass 1
class Car extends Vehicle {
    int numberOfDoors;

    // Constructor
    public Car(String brand, int year, int numberOfDoors) {
        super(brand, year); // Call to superclass constructor
        this.numberOfDoors = numberOfDoors;
    }

    // Method overriding

    void start() {
        System.out.println("The car engine is starting.");
    }

    void drive() {
        System.out.println("The car is in motion.");
    }
}

// Subclass 2
class Motorcycle extends Vehicle {
    boolean hasSideCar;

    // Constructor
    public Motorcycle(String brand, int year, boolean hasSideCar) {
        super(brand, year); // Call to superclass constructor
        this.hasSideCar = hasSideCar;
    }

    // Method overriding

    void start() {
        System.out.println("The motorcycle engine is starting.");
    }

    void ride() {
        System.out.println("The motorcycle is in motion.");
    }
}

public class InheritanceExample {
    public static void main(String[] args) {
        // Creating instances of subclasses
        Car myCar = new Car("Toyota", 2022, 4);
        Motorcycle myMotorcycle = new Motorcycle("Harley-Davidson", 2021, false);

        // Accessing inherited members
        System.out.println("Car Brand: " + myCar.brand);
        System.out.println("Motorcycle Year: " + myMotorcycle.year);

        // Calling overridden methods
        myCar.start();          // Calls overridden method in Car class
        myMotorcycle.start();   // Calls overridden method in Motorcycle class

        // Calling subclass-specific methods
        myCar.drive();
        myMotorcycle.ride();
    }
}

Abstract classes and methods in Java are used to define a common structure for a group of related classes. Abstract classes cannot be instantiated on their own; they are meant to be extended by subclasses. Abstract methods declared in an abstract class are meant to be implemented by the concrete (non-abstract) subclasses. Abstract classes provide a way to achieve abstraction and define a blueprint for classes that share common characteristics.

abstract class Shape {
    abstract double calculateArea();

    void display() {
        System.out.println("This is a shape.");
    }
}

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }


    double calculateArea() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    private double length;
    private double width;

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    double calculateArea() {
        return length * width;
    }
}

public class AbstractClassExample {
    public static void main(String[] args) {
        Circle myCircle = new Circle(5.0);
        Rectangle myRectangle = new Rectangle(4.0, 6.0);

        myCircle.display();
        System.out.println("Area of Circle: " + myCircle.calculateArea());

        System.out.println("-------------------------");

        myRectangle.display();
        System.out.println("Area of Rectangle: " + myRectangle.calculateArea());
    }
}

class A {
    void displayA() {
        System.out.println("Class A");
    }
}

class B extends A {
    void displayB() {
        System.out.println("Class B");
    }
}

class C extends B {
    void displayC() {
        System.out.println("Class C");
    }
}

class D extends C {
    void displayD() {
        System.out.println("Class D");
    }
}

public class MultilevelInheritanceExample {
    public static void main(String[] args) {
        D objD = new D();

        // Accessing methods from different levels of hierarchy
        objD.displayA(); // From class A
        objD.displayB(); // From class B
        objD.displayC(); // From class C
        objD.displayD(); // From class D
    }
}

Garbage collection is a process in Java that automatically reclaims memory occupied by objects that are no longer in use or reachable by the program. Java employs an automatic garbage collector to manage memory and deallocate objects that are no longer referenced. This helps in avoiding memory leaks and makes memory management more convenient for developers.

The finalize() method is a method defined in the Object class in Java, which is the base class for all other classes. It is invoked by the garbage collector before an object is garbage collected, providing an opportunity to perform cleanup operations.

import java.lang.*;
 
 class prep {
 
    protected void finalize() throws Throwable
    {
        try {
 
            System.out.println("inside prep finalize()");
        }
        catch (Throwable e) {
 
            throw e;
        }
        finally {
 
            System.out.println("Calling finalize method"
                               + " of the Object class");
 
            // Calling finalize() of Object class
            super.finalize();
        }
    }
 
    // Driver code
    public static void main(String[] args) throws Throwable
    {
 
        // Creating demo's object
        prep d = new prep();
 
        // Calling finalize of demo
        d.finalize();
    }
}

FeatureInterfacesAbstract Classes
InheritanceSupports multiple inheritance. A class can implement multiple interfaces.Supports single inheritance. A class can extend only one abstract class.
ConstructorCannot have constructors.Can have constructors, and they are used during object creation.
FieldsCan have only static and final fields.Can have instance variables, static variables, and final variables.
Access ModifiersAll methods are implicitly public and abstract. Fields are implicitly public, static, and final.Can have different access modifiers for methods and fields.
Method TypeMethods are implicitly abstract and public. Can also have default and static methods starting from Java 8.Methods can be abstract or concrete. They may have any access modifier (public, private, protected).
StateCannot contain state (fields) before Java 8 (Java 8 onwards, static and final fields are allowed).Can contain state (fields).
Constructor InvocationNo constructor chaining because there are no constructors in interfaces.Supports constructor chaining through the constructor of the superclass.
Instance CreationCannot be instantiated.Cannot be instantiated; used as a blueprint for subclasses.
Use CasesUsed to achieve multiple inheritance and to define contracts for classes.Used when a common base implementation is needed and to provide a partial or complete implementation.
DependencyPromotes a loosely coupled design as a class can implement multiple interfaces without worrying about the implementation details.Tighter coupling, as a class can extend only one abstract class and is bound to its implementation.
VersioningEasier to add new methods without affecting existing classes that implement the interface.May lead to issues with existing subclasses if new methods are added, especially in backward compatibility scenarios.
Abstract MethodsAll methods are implicitly abstract.May have abstract and concrete methods.
Default MethodsIntroduced in Java 8. Allows adding new methods to interfaces without breaking existing implementations.Not applicable; abstract classes do not have default methods.

An exception in Java is an event that disrupts the normal flow of the program's instructions during execution. It is typically caused by errors or unexpected conditions that occur at runtime. Exceptions can be of different types, such as runtime exceptions, checked exceptions, and errors.

try {
    // Code that may cause an exception
} catch (ExceptionType1 e1) {
    // Handle ExceptionType1
} catch (ExceptionType2 e2) {
    // Handle ExceptionType2
} finally {
    // Code that will be executed regardless of whether an exception occurred or not
}

Benefits:

FeatureExceptionError
TypeChecked or Unchecked ExceptionUnchecked Exception (Runtime Exception)
CauseCaused by external factors or user codeGenerally caused by external factors beyond the control of the application or indicate serious issues in the JVM or the system
HandlingIntended to be caught and handled by the programTypically not caught or handled by the program; often indicates irrecoverable situations
ExamplesIOException, SQLException, NullPointerExceptionOutOfMemoryError, StackOverflowError, NoClassDefFoundError

// User-defined exception class
class NotEqualException extends Exception {
    public NotEqualException(String message) {
        super(message);
    }
}

// Main program
public class CustomExceptionExample {
    public static void main(String[] args) {
        try {
            float floatValue = 3.0f; // Change this value to see the exception

            // Check if the float value is equal to 3.14
            if (floatValue != 3.14f) {
                throw new NotEqualException("Float value is not equal to 3.14");
            } else {
                System.out.println("Float value is equal to 3.14");
            }
        } catch (NotEqualException e) {
            // Handle the custom exception
    System.err.println("Caught NotEqualException: " + e.getMessage());
        }
    }
}

"Write Once, Run Anywhere" (WORA) is a key principle of Java that highlights its platform independence. This principle is achieved through the use of the Java Virtual Machine (JVM) and bytecode.

Java source code is compiled into an intermediate form called bytecode. This bytecode is not specific to any particular hardware or operating system. The compiled bytecode is executed by the Java Virtual Machine (JVM). The JVM is a software-based machine that interprets and executes Java bytecode.

  1. try block:
    • The try block contains the code that might throw an exception.
  1. catch block:
    • The catch block follows the try block and handles the exception if it occurs. Multiple catch blocks can be used to handle different types of exceptions.
  1. throw statement:
    • The throw statement is used to explicitly throw an exception. It is typically used within the try block.
  1. throws clause:
    • The throws clause is used in a method signature to declare the exceptions that the method might throw. It informs the caller about the potential exceptions.
  1. finally block:
    • The finally block contains code that will be executed whether an exception occurs or not. It is optional but commonly used for cleanup operations.

    .

    try {
        // Code that may cause an exception
    } catch (ExceptionType1 e1) {
        // Handle ExceptionType1
    } catch (ExceptionType2 e2) {
        // Handle ExceptionType2
    } finally {
        // Code that will be executed regardless of whether an exception occurred or not
    }

    • throw vs throws
    Featurethrowthrows
    PurposeUsed to explicitly throw an exception in code.Used in method signatures to declare exceptions that the method might throw.
    UsageUsed inside the try block to throw an exception.Used in method declarations followed by the exception types separated by commas.
    Examplethrow new IOException("Invalid input");void exampleMethod() throws IOException { ... }
    ApplicabilityUsed for throwing exceptions programmatically.Used for declaring exceptions that a method may throw, allowing the caller to handle them or propagate them further.
    LocationInside a method or a block of code.In the method signature before the method body.
    Exception TypeCan throw any subclass of Throwable.Specifies the specific exceptions that a method might throw.
    Number of TypesCan throw one exception at a time.Can declare multiple exceptions using a comma-separated list.
    HandlingRequires a corresponding catch block or the method must declare the exception using throws.Alerts the calling code about potential exceptions and allows it to handle them.

    • What is portability? How does Java solve portability problem?

    Portability refers to the ability of software to run on different platforms or systems without modification. In the context of programming languages and applications, a portable program can be written once and then executed on various platforms with minimal or no modifications.

    How Java Solves the Portability Problem:

    1. Bytecode:
      • Java source code is compiled into an intermediate form called bytecode. Bytecode is not platform-specific and can be executed on any device or system that has a Java Virtual Machine (JVM) implemented for that platform.
    1. Java Virtual Machine (JVM):
      • The JVM is a software-based machine that interprets and executes Java bytecode. Each platform or operating system has its own JVM implementation, making it responsible for handling platform-specific details.

The bitwise operators in Java are:

  1. AND (&):
  1. OR (|):
  1. XOR (^):
  1. NOT (~):
  1. Left Shift (<<):
  1. Right Shift (>>):
  1. Unsigned Right Shift (>>>):

why:

static method restrictions

  • directly call only other static methods and variables in their class
  • do not have this reference
  • Cannot Use super in a Static Context:

The super keyword in Java is used to refer to the immediate parent class's members (variables or methods, constructors). It is often used to differentiate between a subclass's members and those of its superclass with the same name.

class Animal {
    void makeSound() {
        System.out.println("Some generic sound");
    }
}

class Dog extends Animal {
    void makeSound() {
        // Calling the superclass's makeSound using super
        super.makeSound();

        // Adding subclass-specific behavior
        System.out.println("Woof! Woof!");
    }
}

public class SuperKeywordExample {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.makeSound();
    }
}

In this example:

FeatureMethod OverridingMethod Overloading
DefinitionOccurs when a subclass provides a specific implementation for a method that is already defined in its superclass.Involves having multiple methods in the same class with the same name but different parameter lists (number, type, or order).
SignatureThe overridden method in the subclass must have the same method signature (name, return type, and parameters) as the one in the superclass.The overloaded methods must have different parameter lists. The return type or access modifiers may remain the same or differ.
InheritanceRelated to inheritance and occurs in a superclass-subclass relationship.Not dependent on inheritance; can occur within the same class or between a superclass and its subclass.
OccurrenceHappens when a subclass wants to provide a specialized implementation for a method defined in its superclass.Involves having multiple methods in the same class with the same name but different parameter lists.
PolymorphismContributes to runtime polymorphism. The version of the method in the subclass replaces the one in the superclass during runtime.Does not involve polymorphism. The appropriate method to be executed is determined at compile-time based on the method signature.
Examplejava class Animal { void makeSound() { System.out.println("Some generic sound"); } } class Dog extends Animal { void makeSound() { System.out.println("Woof! Woof!"); } }java class Calculator { int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } }

Dynamic Method Dispatch is a mechanism in object-oriented programming languages, including Java, where the method that gets executed is determined at runtime based on the actual type of the object. It enables polymorphism and allows a superclass reference variable to refer to a subclass object and invoke overridden methods.

class Animal {
    void makeSound() {
        System.out.println("Some generic sound");
    }
}

class Dog extends Animal {
    void makeSound() {
        System.out.println("Woof! Woof!");
    }
}

class Cat extends Animal {
    void makeSound() {
        System.out.println("Meow!");
    }
}

public class DynamicMethodDispatchExample {
    public static void main(String[] args) {
        Animal myAnimal;

        myAnimal = new Dog(); // Dog object assigned to Animal reference
        myAnimal.makeSound(); // Dynamic method dispatch, calls Dog's makeSound

        myAnimal = new Cat(); // Cat object assigned to Animal reference
        myAnimal.makeSound(); // Dynamic method dispatch, calls Cat's makeSound
    }
}

In this example:

class Alpha {...
class Beta extends Alpha {....
Class Gamma extends Beta {....

In what order do the constructors for these classes complete their execution when a Gamma object is instantiated?

[Keynote: Superclass → subclass of this superclass- > subclass of the …..]

  1. Topmost Superclass (Alpha):
    • The constructor of the topmost superclass (Alpha) is executed first.
  1. Immediate Superclass (Beta):
    • The constructor of the immediate superclass (Beta) is executed next.
  1. Derived Class (Gamma):
    • Finally, the constructor of the derived class (Gamma) is executed.

Therefore, when a Gamma object is instantiated, the order of constructor execution is as follows:

Output:
Alpha’s Constructor
Beta’s Constructor

Gamma’s constructor

class A{
public static void main(String args[]){
int x=99;
{ int x=9;}.
}
}

A variable in a method can be defined only for once. While the “x” is declared twice. So, it will generate an error.

Attempting to declare the variable x again within the inner block will result in a compilation error.

[Right shift : x >> y ⇒ dividing x by 2^y

Left shift : x << y ⇒ multiplying x by 2^y]

3222=8\frac{32}{2^2} = 8

java.lang package is automatically imported into every Java program

This means that classes and interfaces from the java.lang package can be used in a Java program without the need for an explicit import statement.

The java.lang package is a fundamental package in Java and includes essential classes and interfaces that are commonly used, such as Object, String, and basic data types like int and boolean. Since it is automatically imported, you can directly use these classes and data types without explicitly importing them.

Featureprotected Access ModifierDefault (Package-Private) Access Modifier
ScopeAccessible within the same package and subclasses, even if they are in different packages.Accessible only within the same package.
Outside PackageAccessible in subclasses outside the package.Not accessible in subclasses outside the package.
Example Codejava public class A { protected int x; }java class B { int y; }
Example Usagejava public class C extends A { void method() { System.out.println(x); } }java class D { void method() { B obj = new B(); System.out.println(obj.y); } }
InheritanceUseful when you want to expose a member to subclasses, regardless of the package.Useful when you want to limit access to members within the same package.

A class in Java can implement multiple interfaces, and an interface can be implemented by multiple classes.

Yes, an interface can extend other interfaces, just as a class subclass or extend another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces. The interface declaration includes a comma-separated list of all the interfaces that it extends.

interface A {
   void funcA();
}
interface B extends A {
   void funcB();
}
class C implements B {
   public void funcA() {
      System.out.println("This is funcA");
   }
   public void funcB() {
      System.out.println("This is funcB");
   }
}
public class Demo {
   public static void main(String args[]) {
      C obj = new C();
      obj.funcA();
      obj.funcB();
   }
}

Yes, starting from Java 8, it is possible to define a static method in an interface.

Beginning with Java 9, you can have private methods in interfaces.

Since private methods are only accessible within the interface in which it has been defined, you can take advantage of such methods to write sensitive code which you would not want to be accessed by any class or interface

FeatureInstance VariableClass Variable (Static Variable)
DeclarationDeclared inside a class but outside any method.Declared with the static keyword.
Memory AllocationEach instance of the class has its own copy.Shared among all instances of the class.
Access ModifiersCan have different access modifiers.Usually declared as private or public.
InitializationInitialized when an object is created.Initialized when the class is loaded.
UsagePertains to the specific instance of the class.Shared among all instances of the class.
KeywordNo specific keyword used.Declared using the static keyword.
Accessed Using Accessed using an object of the class.Accessed using the class name (ClassName.variable).

FeatureConstructorDestructor (Not present in Java)
PurposeInitializes an object when created.Not applicable; Java relies on garbage collection.
NameSame as the class name.Not applicable; Java doesn't have destructors.
InvocationAutomatically invoked when an object is created.Not applicable; No direct equivalent in Java.
UsageUsed for initialization tasks.Not present in Java; memory cleanup is handled by garbage collection.
Multiple ConstructorsCan have multiple constructors with different parameter lists (overloading).Achieved using constructor overloading.

Multiple constructors in a class can be used through constructor overloading, where you define more than one constructor with different parameter lists.

public class MyClass {
    private int value;

    // Default constructor
    public MyClass() {
        value = 0;
    }

    // Parameterized constructor
    public MyClass(int initialValue) {
        value = initialValue;
    }

    // Another parameterized constructor
    public MyClass(String stringValue) {
        // Convert the string to an integer and set the value
        value = Integer.parseInt(stringValue);
    }

    // Getter method
    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        // Using different constructors
        MyClass obj1 = new MyClass();          // Default constructor
        MyClass obj2 = new MyClass(42);        // Parameterized constructor with an int
        MyClass obj3 = new MyClass("123");     // Parameterized constructor with a string

        // Accessing values
        System.out.println("Value of obj1: " + obj1.getValue());
        System.out.println("Value of obj2: " + obj2.getValue());
        System.out.println("Value of obj3: " + obj3.getValue());
    }
}

In Java, a class implementing an interface can choose to provide a partial implementation by declaring the class as abstract and implementing only some of the interface methods. Other methods can be left unimplemented, to be implemented by concrete subclasses

// Interface with multiple methods
interface MyInterface {
    void method1();  // Unimplemented method
    void method2();  // Unimplemented method
    void method3();  // Unimplemented method
}

// Abstract class implementing the interface partially
abstract class MyAbstractClass implements MyInterface {
    public void method1() {
        System.out.println("Implemented method1 in the abstract class");
    }

    // method2 is not implemented here

    // method3 is not implemented here
}

// Concrete subclass providing the remaining implementations
class MyConcreteClass extends MyAbstractClass {

    public void method2() {
        System.out.println("Implemented method2 in the concrete class");
    }

  
    public void method3() {
        System.out.println("Implemented method3 in the concrete class");
    }
}

public class InterfacePartialImplementationExample {
    public static void main(String[] args) {
        MyConcreteClass myObject = new MyConcreteClass();

        // Calling the implemented methods
        myObject.method1();
        myObject.method2();
        myObject.method3();
    }
}

An exception in Java is an event that disrupts the normal flow of the program's instructions during execution.

  • Checked Exceptions (Compile-time Exceptions): These exceptions are checked at compile-time. The compiler ensures that these exceptions are either handled using try-catch blocks or declared in the method's throws clause.
public class CheckedExceptionExample {
    public static void main(String[] args) {
        try {
            File file = new File("example.txt");
            Scanner scanner = new Scanner(file);
        } catch (FileNotFoundException e) {
            System.out.println("File not found: " + e.getMessage());
        }
    }
}

  • Unchecked Exceptions (Runtime Exceptions): These exceptions are not checked at compile-time and are subclassed from RuntimeException. They usually indicate programming bugs or logical errors.
    public class UncheckedExceptionExample {
        public static void main(String[] args) {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[4]);  // ArrayIndexOutOfBoundsException
        }
    }

  • Error: Errors are serious, often unrecoverable problems that occur at runtime. They are typically outside the control of the application and should not be caught or handled by the program.
    public class ErrorExample {
        public static void main(String[] args) {
            try {
                // .....
            } catch (OutOfMemoryError e) {
    
                System.out.println("Out of memory error: " + e.getMessage());
            }
        }
    }

  • Discuss about the restrictions of a static method. Demonstrate static variables, methods and blocks.

Restrictions of a Static Method:

  1. No Access to Instance Members:
    • A static method cannot directly access or refer to instance variables or instance methods, as it operates at the class level rather than on a specific instance.
  1. Cannot Use this Keyword:
    • The this keyword is not applicable within a static method since there is no specific instance associated with it.
  1. No Direct Access to Non-Static Members:
    • A static method cannot directly access non-static (instance) members of a class. It can only access other static members directly.
    public class StaticExample {
        // Static variable (class variable)
        private static int staticVariable = 0;
    
        // Instance variable
        private int instanceVariable;
    
        // Static block - executed when the class is loaded
        static {
            System.out.println("Static block executed");
            // Can initialize static variables here
            staticVariable = 10;
        }
    
        // Static method
        public static void staticMethod() {
            System.out.println("Static method called");
            // Can only access static members directly
            System.out.println("Static Variable: " + staticVariable);
            // Cannot access instanceVariable directly from a static method
            // System.out.println("Instance Variable: " + instanceVariable); // Compilation error
        }
    
        // Instance method
        public void instanceMethod() {
            System.out.println("Instance method called");
            // Can access both static and instance members
            System.out.println("Static Variable: " + staticVariable);
            System.out.println("Instance Variable: " + instanceVariable);
        }
    
        public static void main(String[] args) {
            // Calling static method without creating an instance
            staticMethod();
    
            // Creating an instance of the class
            StaticExample obj = new StaticExample();
            // Calling instance method
            obj.instanceMethod();
        }
    }

class shape{
    public double w, h;
    shape(double w){
        this.w =w ;
    }
    shape(double w, double h){
        this.w = w; this.h = h;
    }
}

abstract class TwoDShape extends shape{
    TwoDShape(double w, double h){
        super(w, h);
    }
    TwoDShape(double w){
        super(w);
    }
    abstract double getArea();
};

class Square extends TwoDShape{
    Square(double w, double h){
        super(w, h);
    }
    double getArea(){
        return w*h;
    }
}

class Circle extends TwoDShape{
    Circle(double w){
        super(w);
    }
    double getArea(){
        return 3.14*w*w;
    }
}
class Triangle extends TwoDShape{
    Triangle(double w, double h){
        super(w, h);
    }
    double getArea(){
        return 0.5*w*h;
    }
}

abstract class ThreeDShape extends shape{
    ThreeDShape(double w){
        super(w);
    }    
    ThreeDShape(double w, double h){
       super(w, h);
    }
    abstract double getArea();
    abstract double getVolume();
}

class Sphere extends ThreeDShape {
    Sphere(double w){
        super(w);
    }
    double getArea(){
        return 4*3.14*w*w;
    }
    double getVolume(){
        return (4/3)*3.14*w*w*w;
    }
}

class Cube extends ThreeDShape{
    Cube(double w){
        super(w);
    }
    double getArea(){
        return 6*w*w;
    }
    double getVolume(){
        return w*w*w;
    }
}

class Tetrahedron extends ThreeDShape{
    Tetrahedron(double w){
        super(w);
    }
    double getArea(){
        return Math.sqrt(3)*w*w;
    }
    double getVolume(){
        return (Math.sqrt(2)/12)*w*w*w;
    }    
};


class HelloWorld {
    public static void main(String[] args) {
       Triangle tr = new Triangle(5, 6);
       System.out.println(tr.getArea());
    }
}

Sr. No.KeyCompile-time polymorphismRuntime polymorphism
1BasicCompile time polymorphism means binding is occuring at compile timeR un time polymorphism where at run time we came to know which method is going to invoke
2Static/DynamicBindingIt can be achieved through static bindingIt can be achieved through dynamic binding
4.InheritanceInheritance is not involvedInheritance is involved
5ExampleMethod overloading is  an example of compile time polymorphismMethod overriding is an example of runtime polymorphism

Example of Compile-time Polymorphism

public class Main {
   public static void main(String args[]) {
      CompileTimePloymorphismExample obj = new CompileTimePloymorphismExample();
      obj.display();
      obj.display("Polymorphism");
   }
}
class CompileTimePloymorphismExample {
   void display() {
      System.out.println("In Display without parameter");
   }
   void display(String value) {
      System.out.println("In Display with parameter" + value);
   }
}

Example of Runtime Polymorphism

public class Main {
   public static void main(String args[]) {
      RunTimePolymorphismParentClassExample obj = new RunTimePolymorphismSubClassExample();
      obj.display();
   }
}

class RunTimePolymorphismParentClassExample {
   public void display() {
      System.out.println("Overridden Method");
   }
}

public class RunTimePolymorphismSubClassExample extends RunTimePolymorphismParentExample {

   public void display() {
      System.out.println("Overriding Method");
   }
}