CS F213 Objected Oriented Programming Labsheet 4
Spring 2024
Using Objects as Parameters and Returning Objects
So far, we have only been using simple types as parameters to methods. However, it is both correct and common to pass objects to methods. This can be used to make copies of an object or if an object has too many attributes, instead of passing each of them individually we can pass the object and access them directly in the method.
Example:
import java.util.Scanner;
public class Student {
private String name;
private int age;
public Student(){}
public Student(String name, int age){
this.name = name;
this.age = age;
}
public Student copyObject(Student std){
//method of Student data type taking an object of Student data type as parameter
this.name = std.name;
this.age = std.age;
return std;
}
public void displayData(){
System.out.println("Name : "+this.name);
System.out.println("Age : "+this.age);
}
}
class Main
{
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
System.out.println("Enter your name ");
String name = sc.next();
System.out.println("Enter your age ");
int age = sc.nextInt();
Student std = new Student(name, age);
System.out.println("Contents of the original object");
std.displayData();
System.out.println("Contents of the copied object");
Student copyOfStd = new Student().copyObject(std);
copyOfStd.displayData();
}
}
Output:
Enter your name
John
Enter your age
20
Contents of the original object
Name : John
Age : 20
Contents of the copied object
Name : John
Age : 20
Argument Passing
In general, there are two ways that a computer language can pass an argument to a subroutine. The first way is call-by-value
. This approach copies the value of an argument into the formal parameter of the subroutine. Therefore, changes made to the parameter of the subroutine have no effect on the argument
. The second way an argument can be passed is call-by-reference
. In this approach, a reference to an argument (not the value of the argument) is passed to the parameter. Inside the subroutine, this reference is used to access the actual argument specified in the call. This means that changes made to the parameter will affect the argument used to call the subroutine
. Please note that Java uses call by value. When passing a reference type (e.g. objects), the reference is copied in the called method. Both the copies of the references refer to the same object, hence the changes are reflected from one to the other. Let's look at an example
Example:
class Data {
int value;
Data(int value) {
this.value = value;
}
}
class CallByExample {
static void callByValue(int x, int y) {
x *= 2;
y /= 2;
}
static void callByReference(Data data) {
data.value *= 2;
}
}
class Main
{
public static void main(String[] args) {
int a = 15, b = 20;
CallByExample ob= new CallByExample();
System.out.println("a and b before callByValue: " + a + " " + b);
ob.callByValue(a, b);
System.out.println("a and b after callByValue: " + a + " " + b);
// Call by reference example (for objects)
Data obj = new Data(15);
System.out.println("obj.value before callByReference: " + obj.value);
ob.callByReference(obj);
System.out.println("obj.value after callByReference: " + obj.value);
}
}
Output:
a and b before callByValue: 15 20
a and b after callByValue: 15 20
obj.value before callByReference: 15
obj.value after callByReference: 30
Recursion
Recursion is the process of defining something in terms of itself. As it relates to Java programming, recursion is the attribute that allows a method to call itself
. A method that calls itself is said to be recursive. The classic example of recursion is the computation of the factorial of a number. The factorial of a number N is the product of all the whole numbers between 1 and N
Example:
class Factorial {
// this is a recursive method
int fact(int n) {
int result;
if(n==1) return 1;
result = fact(n-1) * n;
return result;
}
}
class Recursion {
public static void main(String[] args) {
Factorial f = new Factorial();
System.out.println("Factorial of 3 is " + f.fact(3));
System.out.println("Factorial of 4 is " + f.fact(4));
System.out.println("Factorial of 5 is " + f.fact(5));
}
}
Output:
Factorial of 3 is 6
Factorial of 4 is 24
Factorial of 5 is 120
Working of the above Program
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
return 1
return 2*1 = 2
return 3*2 = 6
return 4*6 = 24
return 5*24 = 120
Recursive versions of many routines may execute a bit more slowly than the iterative equivalent because of the added overhead of the additional method calls. A large number of recursive calls to a method could cause a stack overrun
. Because storage for parameters and local variables is on the stack and each new call creates a new copy of these variables, it is possible that the stack could be exhausted. If this occurs, the Java run-time system will cause an exception.
Static Keyword
There will be times when you will want to define a class member that will be used independently of any object of that class. Normally, a class member must be accessed only in conjunction with an object of its class. However, it is possible to create a member that can be used by itself, without reference to a specific instance. To create such a member, precede its declaration with the keyword static
. When a member is declared static
, it can be accessed before any objects of its class are created, and without reference to any object. You can declare both methods and variables to be static
.
Example: main()
function of class is declared static because it must be called before any objects exist.
If method and variables of a class are declared static, then we don't need to create an object to call them.
Example:
class StaticDemo {
static int a = 42;
static int b = 99;
static void callme() {
System.out.println("a = " + a);
}
}
class Main {
public static void main(String[] args) {
StaticDemo.callme(); //calling method callme() without an object
System.out.println("b = " + StaticDemo.b); //accesiing b without object
}
}
Output:
a = 42
b = 99
Characteristics of static
:
Shared memory allocation
Accessible without object instantiation
Associated with class, not objects
Cannot access non-static members
Can be overloaded, but not overridden:
Final Keyword
The final
keyword is a non-access modifier used for classes, attributes and methods, which makes them non-changeable (impossible to inherit or override).
The final
keyword is useful when you want a variable to always store the same value, like PI (3.14159...)
The final
keyword can be applied with the variables, a final
variable that have no value it is called blank final
variable or uninitialized final
variable. It can be initialized in the constructor or during declaration only. The blank final
variable can be static also which can be initialized in the static block only.
Example:
class Bike{
final int speedlimit=90;//final variable
void run(){
speedlimit=400;
}
}
class Main
{
public static void main(String args[]){
Bike obj=new Bike();
obj.run();
}
}
Output:
Main.java:4: error: cannot assign a value to final variable speedlimit
speedlimit=400;
^
1 error
Arrays.length
There is a special array attribute to calculate the size of an array, that is, the number of elements that an array can hold, it is found in its length
instance variable
Example
int[] a = {4, 3, 2, 1};
System.out.println("length of array is " + a.length);
Output:
length of array is 4
Arrays.sort
Arrays.sort() method consists of two variations one in which we do not pass any arguments where it sort down the complete array be it integer array or character array but if we are supposed to sort a specific part using this method of Arrays class then we overload it and pass the starting and last index to the array.
Example for sorting an integer array using Arrays.sort without arguments()
import java.util.Arrays;
class Sort {
public static void main(String args[])
{
int[] arr = { 5, -2, 23, 7, 87, -42, 509 };
System.out.println("The original array is: ");
for (int num : arr) {
System.out.print(num + " ");
}
Arrays.sort(arr);
System.out.println("\nThe sorted array is: ");
for (int num : arr) {
System.out.print(num + " ");
}
}
}
Output
The original array is:
5 -2 23 7 87 -42 509
The sorted array is:
-42 -2 5 7 23 87 509
Example for sorting an integer array using Arrays.sort with arguments()
import java.util.Arrays;
public class Sort {
public static void main(String[] args)
{
int[] arr = { 13, 7, 6, 45, 21, 9, 2, 100 };
// Sort subarray from index 1 to 4, i.e.,
// only sort subarray {7, 6, 45, 21} and
// keep other elements as it is.
Arrays.sort(arr, 1, 5);
System.out.println("Modified arr[] : "
+ Arrays.toString(arr));
}
}
Output
Modified arr[] : [13, 6, 7, 21, 45, 9, 2, 100]
Nested and Inner Classes
It is possible to define a class within another class; such classes are known as nested classes. The scope of a nested class is bounded by the scope of its enclosing class. Thus, if class B is defined within class A, then B does not exist independently of A. A nested class has access to the members, including private members, of the class in which it is nested. However, the enclosing class does not have access to the members of the nested class.
There are two types of nested classes:
static
- A static nested class is one that has the static modifier applied. Because it is static, it must access the non-static members of its enclosing class through an object. That is, it cannot refer to non-static members of its enclosing class directly.non-static
- The second type of nested class is the inner class. An inner class is a non-static nested class. It has access to all of the variables and methods of its outer class and may refer to them directly in the same way that other non-static members of the outer class do.
Example of Static Nested Class
class OuterClass {
int x = 10;
static class InnerClass {
int y = 5;
}
}
public class Main {
public static void main(String[] args) {
OuterClass.InnerClass myInner = new OuterClass.InnerClass();
System.out.println(myInner.y);
}
}
Output
5
Example of Inner Nested Class
class OuterClass {
int x = 10;
class InnerClass {
int y = 5;
}
}
public class Main {
public static void main(String[] args) {
OuterClass myOuter = new OuterClass();
OuterClass.InnerClass myInner = myOuter.new InnerClass();
System.out.println(myInner.y + myOuter.x);
}
}
Output
15
Java String
String
is probably the most commonly used class in Java’s class library. The obvious reason for this is that strings are a very important part of programming. The first thing to understand about strings is that every string you create is actually an object of type String
.
Once you have created a String object, you can use it anywhere that a string is allowed, so it works as a variable but it actually is an object of String
class.
String Length
A String in Java is actually an object, which contain methods that can perform certain operations on strings. For example, the length of a string can be found with the length() method.
Example
String txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println("The length of the txt string is: " + txt.length());
Output
The length of the txt string is: 26
String Concatenation
The + operator can be used between strings to combine them. This is called concatenation:
Example
String firstName = "John";
String lastName = "Doe";
String fullName = firstName + lastName;
System.out.println(fullName);
Output
John Doe
String charAt() Method
The Java String charAt() method returns the character at the specified index. The index value should lie between 0 and length() – 1.
Example
String s = "Hello World";
char ch = s.charAt(3);
System.out.println(ch);
ch = s.charAt(0);
System.out.println(ch);
Output
l
H
String equals() Method
The equals() method compares two strings, and returns true if the strings are equal, and false if not.
Tip: Use the compareTo() method to compare two strings lexicographically.
Example
String myStr1 = "Hello";
String myStr2 = "Hello";
String myStr3 = "Another String";
System.out.println(myStr1.equals(myStr2)); // Returns true because they are equal
System.out.println(myStr1.equals(myStr3)); // false
Output
true
false
Varargs: Variable-Length Arguments
Modern versions of Java include a feature that simplifies the creation of methods that need to take a variable number of arguments. This feature is called varargs and it is short for variablelength arguments. A method that takes a variable number of arguments is called a variablearity method, or simply a varargs method.
A variable-length argument is specified by three periods (…)
If a vararg variable is declared it must be treated as an array inside the method.
Example:
class VarArgs {
// vaTest() now uses a vararg.
static void vaTest(int ... v) {
System.out.print("Number of args: " + v.length +
" Contents: ");
for(int x : v) // for-each loop
System.out.print(x + " ");
System.out.println();
}
}
class Main
{
public static void main(String[] args)
{
VarArgs obj= new VarArgs();
// Notice how vaTest() can be called with a
// variable number of arguments.
obj.vaTest(10); // 1 arg
obj.vaTest(1, 2, 3); // 3 args
obj.vaTest(); // no args
}
}
Output
Number of args: 1 Contents: 10
Number of args: 3 Contents: 1 2 3
Number of args: 0 Contents:
Some key points:
A method can have “normal” parameters along with a variable-length parameter. However, the
variable-length parameter must be the last parameter
declared by the method.
int doIt(int a, int b, double c, int ... vals) //valid
int doIt(int a, int b, double c, int ... vals, boolean stopFlag)//invalid
There must be only one varargs parameter.
int doIt(int a, double c, int ... vals, double ... morevals) //invalid
You can overload a method that takes a variable-length argument. For example, the following code overloads vaTest 2 times.
class VarArgs3 {
static void vaTest(int ... v) {
System.out.print("vaTest(int ...): " +
"Number of args: " + v.length +
" Contents: ");
for(int x : v)
System.out.print(x + " ");
System.out.println();
}
static void vaTest(String msg, int ... v) {
System.out.print("vaTest(String, int ...): " +
msg + v.length +
" Contents: ");
for(int x : v)
System.out.print(x + " ");
System.out.println();
}
}
class Main
{
public static void main(String[] args) {
VarArgs3 obj= new VarArgs3();
obj.vaTest("Testing: ", 10, 20);
obj.vaTest(1, 2, 3);
}
}
Output
vaTest(String, int ...): Testing: 2 Contents: 10 20
vaTest(int ...): Number of args: 3 Contents: 1 2 3
Note the ambiguities which can arise when using varargs as discussed in the lectures.
Exercises
Exercise 1
Implement a Java program that defines a class Point2D
representing a point in a 2D space with x and y coordinates. Then, create a method translatePoint that takes a Point2D
object and two integers (dx and dy). This method should translate the point's coordinates by adding dx to the x coordinate and dy to the y coordinate. The method should return a new Point2D
object representing the translated point.
Write a main method to test your implementation by taking initial inputs and translation parameters dx, dy from the user, creating an initial Point2D
object, displaying its coordinates, calling the translatePoint method, and displaying the coordinates of the translated point.
Sample Input
Enter initial x coordinate: 2
Enter initial y coordinate: 3
Enter dx: 1
Enter dy: 2
Sample Output
Initial Point: (2, 3)
Translated Point: (3, 5)
Exercise 2
Implement a Java program that calculates the sum and multiplication of elements in an array within a specified range using recursion
. The program should take user input for the array size, array elements, starting index, and ending index. Ensure the validity of both indices and then use two recursive methods to calculate the sum and multiplication of array values within the specified range (both indices inclusive).
Sample Input
Enter the size of array: 10
Enter the array values: 1 2 3 4 5 6 7 8 9 10
Enter Starting Index: 3
Enter Ending Index: 9
Sample Output
Sum of elements from index 3 to 9 = 42
Multiplication of elements from index 3 to 9 = 181440
Exercise 3
You are asked to implement a program that checks if two strings are anagrams. An anagram is a word or phrase formed by rearranging the letters of another. Your task is to create a Java program with the following specifications:
Implement a class named AnagramChecker
with the following methods:
areAnagrams(String str1, String str2)
: A static method that checks whether two strings are anagrams. The method should return true
if the strings are anagrams and false
otherwise. Use the .equals()
method for string comparison. Implement an inner class named StringUtil
within the AnagramChecker class with the following methods:
sortString(String str)
: A method that takes a string as input, sorts its characters, and returns the sorted string. You can use any sorting algorithm or convert the string to a character array and then use Arrays.sort on that to implement this.
In the main
method of the program: Take user input for two strings. Use the AnagramChecker class to check if the entered strings are anagrams. Display the result.
(Assume that there are no white blank spaces present in both the strings)
Sample Input
Enter the first string: listen
Enter the second string: silent
Sample Output
The entered strings are anagrams.
Last updated