> For the complete documentation index, see [llms.txt](https://oop-spring-2024.gitbook.io/cs-f213-oop/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://oop-spring-2024.gitbook.io/cs-f213-oop/labsheet-4/cs-f213-objected-oriented-programming-labsheet-4.md).

# CS F213 Objected Oriented Programming Labsheet 4

### 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:**

```java
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:**

```java
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:**

```java
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:**

```java
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:**

```java
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:**

```java
Factorial of 3 is 6
Factorial of 4 is 24
Factorial of 5 is 120
```

**Working of the above Program**

```java
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:**

```java
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:**

```java
a = 42
b = 99
```

<br>

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:**

```java
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:**

```java
Main.java:4: error: cannot assign a value to final variable speedlimit
  speedlimit=400;  
  ^
1 error
```

<br>

### 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**

```java
int[] a = {4, 3, 2, 1};
System.out.println("length of array is " + a.length); 
```

**Output:**

```
length of array is 4
```

<br>

### 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()**

```java
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**

```java
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()**

```java
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**

```java
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:

1. `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.
2. `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**

```java
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**

```java
5
```

**Example of Inner Nested Class**

```java
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**

```java
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**

```java
String txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println("The length of the txt string is: " + txt.length());
```

**Output**

```java
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**

```java
String firstName = "John";
String lastName = "Doe";
String fullName = firstName + lastName;
System.out.println(fullName);
```

**Output**

```java
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**

```java
String s = "Hello World";

char ch = s.charAt(3);
System.out.println(ch);

ch = s.charAt(0);
System.out.println(ch);
```

**Output**

```java
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**

```java
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**

```java
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:**

```java
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**

```java
 Number of args: 1 Contents: 10
 Number of args: 3 Contents: 1 2 3
 Number of args: 0 Contents:
```

#### Some key points:

1. 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.

```java
int doIt(int a, int b, double c, int ... vals) //valid

int doIt(int a, int b, double c, int ... vals, boolean stopFlag)//invalid
```

<br>

2. There must be only one varargs parameter.

```java
int doIt(int a, double c, int ... vals, double ... morevals) //invalid
```

<br>

3. You can overload a method that takes a variable-length argument. For example, the following code overloads vaTest 2 times.

<pre class="language-java"><code class="lang-java">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);
<strong>        obj.vaTest(1, 2, 3);
</strong>    }
}
</code></pre>

**Output**

```java
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**

```java
Enter initial x coordinate: 2
Enter initial y coordinate: 3
Enter dx: 1
Enter dy: 2
```

**Sample Output**

```java
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**

```java
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**

```java
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.
```
