Class :

(Code Block is also present)

  • Class is a named group of properties and functions
int[] rno = new int[5];
String[] name = new String[5];
float[] marks = new float[5];
// these 3 properties, if we want to combine them to form a single entity, we can do so via Classes.
  • By convention, the class name starts with an UPPERCASE letter.
  • If we want to create our own data type, then we can do that by using classes.
  • function inside a class is called a method.
  • A class is a template for an object, and an object is an instance of a class.
  • A class creates a new data type that can be used to create objects.

When you declare an object of a class, you are creating an instance of that class.
Thus, a class is a logical construct. An object has physical reality. (That is, an object occupies space in memory.)

Objects are characterized by three essential properties: state, identity, and behavior of the object.

  • State of the object : is the value from its data type
  • Identity of the object : The identity of an object distinguishes one object from another.
    It is useful to think of an object’s identity as the place where its value is stored in memory.
  • Behavior of the object : The behavior of an object is the effect of data-type operations.

The dot operator links the name of the object with the name of an instance variable.
Although commonly referred to as the dot operator, the formal specification for Java categorizes the . as a separator.

The 'new' keyword dynamically allocates (that is, allocates at run time and not at compile time)memory for an object & returns a reference to it.

  • Thus, in Java, all class objects must be dynamically allocated.

Constructor :

It basically defines what happens when your object will be created.
It is a special "function" that runs when you create an object, and it allocates some variables.


package com.hitarth.oop;

import java.util.Arrays;

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

        /*declaring an Object*/
        Student kunal; // Declaring a reference to an object of Student type // kunal is a reference variable of our own data type. It consists of 3 "properties".


        /* creating an object */
        Student student1 = new Student(); // 'new' keyword dynamically allocates memory and returns a reference variable to it which will be stored in "student1" variable


        /* null values  */
        Student[] students = new Student[5];
        System.out.println(Arrays.toString(students)); // → [null, null, null, null, null]


        Student real = new Student();
        System.out.println(real); // → / → com.hitarth.oop.Student@5f184fc6 // some random value
        System.out.println(real.name); // → null
        System.out.println(real.rno); // → 0
        System.out.println(real.marks); // → 0.0

        real.rno=13;
        real.name = "Kunal";
        real.marks = 88.58f;

        /* Allocating values while creating an Object using a constructor */
        // constructor function 1
        Student2 bruh2 = new Student2();
        System.out.println(bruh2.name); // → Dev

        bruh2.greeting(); // → Hello! My name is Dev

        bruh2.changeName("hitarth");
        System.out.println(bruh2.name); // → hitarth

        // using constructor function 2
        Student2 vishal = new Student2(12, "VishalP", 23.4f);
        System.out.println(vishal.name); // → VishalP

        // constructor 3
        Student2 dawg = new Student2(143, "doggo", 89.23f);
        System.out.println(dawg.name); // → doggo
    }
}


/* ------------------------------------------------------ */
/*  creating a Class    */

class Student {
    int rno;
    String name;
    float marks; // default values can be defined like this: float marks = 90;
}

class Student2 {
    int rno;
    String name;
    float marks; // default values can be defined like this: float marks = 90;

    // Constructor Function 1:
    Student2 ()
    {
        this.rno = 13;
        this.name = "Dev";
        this.marks = (float) 23.12;
    }

    // Constructor Function 2: here, since both parameter names are same so we are forced to use the "this" keyword for more clarity.
    /*
    Student2 (int rno, String name, float marks)
    {
        this.rno = rno;
        this.name = name;
        this.marks = marks;
    }
    */

    // Constructor Function 3: here since the parameter names and class property names are different, so we can skip the "this" keyword in the constructor function. However, "this" will also work here.
    Student2 (int roll, String naam, float score)
    {
        rno = roll;
        name = naam;
        marks = score;
    }

    void changeName(String newName)
    {
        name = newName;
    }

    void greeting() {
        System.out.println("Hello! My name is " + this.name);
    }
}

Calling a constructor from another constructor :

(using Constructor Overloading)

package com.hitarth.oop;

import java.util.Arrays;

public class Main {
    public static void main(String[] args)
    {
        Student kunal = new Student();
        System.out.println(kunal.name); // → default person
    }
}
/* ------------------------------------------------------ */
class Student {
    int rno;
    String name;
    float marks;

    Student()
    {
        this (13, "default person", 100.23f);
    }

    Student(int rno, String name, float marks)
    {
        this.rno = rno;
        this.name = name;
        this.marks = marks;
    }
}

Wrapper Classes

Final Class :

  • final is a keyword using which you can prevent your content to be modified.
  • final variables have to be initialized on declaration.
  • It only guarantees "no change" when the instance variables are of primitive data type and not reference data type.
  • If a reference data type has a final modifier attached to it then the value of that instance variable will never change, i.e. the reference to the object will never change. It will always refer to the same object but the value of that object can still be modified / changed.
  • This happens because this immutability that you can't change the value is only holding true for primitive data type.
  • What if the object itself is final
final Student kunal = new Student();
kunal.name = "new name" // this is possible despite the presence of the "final" keyword.
// this happens because the kunal here is an object and not a primitive data type.
// so here, we are allowed to change the values but we are NOT allowed to reassign the "kunal" reference variable. Therefore : 
kunal = new Student("new object"); // this is NOT allowed  

Code Block :

package com.hitarth.oop;

import java.util.Arrays;

public class Main {
    public static void main(String[] args)
    {
        Integer num = 45; // now this num is an object and it's not a primitive
        // This num object comes with it's own functions. Type "num." and you'll be shown a list of all the performable functions.

        //num.toString()  //  num.byteValue() // and so on

        swap(num);
        System.out.println(num); // → 45
        // even tho num is an object it still wasn't swapped
        // This happens because Integer class is a final class
        // Final is a keyword using which you can prevent your content to be modified, a constant I should say.

        // for e.g.
        final int increase = 2; // now this integer cannot be modified
        // increase++; // → error
    }

    static void swap (Integer a)
    {
        a = 23;
    }
}

Garbage Collection :

  • right before the object is freed from the memory, java is going to call the garbage collector and the finalized method.
package com.hitarth.oop;

import java.util.Arrays;

public class Main {
    public static void main(String[] args)
    {
        A obj1;
        // we have to enter a large number here like 10000000 in order to put load on the memory so that the garbage collector actually starts destroying objects in order to save some space.
        for (int i =0; i< 10000000; i++)
        {
            obj1 = new A("Random name"); // obj1 will point to a new object on every iteration so the prev object will be destroyed
        }
        // → Object is destroyed // will be printed again and again now
    }
}

/* ------------------------------------------------------ */
class A {
    final int num = 10;
    String name;

    A(String name)
    {
        this.name = name;
    }

    /*finalized method*/
    // whenever any object of class A is freed from the memory the following function will be executed.
    // type "finalize" to get a pop up in IntelliJ
    @Override
    protected void finalize() throws Throwable {
        System.out.println("Object is destroyed");
    }
}