0% found this document useful (0 votes)
39 views31 pages

Java Abstract Classes and Arrays Guide

This document covers the concepts of abstract classes and methods in Java, explaining their purpose and usage. It also details the array data structure, including how to declare, create, process, and pass arrays to methods, as well as the utility of the Arrays class. Additionally, it introduces the String class, covering string creation, length, concatenation, formatting, and various string methods.

Uploaded by

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

Java Abstract Classes and Arrays Guide

This document covers the concepts of abstract classes and methods in Java, explaining their purpose and usage. It also details the array data structure, including how to declare, create, process, and pass arrays to methods, as well as the utility of the Arrays class. Additionally, it introduces the String class, covering string creation, length, concatenation, formatting, and various string methods.

Uploaded by

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

UNIT-III: Classes and Objects

3.1 Abstract Methods & Class


Abstract Class
An abstract class can never be instantiated. If a class is declared as abstract then the sole
purpose is for the class to be extended.
A class cannot be both abstract and final (since a final class cannot be extended). If a class
contains abstract methods then the class should be declared abstract. Otherwise, a compile
error will be thrown.
An abstract class may contain both abstract methods as well normal methods.
Example
abstract class Caravan {
private double price;
private String model;
private String year;
public abstract void goFast(); // an abstract method
public abstract void changeColor();
}

Abstract Methods
An abstract method is a method declared without any implementation. The methods body
(implementation) is provided by the subclass. Abstract methods can never be final or strict.
Any class that extends an abstract class must implement all the abstract methods of the super
class, unless the subclass is also an abstract class.
If a class contains one or more abstract methods, then the class must be declared abstract. An
abstract class does not need to contain abstract methods.
The abstract method ends with a semicolon. Example: public abstract sample();
Example
public abstract class SuperClass {
abstract void m(); // abstract method
}

Prof. Amit N. Kshirsaga√


class SubClass extends SuperClass {
// implements the abstract method
void m() {
.........
}
}
3.2 Arrays
Java provides a data structure, the array, which stores a fixed-size sequential collection of
elements of the same type. An array is used to store a collection of data, but it is often more
useful to think of an array as a collection of variables of the same type.
Instead of declaring individual variables, such as number0, number1, ..., and number99, you
declare one array variable such as numbers and use numbers[0], numbers[1], and ...,
numbers[99] to represent individual variables.
This tutorial introduces how to declare array variables, create arrays, and process arrays using
indexed variables.
Declaring Array Variables
To use an array in a program, you must declare a variable to reference the array, and you must
specify the type of array the variable can reference. Here is the syntax for declaring an array
variable –
Syntax
dataType[] arrayRefVar; // preferred way.
or
dataType arrayRefVar[]; // works but not preferred way.
Note − The style dataType[] arrayRefVar is preferred. The style dataType arrayRefVar[] comes
from the C/C++ language and was adopted in Java to accommodate C/C++ programmers.
Example
The following code snippets are examples of this syntax −
double[] myList; // preferred way.
or
double myList[]; // works but not preferred way.
3.2.1 Creating Arrays
You can create an array by using the new operator with the following syntax –
Syntax
arrayRefVar = new dataType[arraySize];
The above statement does two things −
 It creates an array using new dataType[arraySize].
 It assigns the reference of the newly created array to the variable arrayRefVar.
Declaring an array variable, creating an array, and assigning the reference of the array to the
variable can be combined in one statement, as shown below −
dataType[] arrayRefVar = new dataType[arraySize];
Alternatively you can create arrays as follows −
dataType[] arrayRefVar = {value0, value1, ..., valuek};
The array elements are accessed through the index. Array indices are 0-based; that is, they start
from 0 to [Link]-1.
Example
Following statement declares an array variable, myList, creates an array of 10 elements of
double type and assigns its reference to myList −
double[] myList = new double[10];
Following picture represents array myList. Here, myList holds ten double values and the indices
are from 0 to 9.
3.2.2 Processing Arrays
When processing array elements, we often use either for loop or foreach loop because all of
the elements in an array are of the same type and the size of the array is known.
Example
Here is a complete example showing how to create, initialize, and process arrays −
public class TestArray {
public static void main(String[] args) {
double[] myList = {1.9, 2.9, 3.4, 3.5};
// Print all the array elements
for (int i = 0; i < [Link]; i++) {
[Link](myList[i] + " ");
}
// Summing all elements
double total = 0;
for (int i = 0; i < [Link]; i++) {
total += myList[i];
}
[Link]("Total is " + total);
// Finding the largest element
double max = myList[0];
for (int i = 1; i < [Link]; i++) {
if (myList[i] > max) max = myList[i];
}
[Link]("Max is " + max);
}
}
This will produce the following result –
1.9
2.9
3.4
3.5
Total is 11.7
Max is 3.5
3.2.3 The foreach Loops
JDK 1.5 introduced a new for loop known as foreach loop or enhanced for loop, which enables
you to traverse the complete array sequentially without using an index variable.
Example
The following code displays all the elements in the array myList −

public class TestArray {


public static void main(String[] args) {
double[] myList = {1.9, 2.9, 3.4, 3.5};
// Print all the array elements
for (double element: myList) {
[Link](element);
}
}
}
This will produce the following result –
Output
1.9
2.9
3.4
3.5

3.2.4 Passing Arrays to Methods


Just as you can pass primitive type values to methods, you can also pass arrays to methods. For
example, the following method displays the elements in an int array −
Example
public static void printArray(int[] array) {
for (int i = 0; i < [Link]; i++) {
[Link](array[i] + " ");
}
}
You can invoke it by passing an array. For example, the following statement invokes the
printArray method to display 3, 1, 2, 6, 4, and 2 –
Example
printArray(new int[]{3, 1, 2, 6, 4, 2});

3.2.5 Returning an Array from a Method


A method may also return an array. For example, the following method returns an array that is
the reversal of another array –
Example
public static int[] reverse(int[] list) {
int[] result = new int[[Link]];
for(int i = 0, j = [Link] - 1; i < [Link]; i++, j--) {
result[j] = list[i];
}
return result;
}

3.2.6 The Arrays Class


The [Link] class contains various static methods for sorting and searching arrays,
comparing arrays, and filling array elements. These methods are overloaded for all primitive
types.

[Link]. Method & Description

1 public static int binarySearch(Object[] a, Object key)


Searches the specified array of Object ( Byte, Int , double, etc.) for the specified
value using the binary search algorithm. The array must be sorted prior to making
this call. This returns index of the search key, if it is contained in the list; otherwise,
it returns ( – (insertion point + 1)).

2 public static boolean equals(long[] a, long[] a2)


Returns true if the two specified arrays of longs are equal to one another. Two
arrays are considered equal if both arrays contain the same number of elements,
and all corresponding pairs of elements in the two arrays are equal. This returns
true if the two arrays are equal. Same method could be used by all other primitive
data types (Byte, short, Int, etc.)

3 public static void fill(int[] a, int val)


Assigns the specified int value to each element of the specified array of ints. The
same method could be used by all other primitive data types (Byte, short, Int, etc.)

4 public static void sort(Object[] a)


Sorts the specified array of objects into an ascending order, according to the
natural ordering of its elements. The same method could be used by all other
primitive data types ( Byte, short, Int, etc.)

3.3 Strings Class


Strings, which are widely used in Java programming, are a sequence of characters. In Java
programming language, strings are treated as objects.
The Java platform provides the String class to create and manipulate strings.
3.3.1 Creating Strings
The most direct way to create a string is to write −
String greeting = "Hello world!";
Whenever it encounters a string literal in your code, the compiler creates a String object with
its value in this case, "Hello world!'.
As with any other object, you can create String objects by using the new keyword and a
constructor. The String class has 11 constructors that allow you to provide the initial value of
the string using different sources, such as an array of characters.
Example
public class StringDemo {
public static void main(String args[]) {
char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' };
String helloString = new String(helloArray);
[Link]( helloString );
}
}
This will produce the following result –
Output
Hello.
Note − The String class is immutable, so that once it is created a String object cannot be
changed. If there is a necessity to make a lot of modifications to Strings of characters, then you
should use String Buffer & String Builder Classes.
3.3.2 String Length
Methods used to obtain information about an object are known as accessor methods. One
accessor method that you can use with strings is the length() method, which returns the number
of characters contained in the string object.
The following program is an example of length(), method String class.
Example
public class StringDemo {
public static void main(String args[]) {
String palindrome = "Dot saw I was Tod";
int len = [Link]();
[Link]( "String Length is : " + len );
}
}
This will produce the following result –
String Length is : 17

3.3.3 Concatenating Strings


The String class includes a method for concatenating two strings −
[Link](string2);
This returns a new string that is string1 with string2 added to it at the end. You can also use the
concat() method with string literals, as in −
"My name is ".concat("Zara");
Strings are more commonly concatenated with the + operator, as in −
"Hello," + " world" + "!"
This will produce results in −
"Hello, world!"
Let us look at the following example –
Example
public class StringDemo {

public static void main(String args[]) {


String string1 = "saw I was ";
[Link]("Dot " + string1 + "Tod");
}
}
This will produce the following result –
Output
Dot saw I was Tod

3.3.4 Creating Format Strings


You have printf() and format() methods to print output with formatted numbers. The String
class has an equivalent class method, format(), that returns a String object rather than a
PrintStream object.
Using String's static format() method allows you to create a formatted string that you can reuse,
as opposed to a one-time print statement. For example, instead of –
Example
[Link]("The value of the float variable is " +
"%f, while the value of the integer " +
"variable is %d, and the string " +
"is %s", floatVar, intVar, stringVar);
You can write −
String fs;
fs = [Link]("The value of the float variable is " +
"%f, while the value of the integer " +
"variable is %d, and the string " +
"is %s", floatVar, intVar, stringVar);
[Link](fs);
3.3.5 String Methods
Here is the list of methods supported by String class −

[Link]. Method & Description


char charAt(int index)
1
Returns the character at the specified index.
int compareTo(Object o)
2
Compares this String to another Object.
int compareTo(String anotherString)
3
Compares two strings lexicographically.
int compareToIgnoreCase(String str)
4
Compares two strings lexicographically, ignoring case differences.
String concat(String str)
5
Concatenates the specified string to the end of this string.
boolean contentEquals(StringBuffer sb)
6 Returns true if and only if this String represents the same sequence of characters as the
specified StringBuffer.
static String copyValueOf(char[] data)
7
Returns a String that represents the character sequence in the array specified.
static String copyValueOf(char[] data, int offset, int count)
8
Returns a String that represents the character sequence in the array specified.
boolean endsWith(String suffix)
9
Tests if this string ends with the specified suffix.
boolean equals(Object anObject)
10
Compares this string to the specified object.
boolean equalsIgnoreCase(String anotherString)
11
Compares this String to another String, ignoring case considerations.
byte getBytes()
12 Encodes this String into a sequence of bytes using the platform's default charset,
storing the result into a new byte array.
byte[] getBytes(String charsetName)
13 Encodes this String into a sequence of bytes using the named charset, storing the result
into a new byte array.
14 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
Copies characters from this string into the destination character array.
int hashCode()
15
Returns a hash code for this string.
int indexOf(int ch)
16
Returns the index within this string of the first occurrence of the specified character.
int indexOf(int ch, int fromIndex)
17 Returns the index within this string of the first occurrence of the specified character,
starting the search at the specified index.
int indexOf(String str)
18
Returns the index within this string of the first occurrence of the specified substring.
int indexOf(String str, int fromIndex)
19 Returns the index within this string of the first occurrence of the specified substring,
starting at the specified index.
String intern()
20
Returns a canonical representation for the string object.
int lastIndexOf(int ch)
21
Returns the index within this string of the last occurrence of the specified character.
int lastIndexOf(int ch, int fromIndex)
22 Returns the index within this string of the last occurrence of the specified character,
searching backward starting at the specified index.
int lastIndexOf(String str)
23 Returns the index within this string of the rightmost occurrence of the specified
substring.
int lastIndexOf(String str, int fromIndex)
24 Returns the index within this string of the last occurrence of the specified substring,
searching backward starting at the specified index.
int length()
25
Returns the length of this string.
boolean matches(String regex)
26
Tells whether or not this string matches the given regular expression.
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int
27 len)
Tests if two string regions are equal.
28 boolean regionMatches(int toffset, String other, int ooffset, int len)
Tests if two string regions are equal.
String replace(char oldChar, char newChar)
29 Returns a new string resulting from replacing all occurrences of oldChar in this string
with newChar.
String replaceAll(String regex, String replacement
30 Replaces each substring of this string that matches the given regular expression with
the given replacement.
String replaceFirst(String regex, String replacement)
31 Replaces the first substring of this string that matches the given regular expression with
the given replacement.
String[] split(String regex)
32
Splits this string around matches of the given regular expression.
String[] split(String regex, int limit)
33
Splits this string around matches of the given regular expression.
boolean startsWith(String prefix)
34
Tests if this string starts with the specified prefix.
boolean startsWith(String prefix, int toffset)
35
Tests if this string starts with the specified prefix beginning a specified index.
CharSequence subSequence(int beginIndex, int endIndex)
36
Returns a new character sequence that is a subsequence of this sequence.
String substring(int beginIndex)
37
Returns a new string that is a substring of this string.
String substring(int beginIndex, int endIndex)
38
Returns a new string that is a substring of this string.
char[] toCharArray()
39
Converts this string to a new character array.
String toLowerCase()
40 Converts all of the characters in this String to lower case using the rules of the default
locale.
String toLowerCase(Locale locale)
41 Converts all of the characters in this String to lower case using the rules of the given
Locale.
String toString()
42
This object (which is already a string!) is itself returned.
String toUpperCase()
43 Converts all of the characters in this String to upper case using the rules of the default
locale.
String toUpperCase(Locale locale)
44 Converts all of the characters in this String to upper case using the rules of the given
Locale.
String trim()
45
Returns a copy of the string, with leading and trailing whitespace omitted.
static String valueOf(primitive data type x)
46
Returns the string representation of the passed data type argument.

3.5 Java Command Line Arguments


The java command-line argument is an argument i.e. passed at the time of running the java
program.
The arguments passed from the console can be received in the java program and it can be used
as an input.
So, it provides a convenient way to check the behavior of the program for the different values.
You can pass N (1,2,3 and so on) numbers of arguments from the command prompt.

3.5.1 Simple example of command-line argument in java

In this example, we are receiving only one argument and printing it. To run this java program,
you must pass at least one argument from the command prompt.
class CommandLineExample{
public static void main(String args[]){
[Link]("Your first argument is: "+args[0]);
}
}
 compile command: > javac [Link]
 run command: > java CommandLineExample sonu
 Output: Your first argument is: sonu
3.5.2 Example of command-line argument that prints all the values

In this example, we are printing all the arguments passed from the command-line. For this
purpose, we have traversed the array using for loop.
class A{
public static void main(String args[])
{
for(int i=0;i<[Link];i++)
[Link](args[i]);
}
}
 compile by: > javac [Link]
 run by: > java A SKN 1 3 abc
Output: SKN
1
3
abc

3.6. What is Inheritance?


Inheritance is one of the cornerstones of object-oriented programming because it allows the
creation of hierarchical classifications. Using inheritance, you can create a general class that
defines traits common to a set of related items. This class can then be inherited by other, more
specific classes, each adding those things that are unique to it. In the terminology of Java, a
class that is inherited is called a superclass. The class that does the inheriting is called a subclass.
Therefore, a subclass is a specialized version of a superclass. It inherits all of the instance
variables and methods defined by the superclass and add its own, unique elements.
3.6.1 Inheritance Basics
To inherit a class, you simply incorporate the definition of one class into another by using the
extends keyword. To see how, let’s begin with a short example. The following program creates
a superclass called A and a subclass called B. Notice how the keyword extends is used to create
a subclass of A.
// A simple example of inheritance.
// Create a superclass.
class A {
int i, j;
void showij() {
[Link]("i and j: " + i + " " + j);
}
}
// Create a subclass by extending class A.
class B extends A {
int k;
void showk() {
[Link]("k: " + k);
}
void sum() {
[Link]("i+j+k: " + (i+j+k));
}
}
class SimpleInheritance {
public static void main(String args[]) {
A superOb = new A();
B subOb = new B();
// The superclass may be used by itself.
superOb.i = 10;
superOb.j = 20;
[Link]("Contents of superOb: ");
[Link]();
[Link]();
/* The subclass has access to all public members of
its superclass. */
subOb.i = 7;
subOb.j = 8;
subOb.k = 9;
[Link]("Contents of subOb: ");
[Link]();
[Link]();
[Link]();
[Link]("Sum of i, j and k in subOb:");
[Link]();
}
}
The output from this program is shown here:
Contents of superOb:
i and j: 10 20
Contents of subOb:
i and j: 7 8
k: 9
Sum of i, j and k in subOb:
i+j+k: 24

As you can see, the subclass B includes all of the members of its superclass, A. This is why subOb
can access i and j and call showij( ). Also, inside sum( ), i and j can be referred to directly, as if
they were part of B. Even though A is a superclass for B, it is also a completely independent,
stand-alone class. Being a superclass for a subclass does not mean that the superclass cannot
be used by itself. Further, a subclass can be a superclass for another subclass.
The general form of a class declaration that inherits a superclass is shown here:

class subclass-name extends superclass-name {


// body of class
}
super has two general forms. The first calls the superclass’ constructor. The second is used to
access a member of the superclass that has been hidden by a member of a subclass. Each use
is examined here.
Using super to Call Superclass Constructors
A subclass can call a constructor defined by its superclass by use of the following form of super:
super(arg-list);
Here, arg-list specifies any arguments needed by the constructor in the superclass. super( )
must always be the first statement executed inside a subclass’ constructor.
To see how super( ) is used, consider this improved version of the BoxWeight( ) class:

// BoxWeight now uses super to initialize its Box attributes.


class BoxWeight extends Box {
double weight; // weight of box
// initialize width, height, and depth using super()
BoxWeight(double w, double h, double d, double m) {
super(w, h, d); // call superclass constructor
weight = m;
}
}
Here, BoxWeight( ) calls super( ) with the arguments w, h, and d. This causes the Box( )
constructor to be called, which initializes width, height, and depth using these values.
BoxWeight no longer initializes these values itself. It only needs to initialize the value unique to
it: weight. This leaves Box free to make these values private if desired.
In the preceding example, super( ) was called with three arguments. Since constructors
can be overloaded, super( ) can be called using any form defined by the superclass. The
constructor executed will be the one that matches the arguments. For example, here is a
complete implementation of BoxWeight that provides constructors for the various ways
that a box can be constructed. In each case, super( ) is called using the appropriate arguments.
Notice that width, height, and depth have been made private within Box.
// A complete implementation of BoxWeight.
class Box {
private double width;
private double height;
private double depth;
// construct clone of an object
Box(Box ob) { // pass object to constructor
width = [Link];
height = [Link];
depth = [Link];
}
// constructor used when all dimensions specified
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// constructor used when no dimensions specified
Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}
// constructor used when cube is created
Box(double len) {
width = height = depth = len;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
// BoxWeight now fully implements all constructors.
class BoxWeight extends Box {
double weight; // weight of box
// construct clone of an object
BoxWeight(BoxWeight ob) { // pass object to constructor
super(ob);
weight = [Link];
}
// constructor when all parameters are specified
BoxWeight(double w, double h, double d, double m) {
super(w, h, d); // call superclass constructor
weight = m;
}
// default constructor
BoxWeight() {
super();
weight = -1;
}
// constructor used when cube is created
BoxWeight(double len, double m) {
super(len);
weight = m;
}
}
class DemoSuper {
public static void main(String args[]) {
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
BoxWeight mybox3 = new BoxWeight(); // default
BoxWeight mycube = new BoxWeight(3, 2);
BoxWeight myclone = new BoxWeight(mybox1);
double vol;
vol = [Link]();
[Link]("Volume of mybox1 is " + vol);
[Link]("Weight of mybox1 is " + [Link]);
[Link]();
vol = [Link]();
[Link]("Volume of mybox2 is " + vol);
[Link]("Weight of mybox2 is " + [Link]);
[Link]();
vol = [Link]();
[Link]("Volume of mybox3 is " + vol);
[Link]("Weight of mybox3 is " + [Link]);
[Link]();
vol = [Link]();
[Link]("Volume of myclone is " + vol);
[Link]("Weight of myclone is " + [Link]);
[Link]();
vol = [Link]();
[Link]("Volume of mycube is " + vol);
[Link]("Weight of mycube is " + [Link]);
[Link]();
}
}

This program generates the following output:


Volume of mybox1 is 3000.0
Weight of mybox1 is 34.3
Volume of mybox2 is 24.0
Weight of mybox2 is 0.076
Volume of mybox3 is -1.0
Weight of mybox3 is -1.0
Volume of myclone is 3000.0
Weight of myclone is 34.3
Volume of mycube is 27.0
Weight of mycube is 2.0

Creating a Multilevel Hierarchy


Up to this point, we have been using simple class hierarchies that consist of only a superclass
and a subclass. However, you can build hierarchies that contain as many layers of inheritance
as you like. As mentioned, it is perfectly acceptable to use a subclass as a superclass of another.
For example, given three classes called A, B, and C, C can be a subclass of B, which is a subclass
of A. When this type of situation occurs, each subclass inherits all of the traits found in all of its
superclasses. In this case, C inherits all aspects of B and A. To see how a multilevel hierarchy
can be useful, consider the following program. In it, the subclass BoxWeight is used as a
superclass to create the subclass called Shipment. Shipment inherits all of the traits of
BoxWeight and Box, and adds a field called cost, which holds the cost of shipping such a parcel.
// Extend BoxWeight to include shipping [Link] with Box.
class Box {
private double width;
private double height;
private double depth;
// construct clone of an object
Box(Box ob) { // pass object to constructor
width = [Link];
height = [Link];
depth = [Link];
}
// constructor used when all dimensions specified
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// constructor used when no dimensions specified
Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}
// constructor used when cube is created
Box(double len) {
width = height = depth = len;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
// Add weight.
class BoxWeight extends Box {
double weight; // weight of box
// construct clone of an object
BoxWeight(BoxWeight ob) { // pass object to constructor
super(ob);
weight = [Link];
}
// constructor when all parameters are specified
BoxWeight(double w, double h, double d, double m) {
super(w, h, d); // call superclass constructor
weight = m;
}
// default constructor
BoxWeight() {
super();
weight = -1;
}
// constructor used when cube is created
BoxWeight(double len, double m) {
super(len);
weight = m;
}
}
// Add shipping costs.
class Shipment extends BoxWeight {
double cost;
// construct clone of an object
Shipment(Shipment ob) { // pass object to constructor
super(ob);
cost = [Link];
}
// constructor when all parameters are specified
Shipment(double w, double h, double d,
double m, double c) {
super(w, h, d, m); // call superclass constructor cost = c;
}
// default constructor
Shipment() {
super();
cost = -1;
}
// constructor used when cube is created
Shipment(double len, double m, double c) {
super(len, m);
cost = c;
}
}
class DemoShipment {
public static void main(String args[]) {
Shipment shipment1 =
new Shipment(10, 20, 15, 10, 3.41);
Shipment shipment2 =
new Shipment(2, 3, 4, 0.76, 1.28);
double vol;
vol = [Link]();
[Link]("Volume of shipment1 is " + vol);
[Link]("Weight of shipment1 is "+ [Link]);
[Link]("Shipping cost: $" + [Link]);
[Link]();
vol = [Link]();
[Link]("Volume of shipment2 is " + vol);
[Link]("Weight of shipment2 is "+ [Link]);
[Link]("Shipping cost: $" + [Link]);
}
}
The output of this program is shown here:
Volume of shipment1 is 3000.0
Weight of shipment1 is 10.0
Shipping cost: $3.41
Volume of shipment2 is 24.0
Weight of shipment2 is 0.76
Shipping cost: $1.28

Because of inheritance, Shipment can make use of the previously defined classes of Box and
BoxWeight, adding only the extra information it needs for its own, specific application. This is
part of the value of inheritance; it allows the reuse of code. This example illustrates one other
important point: super( ) always refers to the constructor
in the closest superclass. The super( ) in Shipment calls the constructor in BoxWeight. The
super( ) in BoxWeight calls the constructor in Box. In a class hierarchy, if a superclass
constructor requires parameters, then all subclasses must pass those parameters “up the
line.” This is true whether or not a subclass needs parameters of its own.

When Constructors Are Called


When a class hierarchy is created, in what order are the constructors for the classes that make
up the hierarchy called? For example, given a subclass called B and a superclass called A, is A’s
constructor called before B’s, or vice versa? The answer is that in a class hierarchy, constructors
are called in order of derivation, from superclass to subclass. Further, since super( ) must be
the first statement executed in a subclass’ constructor, this order is the same whether or not
super( ) is used. If super( ) is not used, then the default or parameterless constructor of each
superclass will be executed. The following program illustrates when constructors are executed:
// Demonstrate when constructors are called.
// Create a super class.
class A {
A() {
[Link]("Inside A's constructor.");
}
}
// Create a subclass by extending class A.
class B extends A {
B() {
[Link]("Inside B's constructor.");
}
}
// Create another subclass by extending B.
class C extends B {
C() {
[Link]("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
The output from this program is shown here:
Inside A’s constructor
Inside B’s constructor
Inside C’s constructor

As you can see, the constructors are called in order of derivation.


If you think about it, it makes sense that constructors are executed in order of derivation.
Because a superclass has no knowledge of any subclass, any initialization it needs to perform is
separate from and possibly prerequisite to any initialization performed by the subclass.
Therefore, it must be executed first.
Method Overriding
In a class hierarchy, when a method in a subclass has the same name and type signature as
a method in its superclass, then the method in the subclass is said to override the method in
the superclass. When an overridden method is called from within a subclass, it will always
refer to the version of that method defined by the subclass. The version of the method defined
by the superclass will be hidden. Consider the following:
// Method overriding.
class A {
int i, j;
A(int a, int b) {
i = a;
j = b;
}
// display i and j
void show() {
[Link]("i and j: " + i + " " + j);
}
}
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
// display k – this overrides show() in A
void show() {
[Link]("k: " + k);
}
}
class Override {
public static void main(String args[]) {
B subOb = new B(1, 2, 3);
[Link](); // this calls show() in B
}
}
The output produced by this program is shown here:
k: 3

When show( ) is invoked on an object of type B, the version of show( ) defined within B
is used. That is, the version of show( ) inside B overrides the version declared in A. If you wish
to access the superclass version of an overridden method, you can do so by using super. For
example, in this version of B, the superclass version of show( ) is invoked within the subclass’
version. This allows all instance variables to be displayed.
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
void show() {
[Link](); // this calls A's show()
[Link]("k: " + k);
}
}
If you substitute this version of A into the previous program, you will see the following
output:
i and j: 1 2
k: 3
Here, [Link]( ) calls the superclass version of show( ).
Method overriding occurs only when the names and the type signatures of the two methods
are identical. If they are not, then the two methods are simply overloaded.
For example, consider this modified version of the preceding example:
// Methods with differing type signatures are overloaded – not
// overridden.
class A {
int i, j;
A(int a, int b) {
i = a;
j = b;
}
// display i and j
void show() {
[Link]("i and j: " + i + " " + j);
}
}
// Create a subclass by extending class A.
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
// overload show()
void show(String msg) {
[Link](msg + k);
}
}
class Override {
public static void main(String args[]) {
B subOb = new B(1, 2, 3);
[Link]("This is k: "); // this calls show() in B
[Link](); // this calls show() in A
}
}
The output produced by this program is shown here:
This is k: 3
i and j: 1 2
The version of show( ) in B takes a string parameter. This makes its type signature
different from the one in A, which takes no parameters. Therefore, no overriding (or name
hiding) takes place. Instead, the version of show( ) in B simply overloads the version of
show( ) in A.

Dynamic Method Dispatch


While the examples in the preceding section demonstrate the mechanics of method overriding,
they do not show its power. Indeed, if there were nothing more to method overriding than a
name space convention, then it would be, at best, an interesting curiosity, but of little real
value. However, this is not the case. Method overriding forms the basis for one of Java’s most
powerful concepts: dynamic method dispatch. Dynamic method dispatch is the mechanism by
which a call to an overridden method is resolved at run time, rather than compile time. Dynamic
method dispatch is important because this is how Java implements run-time polymorphism.
Let’s begin by restating an important principle: a superclass reference variable can refer to a
subclass object. Java uses this fact to resolve calls to overridden methods at run time. Here is
how. When an overridden method is called through a superclass reference, Java determines
which version of that method to execute based upon the type of the object being referred to
at the time the call occurs. Thus, this determination is made at run time. When different types
of objects are referred to, different versions of an overridden method will be called.
In other words, it is the type of the object being referred to (not the type of the reference
variable) that determines which version of an overridden method will be executed. Therefore,
if a superclass contains a method that is overridden by a subclass, then when different types of
objects are referred to through a superclass reference variable, different versions of the
method are executed.
Here is an example that illustrates dynamic method dispatch:
// Dynamic Method Dispatch
class A {
void callme() {
[Link]("Inside A's callme method");
}
}
class B extends A {
// override callme()
void callme() {
[Link]("Inside B's callme method");
}
}
class C extends A {
// override callme()
void callme() {
[Link]("Inside C's callme method");
}
}
class Dispatch {
public static void main(String args[]) {
A a = new A(); // object of type A
B b = new B(); // object of type B
C c = new C(); // object of type C
A r; // obtain a reference of type A
r = a; // r refers to an A object
[Link](); // calls A's version of callme
r = b; // r refers to a B object
[Link](); // calls B's version of callme
r = c; // r refers to a C object
[Link](); // calls C's version of callme
}
}
The output from the program is shown here:
Inside A’s callme method
Inside B’s callme method
Inside C’s callme method

This program creates one superclass called A and two subclasses of it, called B and C.
Subclasses B and C override callme( ) declared in A. Inside the main( ) method, objects of
type A, B, and C are declared. Also, a reference of type A, called r, is declared. The program
then in turn assigns a reference to each type of object to r and uses that reference to invoke
callme( ). As the output shows, the version of callme( ) executed is determined by the type
of object being referred to at the time of the call. Had it been determined by the type of the
reference variable, r, you would see three calls to A’s callme( ) method.

You might also like