[Go to site: main page, start]

0% found this document useful (0 votes)
14 views20 pages

Java Inheritance and Polymorphism Explained

Inheritance is a key concept in Object-Oriented Programming (OOP) that allows one class to inherit features from another, promoting reusability. Java supports various types of inheritance including single, multilevel, hierarchical, and multiple inheritance through interfaces. Additionally, polymorphism enables methods to perform different tasks based on the object that invokes them, further enhancing the flexibility of code in Java.

Uploaded by

renuajith39
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views20 pages

Java Inheritance and Polymorphism Explained

Inheritance is a key concept in Object-Oriented Programming (OOP) that allows one class to inherit features from another, promoting reusability. Java supports various types of inheritance including single, multilevel, hierarchical, and multiple inheritance through interfaces. Additionally, polymorphism enables methods to perform different tasks based on the object that invokes them, further enhancing the flexibility of code in Java.

Uploaded by

renuajith39
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Unit 2

Unit 2
Inheritance is an important pillar of OOP(Object-Oriented Programming). It is the
mechanism in java by which one class is allowed to inherit the features(fields and
methods) of another class.
Important terminology:
 Super Class: The class whose features are inherited is known as superclass(or a
base class or a parent class).
 Sub Class: The class that inherits the other class is known as a subclass(or a
derived class, extended class, or child class). The subclass can add its own fields
and methods in addition to the superclass fields and methods.
 Reusability: Inheritance supports the concept of “reusability”, i.e. when we want to
create a new class and there is already a class that includes some of the code that
we want, we can derive our new class from the existing class. By doing this, we are
reusing the fields and methods of the existing class.
How to use inheritance in Java
The keyword used for inheritance is extends.
Syntax :

class derived-class extends base-class


{
//methods and fields
}

1. Single Inheritance: In single inheritance, subclasses inherit the features of one


superclass. In the image below, class A serves as a base class for the derived class
B.

// Java program to illustrate the


// concept of single inheritance
import [Link].*;
import [Link].*;
import [Link].*;

class one {
public void print_geek()
{
[Link]("Geeks");
}
}

class two extends one {


public void print_for() { [Link]("for"); }
}
// Driver class
public class Main {
public static void main(String[] args)
{
two g = new two();
g.print_geek();
g.print_for();
g.print_geek();
}
}

Output

Geeks
for
Geeks

Multilevel Inheritance: In Multilevel Inheritance, a derived class will be inheriting a


base class and as well as the derived class also act as the base class to other class.
In the below image, class A serves as a base class for the derived class B, which in
turn serves as a base class for the derived class C.

// Java program to illustrate the


// concept of Multilevel inheritance
import [Link].*;
import [Link].*;
import [Link].*;

class one {
public void print_geek()
{
[Link]("Geeks");
}
}

class two extends one {


public void print_for()
{ [Link]("for"); } }

class three extends two {


public void print_geek()
{
[Link]("Geeks");
}
}

// Drived class
public class Main {
public static void main(String[] args)
{
three g = new three();
g.print_geek();
g.print_for();
g.print_geek();
}
}

Output

Geeks
for
Geeks

// Java program to illustrate the


// concept of Multilevel inheritance
import [Link].*;
import [Link].*;
import [Link].*;

class one {
public void print_geek()
{
[Link]("Geeks");
}
}

class two extends one {


public void print_for()
{ [Link]("for"); } }

class three extends two {


public void print_geek()
{
[Link]("Geeks");
}
}

// Drived class
public class Main {
public static void main(String[] args)
{
three g = new three();
g.print_geek();
g.print_for();
g.print_geek();
}
}
Output

Geeks
for
Geeks

3. Hierarchical Inheritance: In Hierarchical Inheritance, one class serves as a superclass


(base class) for more than one subclass. In the below image, class A serves as a base
class for the derived class B, C and D.

// Java program to illustrate the


// concept of Hierarchical inheritance

class A {
public void print_A() { [Link]("Class
A"); } }

class B extends A {
public void print_B() { [Link]("Class
B"); } }

class C extends A {
public void print_C() { [Link]("Class
C"); } }

class D extends A {
public void print_D() { [Link]("Class
D"); } }

// Driver Class
public class Test {
public static void main(String[] args)
{
B obj_B = new B();
obj_B.print_A();
obj_B.print_B();

C obj_C = new C();


obj_C.print_A();
obj_C.print_C();

D obj_D = new D();


obj_D.print_A();
obj_D.print_D();
}
}

Output
Class A
Class B
Class A
Class C
Class A
Class D
4.
Multiple

Inheritance (Through Interfaces): In Multiple inheritances, one class can have more than
one superclass and inherit features from all parent classes. Please note that Java does
not support multiple inheritances with classes. In java, we can achieve multiple
inheritances only through Interfaces. In the image below, Class C is derived from interface
A and B.

// Java program to illustrate the


// concept of Multiple inheritance
import [Link].*;
import [Link].*;
import [Link].*;

interface one {
public void print_geek();
}

interface two {
public void print_for();
}

interface three extends one, two {


public void print_geek();
}
class child implements three {
@Override public void print_geek()
{
[Link]("Geeks");
}

public void print_for() { [Link]("for"); }


}

// Drived class
public class Main {
public static void main(String[] args)
{
child c = new child();
c.print_geek();
c.print_for();
c.print_geek();
}
}

Output
Geeks
for

Geeks
5. Hybrid Inheritance(Through Interfaces): It is a mix of two or more of the above types
of inheritance. Since java doesn’t support multiple inheritances with classes, hybrid
inheritance is also not possible with classes. In java, we can achieve hybrid inheritance
only through Interfaces.

Java Polymorphism
Polymorphism means "many forms", and it occurs when we have many classes that are
related to each other by inheritance.
In simple words, we can define polymorphism as the ability of a message to be
displayed in more than one form.
Real life example of polymorphism: A person at the same time can have different
characteristic. Like a man at the same time is a father, a husband, an employee. So the
same person posses different behavior in different situations. This is called polymorphism.
Polymorphism is considered one of the important features of Object-Oriented
Programming. Polymorphism allows us to perform a single action in different ways. In
other words, polymorphism allows you to define one interface and have multiple
implementations. The word “poly” means many and “morphs” means forms, So it means
many forms.

Inheritance lets us inherit attributes and methods from another class. Polymorphism
uses those methods to perform different tasks. This allows us to perform a single action in
different ways.
class Animal {
public void animalSound() {
[Link]("The animal makes a sound");
}
}

class Pig extends Animal {


public void animalSound() {
[Link]("The pig says: wee wee");
}
}

class Dog extends Animal {


public void animalSound() {
[Link]("The dog says: bow wow");
}
}

class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Create a Animal object
Animal myPig = new Pig(); // Create a Pig object
Animal myDog = new Dog(); // Create a Dog object
[Link]();
[Link]();
[Link]();
}
}
output:
The animal makes a sound
The pig says: wee wee
The dog says: bow wow
In Java polymorphism is mainly divided into two types:
 Compile time Polymorphism
 Runtime Polymorphism
1. Compile-time polymorphism: It is also known as static polymorphism. This type of
polymorphism is achieved by function overloading or operator overloading. But Java
doesn’t support the Operator Overloading.

Method Overloading: When there are multiple functions with same name but different
parameters then these functions are said to be overloaded. Functions can be overloaded
by change in number of arguments or/and change in type of arguments.
Example: By using different types of arguments
// Java program for Method overloading

class MultiplyFun {

// Method with 2 parameter


static int Multiply(int a, int b)
{
return a * b;
}

// Method with the same name but 2 double parameter


static double Multiply(double a, double b)
{
return a * b;
}
}

class Main {
public static void main(String[] args)
{

[Link]([Link](2, 4));

[Link]([Link](5.5, 6.3));
}
}

Output:
8
34.65

. Runtime polymorphism: It is also known as Dynamic Method Dispatch. It is a process


in which a function call to the overridden method is resolved at Runtime. This type of
polymorphism is achieved by Method Overriding.

Method overriding, on the other hand, occurs when a derived class has a definition for
one of the member functions of the base class. That base function is said to be
overridden.
Example:
// Java program for Method overriding

class Parent {

void Print()
{
[Link]("parent class");
}
}
class subclass1 extends Parent {

void Print()
{
[Link]("subclass1");
}
}

class subclass2 extends Parent {

void Print()
{
[Link]("subclass2");
}
}

class TestPolymorphism3 {
public static void main(String[] args)
{

Parent a;

a = new subclass1();
[Link]();

a = new subclass2();
[Link]();
}
}
Output:
subclass1
subclass2

Using final with Inheritance

how to use final apply to inheritance.


Using final to Prevent Overriding

While method overriding is one of Java’s most powerful [Link] disallow a method
from being overridden,specify final as a modifier at the start of its declaration.
Methods declared as final cannot be overridden.
Example1:using final to Prevent Overriding

class A
{
final void meth()
{
[Link]("This is a final method.");
}
}
class B extends A
{
void meth() // ERROR! Can't override.
{
[Link]("Illegal!");
}
}
Here meth( ) is declared as final, it cannot be overridden in B. If you attempt to do so, a
compile time error will result.
Using final to Prevent Inheritance

Sometimes you will want to prevent a class from being inherited. To do this, precede the
class declaration with final. Declaring a class as final implicitly declares all of its methods
as final, too. As you might expect, it is illegal to declare a class as both abstract and final
since an abstract class is incomplete by itself and relies upon its subclasses to provide
complete implementations.

an example of a final class:


final class A
{
// ...
}
// The following class is illegal.
class B extends A // ERROR! Can't subclass A
{
// ...
}

As the comments imply, it is illegal for B to inherit A since A is declared as final.

Abstract Classes and Methods


Data abstraction is the process of hiding certain details and showing only essential
information to the user.
Abstraction can be achieved with either abstract classes or interfaces (which you will
learn more about in the next chapter).
The abstract keyword is a non-access modifier, used for classes and methods:
 Abstract class: is a restricted class that cannot be used to create objects (to
access it, it must be inherited from another class).
 Abstract method: can only be used in an abstract class, and it does not have a
body. The body is provided by the subclass (inherited from).
An abstract class can have both abstract and regular methods:
abstract class Animal {
public abstract void animalSound();
public void sleep() {
[Link]("Zzz");
}
}

From the example above, it is not possible to create an object of the

Animal class: Animal myObj = new Animal(); // will generate an error


To access the abstract class, it must be inherited from another class.
Example
// Abstract class
abstract class Animal {
// Abstract method (does not have a body)
public abstract void animalSound();
// Regular method
public void sleep() {
[Link]("Zzz");
}
}

// Subclass (inherit from Animal)


class Pig extends Animal {
public void animalSound() {
// The body of animalSound() is provided here
[Link]("The pig says: wee wee");
}
}

class Main {
public static void main(String[] args) {
Pig myPig = new Pig(); // Create a Pig object
[Link]();
[Link]();
}
}

The pig says: wee wee


Zzz

Java static Keyword


Example
A static method can be accessed without creating an object of the class first:
public class Main {
// Static method
static void myStaticMethod() {
[Link]("Static methods can be called without creating
objects"); }

// Public method
public void myPublicMethod() {
[Link]("Public methods must be called by creating
objects"); }

// Main method
public static void main(String[ ] args) {
myStaticMethod(); // Call the static method
// myPublicMethod(); This would output an error

Main myObj = new Main(); // Create an object of Main


[Link](); // Call the public method
}
}
output:
Static methods can be called without creating objects
Public methods must be called by creating objects

Final
If you don't want the ability to override existing attribute values, declare attributes
as final: Example
public class Main {
final int x = 10;
final double PI = 3.14;

public static void main(String[] args) {


Main myObj = new Main();
myObj.x = 50; // will generate an error: cannot assign a value to a final
variable [Link] = 25; // will generate an error: cannot assign a value to
a final variable [Link](myObj.x);
}
}

output:
[Link]: error: cannot assign a value to final variable x
myObj.x = 50;
^
[Link]: error: cannot assign a value to final variable PI
[Link] = 25;
^ 2 errors

Java this Keyword


Example
Using this with a class attribute (x):
public class Main {
int x;

// Constructor with a parameter


public Main(int x) {
this.x = x;
}

// Call the constructor


public static void main(String[] args) {
Main myObj = new Main(5);
[Link]("Value of x = " + myObj.x);
}
}

output:
Value of x = 5

Definition and Usage


The this keyword refers to the current object in a method or constructor.
The most common use of the this keyword is to eliminate the confusion between class
attributes and parameters with the same name (because a class attribute is shadowed by
a method or constructor parameter). If you omit the keyword in the example above, the
output would be "0" instead of "5".
this can also be used to:
 Invoke current class constructor
 Invoke current class method
 Return the current class object
 Pass an argument in the method call
 Pass an argument in the constructor call
Strings in Java

Strings in Java are Objects that are backed internally by a char array. Since arrays are
immutable(cannot grow), Strings are immutable as well. Whenever a change to a String is
made, an entirely new String is created.
Syntax:
<String_Type> <string_variable> = "<sequence_of_string>";

Example:
String str = "Geeks";

Memory allotment of String


Whenever a String Object is created as a literal, the object will be created in String
constant pool. For example:
String str = "Geeks";

The string can also be declared using new operator i.e. dynamically allocated. In case of
String are dynamically allocated they are assigned a new memory location in heap. This
string will not be added to String constant pool.
For example:
String str = new String("Geeks");

What is String in java


Generally, String is a sequence of characters. But in Java, string is an object that represents a
sequence of characters. The [Link] class is used to create a string object.
How to create a string object?
There are two ways to create String object:
1. By string literal
2. By new keyword
1) String Literal
Java String literal is created by using double quotes. For Example:
1. String s="welcome";
Each time you create a string literal, the JVM checks the "string constant pool" first. If the string
already exists in the pool, a reference to the pooled instance is returned. If the string doesn't exist in
the pool, a new string instance is created and placed in the pool. For example:
1. String s1="Welcome";
2. String s2="Welcome";//It doesn't create a new instance

2) By new keyword
1. String s=new String("Welcome");//creates two objects and one reference variable
In such case, JVM will create a new string object in normal (non-pool) heap memory, and
the literal "Welcome" will be placed in the string constant pool. The variable s will refer to
the object in a heap (non-pool).
Java String Example
public class StringExample{
public static void main(String args[]){
String s1="java";//creating string by java string literal
char ch[]={'s','t','r','i','n','g','s'};
String s2=new String(ch);//converting char array to string
String s3=new String("example");//creating java string by new keyword
[Link](s1);
[Link](s2);
[Link](s3);
}}
output:

java
strings
example

An example that shows how to declare String

// Java code to illustrate String


import [Link].*;
import [Link].*;

class Test {
public static void main(String[] args)
{
// Declare String without using new operator
String s = "GeeksforGeeks";

// Prints the String.


[Link]("String s = " + s);

// Declare String using new operator


String s1 = new String("GeeksforGeeks");

// Prints the String.


[Link]("String s1 = " + s1);
}
}
Output:
String s = GeeksforGeeks
String s1 = GeeksforGeeks

StringBuffer is a peer class of String that provides much of the functionality of strings.
The string represents fixed-length, immutable character sequences while StringBuffer
represents growable and writable character sequences.
Syntax:
StringBuffer s = new StringBuffer("GeeksforGeeks");

StringBuffer class in Java


 Difficulty Level : Easy
 Last Updated : 06 Dec, 2018
String Class in Java
StringBuffer is a peer class of String that provides much of the functionality of strings.
String represents fixed-length, immutable character sequences while StringBuffer
represents growable and writable character sequences.
StringBuffer may have characters and substrings inserted in the middle or appended to
the end. It will automatically grow to make room for such additions and often has more
characters preallocated than are actually needed, to allow room for growth.
StringBuffer Constructors
StringBuffer( ): It reserves room for 16 characters without reallocation.
StringBuffer s=new StringBuffer();

StringBuffer( int size)It accepts an integer argument that explicitly sets the size of
the buffer. StringBuffer s=new StringBuffer(20);

StringBuffer(String str): It accepts a String argument that sets the initial contents of the
StringBuffer object and reserves room for 16 more characters without reallocation.
StringBuffer s=new StringBuffer("GeeksforGeeks");

Methods
Some of the most used methods are:
 length( ) and capacity( ): The length of a StringBuffer can be found by the length( )
method, while the total allocated capacity can be found by the capacity( ) method.
Code Example:
import [Link].*;
class GFG {
public static void main(String[] args)
{
StringBuffer s = new StringBuffer("GeeksforGeeks");
int p = [Link]();
int q = [Link]();
[Link]("Length of string GeeksforGeeks=" + p);
[Link]("Capacity of string GeeksforGeeks=" + q);
}
}

Output:
Length of string GeeksforGeeks=13
Capacity of string GeeksforGeeks=29

 append( ): It is used to add text at the end of the existence text. Here are a few of its forms:
StringBuffer append(String str)
StringBuffer append(int num)

Code Example:
import [Link].*;
class GFG {
public static void main(String[] args)
{
StringBuffer s = new StringBuffer("Geeksfor");
[Link]("Geeks");
[Link](s); // returns GeeksforGeeks
[Link](1);
[Link](s); // returns GeeksforGeeks1
}
}

Output:
GeeksforGeeks
GeeksforGeeks1
Java Arrays
Arrays are used to store multiple values in a single variable, instead of declaring separate
variables for each value.
To declare an array, define the variable type with square brackets:
String[] cars;

We have now declared a variable that holds an array of strings. To insert values to it, we
can use an array literal - place the values in a comma-separated list, inside curly braces:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};

To create an array of integers, you could write:


int[] myNum = {10, 20, 30, 40};

Access the Elements of an Array


You access an array element by referring to the index number.
This statement accesses the value of the first element in cars:
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
[Link](cars[0]);
// Outputs Volvo

Note: Array indexes start with 0: [0] is the first element. [1] is the second element, etc.

Change an Array Element


To change the value of a specific element, refer to the index number:
Example
cars[0] = "Opel";

Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
cars[0] = "Opel";
[Link](cars[0]);
// Now outputs Opel instead of Volvo

public class Main {

public static void main(String[] args) {


String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
cars[0] = "Opel";
[Link](cars[0]);
}
}

Output:opel
Array Length
To find out how many elements an array has, use the length property:
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
[Link]([Link]);
// Outputs 4

Loop Through an Array


You can loop through the array elements with the for loop, and use the length property
to specify how many times the loop should run.
The following example outputs all elements in the cars array:
Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (int i = 0; i < [Link]; i++) {
[Link](cars[i]);
}

output:
Volvo
BMW
Ford
Mazda

Loop Through an Array with For-Each


There is also a "for-each" loop, which is used exclusively to loop through elements
in arrays: Syntax
for (type variable : arrayname) {
...
}

The following example outputs all elements in the cars array, using a "for-
each" loop: Example
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (String i : cars) {
[Link](i);
}

output:
Volvo
BMW
Ford
Mazda

The example above can be read like this: for each String element (called i - as in
index) in cars, print out the value of i.
If you compare the for loop and for-each loop, you will see that the for-each method is
easier to write, it does not require a counter (using the length property), and it is more
readable.

Multidimensional Arrays
A multidimensional array is an array containing one or more arrays.
To create a two-dimensional array, add each array within its own set of curly
braces: Example
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };

myNumbers is now an array with two arrays as its elements.


To access the elements of the myNumbers array, specify two indexes: one for the array,
and one for the element inside that array. This example accesses the third element (2) in
the second array (1) of myNumbers:
Example
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
int x = myNumbers[1][2];
[Link](x); // Outputs 7

We can also use a for loop inside another for loop to get the elements of a two-
dimensional array (we still have to point to the two indexes):
Example
public class Main {
public static void main(String[] args) {
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
for (int i = 0; i < [Link]; ++i) {
for(int j = 0; j < myNumbers[i].length; ++j) {
[Link](myNumbers[i][j]);
}
}
}
}

output:

1
2
3
4
5
6
7

Common questions

Powered by AI

Single inheritance in Java allows a subclass to inherit from only one superclass, meaning a class can extend only one other class. This is straightforward, using the 'extends' keyword to inherit the features of a superclass . On the other hand, Java does not support multiple inheritance with classes, meaning a class cannot extend more than one class. However, Java achieves multiple inheritance through interfaces, where a class can implement multiple interfaces, hence gaining the ability to be based on multiple sources . Interfaces in Java allow a class to inherit from multiple interfaces using the 'implements' keyword, thus achieving a form of multiple inheritance .

Polymorphism enhances extensibility in Java by allowing methods to perform differently based on the object that calls them. Method overriding enables a subclass to provide a specific implementation for a method that is already defined in its superclass; this allows new behaviors to be introduced without altering existing code . Additionally, using interfaces, Java allows classes to implement interface methods differently, supporting various functionalities across different classes based on the same interface method signature . This design promotes the open/closed principle, where new features can be added with minimal modifications to existing systems, enhancing the system's extensibility.

Two-dimensional arrays in Java are arrays of arrays, allowing storage of data in a tabular format—rows and columns. They are useful for representing matrices or grids where data is conceptually ordered in two dimensions . A two-dimensional array is declared with two sets of brackets, reflecting its structure, like 'int[][] myNumbers'. Access to elements is achieved using two indices: the first specifies the outer array (row), and the second the inner array (column). For instance, 'myNumbers[1][2]' accesses the third element in the second row . The benefits of two-dimensional arrays include better modeling of complex data structures, improved data management, and enhanced clarity when dealing with multidimensional datasets.

The 'final' keyword in Java, when used with classes and methods, has significant implications related to inheritance. Declaring a class as 'final' means it cannot be subclassed, preventing any class from inheriting from it. This is often used for security reasons or when a class is designed to be immutable, such as Java's String class . When applied to methods, 'final' prevents the method from being overridden in any subclass. This provides control over the class's behavior, ensuring that critical methods remain unchanged, thus preserving their intended functionality and preventing accidental or malicious modification. This use of 'final' thus enforces a class's design and contractual obligations, promoting stability and predictability in Java applications.

Hierarchical inheritance in Java occurs when multiple classes inherit from a single base class, establishing a hierarchy based on a shared superclass. This is implemented using the 'extends' keyword for each subclass . For example, in the provided Java code, classes B, C, and D all extend the base class A, allowing them to inherit its fields and methods while also defining their own unique methods . The advantage of hierarchical inheritance is that it facilitates code reusability and a clear structure where subclasses can share common functionalities from the base class while extending or modifying specific behaviors, promoting DRY (Don't Repeat Yourself) principles and maintainability.

Compile-time polymorphism, also known as static polymorphism, is achieved through method overloading in Java. This occurs when two or more methods in the same class have the same name but different parameters (either in number or type). As a result, the method to be executed is determined at compile-time based on the method signature used in the call. For example, multiple 'Multiply' methods accepting different argument types illustrate compile-time polymorphism . Meanwhile, runtime polymorphism, or dynamic polymorphism, involves method overriding, where a subclass provides specific implementations for methods declared in its superclass. The JVM resolves the method calls at runtime based on the actual object type, not the reference type . Both techniques allow Java to support polymorphic behavior but vary in timing and use cases.

Method overloading in Java is a feature where multiple methods have the same name but differ in parameters—either by number, type, or both . This allows one method name to represent different functionalities, facilitating code readability and usability. Compile-time polymorphism, achieved via method overloading, determines the appropriate method to invoke at compile time based on the parameters' types and numbers, thus optimizing and streamlining the method call processes. For example, the 'MultiplyFun' class demonstrates method overloading with two 'Multiply' methods—one accepting integer parameters and another with double parameters . This approach allows a single method name to handle different data types and operations, reflecting polymorphic behavior that enhances code flexibility and robustness.

Java allows looping through array elements using both standard for-loops and for-each loops. With the standard for-loop, an index is iterated from 0 to the array's length, and each element is accessed using the index, as demonstrated by iterating through the 'cars' array with 'System.out.println(cars[i])' . This approach grants access to the element index, enabling modifications or specific comparisons. Conversely, a for-each loop simplifies iteration over all array elements without explicit indexing. It improves code readability and elegance, reducing potential errors related to index management. The for-each loop is especially useful when the index is not needed for further manipulations . However, it doesn't provide index access, making it less suitable for operations that require modifying elements or accessing indices.

Dynamic method dispatch is a mechanism that implements runtime polymorphism in Java. It allows a method call to be resolved at runtime rather than compile-time, based on the object type the reference is pointing to at runtime . It is implemented through method overriding, where a subclass can provide a custom implementation of a method already defined in its superclass. At runtime, depending on the object's actual class type that the reference points to, the appropriate overridden method is invoked. This allows flexibility and dynamic behavior changes, fostering extensible and easily configurable code.

The StringBuffer class in Java is designed for use in scenarios where frequent modifications to string content are required, as it provides a mutable sequence of characters. Unlike the String class, which represents immutable character sequences, StringBuffer allows for insertion, modification, and deletion of characters without creating new objects, thereby reducing memory overhead and improving performance in string manipulations . StringBuffer manages memory differently by maintaining a dynamically resizable array that can accommodate additional characters beyond its current contents without the necessity of reallocating more memory every time changes are made. The capacity of a StringBuffer can automatically increase as required, reducing the need for frequent reallocations and enhancing efficiency .

You might also like