Lab Sheet 4
Lab Sheet 4
CS F213
LAB 4
AGENDA TIME: 02 Hrs
● Dynamic Binding
● Arrays
● Strings
OOPChef has already learned about method overriding and overloading. He is already building complex
classes with many overridden methods. He has built the following class structure and is now very
confused.
//various functions of b1
System.out.println("b1");
b1.leaveUnattended();
b1.cook();
//b1.knead();
b1.eat();
//various functions of b2
System.out.println("b2");
b2.leaveUnattended();
b2.cook();
b2.eat();
//b2.decorate();
//various functions of b3
System.out.println("b3");
b3.leaveUnattended();
b3.cook();
b3.eat();
//b3.decorate();
//b3.eatFrosting();
//various functions of c1
System.out.println("c1");
c1.leaveUnattended();
c1.cook();
c1.eat();
c1.decorate();
//various functions of c2
System.out.println("c2");
c2.leaveUnattended();
c2.cook();
c2.eat();
c2.decorate();
//c2.eatFrosting();
//various functions of p1
System.out.println("p1");
p1.leaveUnattended();
p1.cook();
p1.eat();
p1.decorate();
p1.eatFrosting();
}
}
OOPChef ran the code and was utterly confused by the various outputs. Before trying to understand what
is going on, you must have a little understanding of two very important, but often overlooked concepts:
Reference Type, and Object Type. Let's look at some examples to understand the difference:
Now, you must be wondering, why is it even possible to have different object and reference types in the
first place. This is because of the inheritance support provided by Java. An object is not only an instance
of a class, but also an instance of it’s ancestor classes.
Cake c1 = new Pastry();
On executing the above statement, the memory looks something like this:
Image 4.1.a
A reference (pointer) is created in the stack, with the type ReferenceType. At the same time, a new object
of type ObjectType is created in the heap, which actually contains all the information about the object.
Now, since the object stored in the heap could be interpreted as an instance of its class, or of any of its
ancestor classes, the reference type actually helps the compiler in determining how to interpret the object.
Hence, the reference type is used to determine what all methods and members can be accessed. However,
during runtime, the object in the heap refers to the information about the class it is an object of, and hence
that determines which method would be executed.
Now with this clear, let us try to make sense of the output of the above program step by step.
● The outputs from c1, b1, and p1 should be pretty straightforward, because the reference type is
the same as the object type.
● The outputs for the leaveUnattended, and the cook method are the same everywhere because they
have not been overridden by the child classes.
● Which eat method would be called actually depends on the object type, and not on the reference
type, because of dynamic method dispatch. Hence, b2 and c1 call the eat method of the cake
class, while b3 and c2 call the eat method of the pastry class.
4.1.5 Exercises
1. Build 5 classes A, B, C, D and E, each with one public method speak() which prints the name of
the class along with a small message. B and C extend A, D extends B, and E extends C
2. Do the following, or determine that it is impossible to do:
- Run the implementation of speak() in class D with a reference of type A
- Run the implementation of speak() in class A with a reference of type D
- Run the implementation of of speak() in class C with a reference of type A
- Run the implementation of` of speak() in class C with a reference of type E
4.2 Arrays
Like, we want to gather the details of Students who got enrolled in the OOP course. How do we do
that?
To have ease in management and accessing the data, we usually group similar entities.
An array is one of the available data structures which will group similar items. In the Java programming
language, arrays are considered as objects, which is not the case with C and C++ paradigms.
//Declaration
type variable_name[]
type []variable_name
● “type” specifies either primitive data types like ( int, float, char, byte ) or non-primitive types like
( String, Student, Employee ).
● ‘’[ ]”, this informs the compiler that an array reference is going to be created. It also gives the
details about the “no of dimensions” we are interested in.
● “variable_name”, becomes a reference to the array where we are going to store the data of type
“type”.
When an array is declared, only a reference variable is created, but to assign actual memory to the array,
we need to use the “new” keyword to instantiate the array.
Here an array of size ‘5’ is created inside the memory and is being referenced by the ‘intArr’variable. We
can always combine both line1 and line2 in one step.
Note:
The elements in the array allocated by new will automatically be initialized to 0 (for numeric types), or
null (for reference types).
Program 4.2.a
Program 4.2.c
class Student
{
public int id;
public String name;
Student(int id, String name)
{
this.id = id;
this.name = name;
}
}
public class Main
{
public static void main (String[] args)
{
Student[] arr;
arr = new Student[4];
System.out.println("Before Initialization");
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
arr[0] = new Student(234,"surya");
arr[1] = new Student(345,"ravi");
arr[2] = new Student(456,"aman");
arr[3] = new Student(567,"amit");
System.out.println("Students Details!");
In a 1D array, all the elements are stored in contiguous locations. But, when coming to 2D arrays, the
elements are the array objects. We can see a 2D array as “an array of arrays”.
Program 4.2.d
intArray[0] = a;
intArray[1] = b;
for(int i =0;i<intArray[0].length;i++){
System.out.print(intArray[0][i]+" ");
}
System.out.print("\n");
for(int i =0;i<intArray[1].length;i++){
System.out.print(intArray[1][i]+" ");
}
}
}
In order to gather the “ array objects ‘a’ and ‘b’ ” together (which might be different locations in the
memory), we shall be having contiguous int[ ] array references
intArray[0], intArray[1]
ready in “intArray” 2D-array to refer to those array objects.
Program 4.2.e
4.2.4 Exercises
Exercise 4.2.f
Given a one-dimensional array ‘arr’, you should be cloning any sub-array of ‘arr’ or whole array, upon
the user requirement without using any inbuilt functions. You have to create a method with the name
“cloneArray” inside the “Exercise1” class itself.
Consider having the same method name “cloneArray’ for implementing the above functionalities.
Quick questions:
1) How do you implement the above three methods with the same name?
2) What is the nature of the method, is it a normal method or static type? State your reasons.
/*
Example:
arr is {1,2,3,4,5,6,7,8,9},
cloning a sub-array with length '4' gives out a new array with elements {1,2,3,4}, if you print it.
cloning a sub-array with start index '3' and length '5' gives out {4,5,6,7,8} new array.
*/
Exercise 4.2.g
Given a 2D array ‘arr’, return a new array ‘newArray’, where the index '𝑖' element in the new array
indicates the sum of the elements in column '𝑖' of the given 2D array ‘arr’.
Implement a method inside the provided ‘Exercise2’ class with any name of your likes.
/*
Example:
Input array 'arr' contents :[ [1 2 3],
[4 5 6],
[7 8 9] ]
'newArray' contents : [ 12 15 18 ]
*/
4.3 Strings
In Java, a string is a sequence of characters. For example, "hello" is a string containing a sequence of
characters 'h', 'e', 'l', 'l', and 'o'.
// create a string
String type = "Java programming";
Program 4.3.a : Create a String in Java
class Main {
public static void main(String[] args) {
// create strings
String first = "Java";
String second = "Python";
String third = "JavaScript";
// print strings
System.out.println(first); // print Java
System.out.println(second); // print Python
System.out.println(third); // print JavaScript
}
}
In the above example, we have created three strings named first, second, and third. Here, we are directly
creating strings like primitive types. However, there is another way of creating Java strings (using the new
keyword).
Program 4.3.b
class Main {
public static void main(String[] args) {
Now that we know how strings are created using string literals and the new keyword, let's see what is the
major difference between them.
In Java, the JVM maintains a string pool to store all of its strings inside the memory. The string pool
helps in reusing the strings.
● If the string already exists, the new string is not created. Instead, the new reference example
points to the already existing string (Java).
● If the string doesn't exist, the new string (Java) is created.
Here, the value of the string is not directly provided. Hence, a new "Java" string is created even though
"Java" is already present inside the memory pool.
The string can also be declared using a new operator i.e. dynamically allocated. In case String is
dynamically allocated they are assigned a new memory location in heap. This string will not be added to
the String constant pool.
● CharBuffer: This class implements the CharSequence interface. This class is used to allow
character buffers to be used in place of CharSequences. An example of such usage is the
regular-expression package java.util.regex.
● String: String is a sequence of characters. In java, objects of String are immutable which means
constant and cannot be changed once created.
Program 4.3.c
public class Main {
public static void main(String[] args) {
//Substring method
String s1 = new String("Hello World");//returns the substring from the ith index
String s2=s1.substring(4);//
System.out.println(s2);
}
}
4.3.3 StringBuffer:
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.
Program 4.3.d
class StringBufferExample{
public static void main(String args[]){
StringBuffer sb=new StringBuffer();
System.out.println(sb.capacity());//default 16
sb.append("Hello");
System.out.println(sb.capacity());//now 16
sb.append("java is my favourite language");
System.out.println(sb.capacity());//now (16*2)+2=34 i.e (oldcapacity*2)+2
}
}
String and StringBuffer classes are declared final, so there cannot be subclasses of these classes.
4.3.4 StringBuilder:
The StringBuilder in Java represents a mutable sequence of characters. Since the String Class in Java
creates an immutable sequence of characters, the StringBuilder class provides an alternative to String
Class, as it creates a mutable sequence of characters.
Program 4.3.e:
class Example{
public static void main(String args[]){
StringBuilder sb=new StringBuilder("Hello ");
sb.append("Java");//now original string is changed
System.out.println(sb);//prints Hello Java
}
}
Exercise 4.3.f: