Core Java Concepts: Classes, Inheritance, and Methods

1. Analyzing Java Method Output

Given two methods, display(int x, double y) and display(int p, double q), let’s analyze the output.

  • The first method, display(int x, double y), prints the sum of x and y. Therefore, 4 + 5.0 results in 9.0, which is printed to the console.

  • The second method, display(int p, double q), returns the sum of p and q as a double. So, 4 + 5.0 is 9.0, which is returned and then printed by the System.out.println() call.

Thus, the output of the program will be:

Answer:

9.0
9.0

The correct option is (a) 9.0 9.0.


2. Java Data Types: Size and Default Values

Here are the sizes and default values for common Java data types:

  • boolean:
    • Size: 1 bit
    • Default Value: false
  • char:
    • Size: 2 bytes (16 bits)
    • Default Value: '\u0000' (null character)
  • short:
    • Size: 2 bytes (16 bits)
    • Default Value: 0
  • double:
    • Size: 8 bytes (64 bits)
    • Default Value: 0.0d

3. Core Features of the Java Language

Key Features of Java:

  1. Platform-Independent: Java programs are compiled into bytecode, which can run on any platform with a Java Virtual Machine (JVM). This makes Java platform-independent. For example, a program compiled on Windows can run on Linux or macOS.

  2. Object-Oriented: Java is an object-oriented programming (OOP) language, using classes and objects to structure code. Its key principles include inheritance, polymorphism, encapsulation, and abstraction. For instance, a Car class with properties like color and methods like drive() exemplifies OOP design.

  3. Robust: Java is known for its strong memory management and exception handling. It features automatic garbage collection to prevent memory leaks and provides try-catch blocks for handling errors, reducing runtime crashes.

  4. Distributed Computing: Java provides APIs and tools for developing distributed applications, simplifying work with file systems, databases, and other distributed resources. Java RMI (Remote Method Invocation) allows programs to call methods on remote objects.

  5. Secure: Java has built-in security features like bytecode verification and a security manager to restrict access to system resources. For example, Java applets run in a sandbox environment that restricts file system access.

  6. Multithreading: Java supports multithreading, allowing multiple threads to run concurrently for efficient CPU utilization. A server handling multiple client requests simultaneously is a prime example of Java’s multithreading capabilities.


4. Java Parameterized Constructors with an Example

A parameterized constructor is a constructor that accepts arguments to initialize an object with specific values. Here is an example:

class Student {
    String name;
    int age;

    // Parameterized constructor
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void display() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }

    public static void main(String[] args) {
        // Creating an object with the parameterized constructor
        Student student1 = new Student("John", 20);
        student1.display();
        
        Student student2 = new Student("Alice", 22);
        student2.display();
    }
}

Output:

Name: John
Age: 20
Name: Alice
Age: 22

In this program, the Student class has a parameterized constructor that takes name and age as parameters to initialize the instance variables.


5. Common Java String Functions with Code Snippets

Here are six commonly used string functions in Java:

  1. length(): Returns the length of the string.

    String str = "Hello";
    System.out.println(str.length());  // Output: 5
  2. charAt(): Returns the character at the specified index.

    String str = "Hello";
    System.out.println(str.charAt(1));  // Output: 'e'
  3. toLowerCase(): Converts all characters of the string to lowercase.

    String str = "Hello";
    System.out.println(str.toLowerCase());  // Output: "hello"
  4. toUpperCase(): Converts all characters of the string to uppercase.

    String str = "Hello";
    System.out.println(str.toUpperCase());  // Output: "HELLO"
  5. substring(): Extracts a part of the string based on the specified start and end indices.

    String str = "Hello";
    System.out.println(str.substring(1, 4));  // Output: "ell"
  6. equals(): Compares two strings for equality.

    String str1 = "Hello";
    String str2 = "Hello";
    String str3 = "World";
    System.out.println(str1.equals(str2));  // Output: true
    System.out.println(str1.equals(str3));  // Output: false

6. Understanding Inheritance in Java

Inheritance is a mechanism in Java by which one class can inherit fields and methods from another. This promotes code reuse and establishes a hierarchical relationship between classes.

In Java, inheritance helps build a new class based on an existing one, allowing the new class to inherit the properties and behaviors of the existing class. The class being inherited from is the superclass (or parent class), and the class that inherits is the subclass (or child class).

Types of Inheritance in Java

  1. Single Inheritance: A class inherits from only one superclass. For example, a Car class inherits from a Vehicle class.

    class Vehicle {
        void move() {
            System.out.println("Vehicle is moving");
        }
    }
    
    class Car extends Vehicle {
        void honk() {
            System.out.println("Car is honking");
        }
    }
  2. Multilevel Inheritance: A class inherits from another class, which in turn inherits from a different class. For example, a SportsCar class inherits from Car, which inherits from Vehicle.

    class Vehicle {
        void move() {
            System.out.println("Vehicle is moving");
        }
    }
    
    class Car extends Vehicle {
        void honk() {
            System.out.println("Car is honking");
        }
    }
    
    class SportsCar extends Car {
        void turboBoost() {
            System.out.println("SportsCar turbo boost");
        }
    }
  3. Hierarchical Inheritance: One superclass has multiple subclasses. For example, a Vehicle class has both Car and Bike as subclasses.

    class Vehicle {
        void move() {
            System.out.println("Vehicle is moving");
        }
    }
    
    class Car extends Vehicle {
        void honk() {
            System.out.println("Car is honking");
        }
    }
    
    class Bike extends Vehicle {
        void ride() {
            System.out.println("Bike is riding");
        }
    }
  4. Multiple Inheritance (Through Interfaces): While Java does not support a class inheriting from more than one class directly, multiple inheritance can be achieved by implementing multiple interfaces. For example, a class can implement both a Vehicle and a Horn interface.

    interface Vehicle {
        void move();
    }
    
    interface Horn {
        void honk();
    }
    
    class Car implements Vehicle, Horn {
        public void move() {
            System.out.println("Car is moving");
        }
        public void honk() {
            System.out.println("Car is honking");
        }
    }

7. Abstract Class vs. Interface in Java

Abstract Class

  • An abstract class cannot be instantiated on its own. It can have both abstract methods (without a body) and concrete methods (with a body).
  • Key Points:
    • Used to define common behaviors and can contain abstract and non-abstract methods.
    • Can have member variables (fields), constructors, and methods.
    • A class can only extend one abstract class, as Java does not support multiple inheritance of classes.
  • Example:
    abstract class Animal {
        abstract void sound(); // Abstract method
    
        void sleep() {  // Concrete method
            System.out.println("Animal is sleeping");
        }
    }
    
    class Dog extends Animal {
        void sound() {
            System.out.println("Dog barks");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Animal myDog = new Dog();
            myDog.sound();
            myDog.sleep();
        }
    }

Interface

  • An interface is a reference type that can contain only constants, method signatures, default methods, static methods, and nested types. Interfaces cannot have instance fields or constructors.
  • Key Points:
    • Used to represent a contract or capability (what a class can do).
    • A class can implement multiple interfaces, enabling a form of multiple inheritance.
    • All methods in an interface are implicitly public and abstract unless they are default or static.
  • Example:
    interface Animal {
       void sound(); // Abstract method
    }
    
    class Dog implements Animal {
       public void sound() {
         System.out.println("Dog barks");
        }
    }
    
    public class Test {
     public static void main(String[] args) {
          Animal myDog = new Dog();
          myDog.sound();
        }
    }

Key Differences Summarized

FeatureAbstract ClassInterface
Multiple InheritanceNot supported (a class can extend only one abstract class).Supported (a class can implement multiple interfaces).
MethodsCan have both abstract and non-abstract (concrete) methods.Can only have abstract methods (before Java 8). Java 8+ allows default and static methods.
FieldsCan have final, non-final, static, and non-static variables.Variables are implicitly public, static, and final.
ConstructorsCan have constructors.Cannot have constructors.

8. The Usage of the Java `super` Keyword

In Java, the super keyword refers to the superclass (parent) of the current object. It is used to access methods, constructors, and fields from the parent class.

Usage of the `super` Keyword

  1. Accessing Parent Class Constructor: The super() call invokes the constructor of the parent class. If not called explicitly, the default constructor of the superclass is invoked automatically.

    Example:

    class Animal {
        Animal() {
            System.out.println("Animal constructor");
        }
    }
    
    class Dog extends Animal {
        Dog() {
            super();  // Call to the parent class constructor
            System.out.println("Dog constructor");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Dog dog = new Dog(); // Output: Animal constructor, Dog constructor
        }
    }
  2. Accessing Parent Class Methods: The super keyword is used to invoke methods from the parent class that have been overridden in the subclass.

    Example:

    class Animal {
        void sound() {
            System.out.println("Animal makes a sound");
        }
    }
    
    class Dog extends Animal {
        void sound() {
            super.sound();  // Call to the parent class method
            System.out.println("Dog barks");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.sound();  // Output: Animal makes a sound, Dog barks
        }
    }
  3. Accessing Parent Class Fields: The super keyword is used to access fields from the parent class, especially when there is a naming conflict.

    Example:

    class Animal {
        String name = "Animal";
    }
    
    class Dog extends Animal {
        String name = "Dog";
    
        void printNames() {
            System.out.println("Child name: " + name); // Prints Dog
            System.out.println("Parent name: " + super.name); // Prints Animal
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.printNames(); // Output: Child name: Dog, Parent name: Animal
        }
    }

9. Constructor Overloading and Method Overriding Example

This program demonstrates a Shape class with overloaded constructors and a Test class that overrides the calculate() method.

// Shape class with two constructors
class Shape {
    double length;
    double width;

    // Constructor 1
    public Shape(double length) {
        this.length = length;
        System.out.println("Shape with length: " + length);
    }

    // Constructor 2
    public Shape(double length, double width) {
        this.length = length;
        this.width = width;
        System.out.println("Shape with length: " + length + " and width: " + width);
    }

    // Method to calculate area (default implementation)
    public double calculate() {
        return 0;
    }
}

// Test class inheriting from Shape
class Test extends Shape {

    // Constructor 1 calling Shape's constructor with one argument
    public Test(double length) {
        super(length);  // Calling Shape constructor
    }

    // Constructor 2 calling Shape's constructor with two arguments
    public Test(double length, double width) {
        super(length, width);  // Calling Shape constructor
    }

    // Overriding the calculate method to calculate the area of a rectangle
    @Override
    public double calculate() {
        return length * width;  // Area calculation for a rectangle
    }

    public static void main(String[] args) {
        // Creating object with 1 parameter
        Test test1 = new Test(5);
        System.out.println("Area: " + test1.calculate());  // Area will be 0 as width is not initialized

        // Creating object with 2 parameters
        Test test2 = new Test(5, 10);
        System.out.println("Area: " + test2.calculate());  // Area will be 50
    }
}

Explanation

  1. Shape Class: The Shape class has two constructors (constructor overloading): one accepts only length, and the other accepts both length and width. The calculate() method returns 0 by default.
  2. Test Class: The Test class extends Shape and provides two constructors that call the corresponding constructors of the Shape class using super(). It overrides the calculate() method to compute the area based on length and width.

Output

Shape with length: 5.0
Area: 0.0
Shape with length: 5.0 and width: 10.0
Area: 50.0