Unit 1 : Java Programming Basics

hitarth's Vault // Exported at - 12:29 AM

We'll cover :

  • What is Java, it's history (history related ques might come in exams), features of java
  • Data types
  • Variables
  • Constants

What is JAVA :

  • It is a high level programming language which is based on deep concept of Object-Oriented Programming.
  • Java is a platform because it has its own runtime environment that is JVM (Java Virtual Machine).
  • The features of OOP are : Class, Object, Inheritance, Polymorphism, Encapsulation, Abstraction
  • The features of OOPs are such that the real world problems can be solved by using programming language with less complexity.

History Of JAVA :

James Gosling and his team started JAVA. In Sun Micro Systems, the JAVA was evolved in the year 1991. The first name of JAVA was OAK.
After 4 years that is in 1995 the first version of JAVA was developed. The name of the version was JAVA alpha Beta version. In 1996 the next version was developed, JDK 1.0.

Version of JAVA :

  • ! Ques might come
    Version | Release Date | Code Name
Version Release Date Code Name
JDK 1.0 1996 Oak Changed to JAVA
JDK 1.1 DIY DIY
  • Oracle in 2010 acquitted Sun Microsystems company, so currently license of JAVA is in hands of Oracle

Features of JAVA :

  • JAVA is platform independent

  • The program written once can run anywhere.

  • Pasted image 20231219224609.png

  • Java is portable since we can move .class file from one platform to another.

  • .class file contains bytecode.

  • To execute Java code, you need to compile it. The Java compiler (javac) takes the source code (.java files) and produces bytecode, which is a platform-independent intermediate representation of the code.

  • Security :
    - JVM : Its basic role is to verify byte code before running it. This makes sure that the program is not making any unsafe operation. There are various unsafe operations that a program can perform, for e.g. A program might branch to an incorrect location that contains data rather than instructions.
    - Security Manager : Security Manager Layer is present in JVM, it's makes sure that untrusted code does not manage to access some APIs and features of the platform.
    - No Pointers : Java does not support pointers as C and C++ supports, therefore some arbitrary location can not be addressed. Some arbitrary address can be accessed via pointers, which might be
    - Java has 4 access modifiers, public, protected, private and default, so if we want to hide some code we can use access modifiers.
    Pasted image 20240106022114.png

  • Exception Handling :

    • If a program has some error, it will not get compiled. Exception Handling catches the results which are unexpected and reports the error to the program until the rectification of the error by the programmer. This concept will not allow code to run making java more secure
  • Own Memory Management :

    • The memory management mechanism is unique and owned by java, there is no need for manual intervention for garbage collection and everything is handled automatically. There is no headache to free the memory, it drastically reduces the programmer overhead.

Other Features :

  • Object Oriented : Java is Object Oriented Programming
  • Robust : Robust means trustable. Small exceptions are handled carefully.
  • Multi Threading : Complex problems are divided into small problems and then are solved.
  • Simplicity : As compared to C and C++ JAVA is much more simple, as it does not have the concept of pointers, and has features like Garbage Collection.

Data Types :

They are of two types : Primitive and Non-Primitive.
Non Primitive are user defined and Primitive are pre defined

Primitive Data Type :

  • Size is fixed
  • e.g. : int
    It is further Divided into Boolean and Numeric

Boolean :

  • Either true or false
  • Usually used in true false conditions.
  • Default value of a boolean data type is false.
  • boolean flag = false;
  • System.out.println(flag);

Numeric :

  • Any numeric values
  • Further divided into : Character or Integral

1. Integral

  • Integer and Floating Point
  • Integers : Byte, Short, Int and Long
  • Floating Point : float and Double

2. Character

Non-Primitive Data Type :

  • Size might change on runtime
  • e.g. Array, String, Class, Structure ... etc.

Size :

  • For signed data types, use formula -2(n-1) to (2(n-1)) – 1
  • For unsigned numbers it will be 2n-1 as there are no negative numbers
  • int : 4 Bytes : Default value is 0
  • short : 2 Bytes
  • float : 4 Bytes
  • double : 8 Bytes
  • long : 8 Bytes
  • char : 2 bytes (because of UNICODE System)

Primitives :

  • By default all decimal type values are of type double, if we want to store these decimal values in let's say 'float' then we have to add 'f' at the end like this : float marks = 98.67f;
  • by default all the integer values are of type integers, if we want to store these integers in let's say 'long' then we'll have to add 'L' at the end like this : long largeIntegerNumbers = 1212514513452234234L;
package com.hitarth;

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

        // String is not a primitive
        // Primitive is basically a data type that you cannot break further

        // Primitives :
        int rollno = 64;
        char letter = 'r';
        float marks = 98.67f; // TN: that we have to add 'f' here.
        double largeDecimalNumbers = 456234.3234234;
        long largeIntegerNumbers = 1212514513452234234L; // TN: we have to add 'L' here.
        boolean check = false;

        // 1.) by default all the decimal values are of type double if we want to store these decimal values in lets say 'float' then we have to add 'f' at the end like this : `float marks = 98.67f;`

        // 2.) by default all the integer values are of type integers, if we want to store these integers in let's say 'long' then we'll have to add 'L' at the end like this : `long largeIntegerNumbers = 1212514513452234234L;`
    }
}

Char

package com.hitarth.classLectures;

public class asd {
    public static void main(String[] args) {
        char letter1 = '9';
        System.out.println(letter1); // → 9

        char letter2 = 65; // ASCII / Unicode
        System.out.println(letter2); // → A

		int number = 'A';
		System.out.println(number); // -> 65 // ASCII value of A = 65

    }
}

String :

String a = "Kunal"; // takes 5*2 = 10 bytes
String b = "Kunal";

Array :

Kunal Kushwaha dekh le bhai

Variables in Java :

  • A variable is used to store a memory address.
  • Firse Kunal Kushwaha se padh le bhai

Variables are of three types : Local, Static and Instance (Global variable) Variables.
Static padhle bhai

package com.hitarth.classLectures;

public class asd {
    public static void main(String[] args) {
        int a = 10; // instance variable
        Static int b =20; // static variable
    }
    void add()
    {
        int c =30, d; // local variable
        d= a+b+c;
        System.out.println(d);
    }
    void multiply()
    {
        int e =40, f;
        f=a*b*c*e;
        System.out.println(f);
    }
}

Local Variable :

  • They are declared within a method or a constructor or a block.
  • The scope of local variable is inside a method or a constructor or a block
  • The variables get allocated in the memory when they get executed
  • After an exit the variables get destroyed outside the block.
  • Local Variables don't have any default values.
  • They are stored in stack memory.
  • Access specifiers can't be used with local variables.
package com.hitarth.packages;

public class random {
}

class A {
    int a = 10;
    static int b = 20;

    void add() {
        int c = 30, d; // int c, d => local variable
        d = a + b + c;
        System.out.println(d);
    }
}

Instance Variable :

  • declared inside a class but outside a constructor or a method or a block.
  • The scope of an instance variable is inside all method, blocks or a constructor within a class.
  • Variables get memory allocated when an object is created
  • When an object gets deleted or destroyed, the variable releases the memory.
  • Instance variable is stored in heap memory.
  • They have default values. Default value of int is zero, for bool it is false, for char is NULL.
  • Access specifiers can be used with instance variable.

Static Variable :

  • They are declared within a class by using static keyword but outside a method or a constructor or a block.
  • the scope of static variable is inside all method or constructor or block.
  • these variable get allocated in memory when we run a program and .class file is loaded
  • when .class file is unloaded the variables get deleted.
  • static variables are stored in static memory
  • the default value of static variable is similar to an instance variable.
  • access specifiers can be used with static variables.
package com.hitarth.packages;

class abc {
    int a = 10;
    static int b =20;
}

public class random {

    public static void main(String[] args) {
        abc ob1 = new abc();
        System.out.println(ob1.a); // → 10
        System.out.println(ob1.b); // → 20
        ob1.a = 1000;
        ob1.b = 2000;
        System.out.println(ob1.a); // → 1000
        System.out.println(ob1.b); // → 2000

        abc ob2 = new abc();
        System.out.println(ob2.a); // → 10
        System.out.println(ob2.b); // → 2000
    }
}

Operators, Literals and Keywords in JAVA :

Operators are special symbols which can perform any operations on one or more operands.

  • c = a + b : a and b are operands

Arithmetic Operator :

  • Addition, Subtraction, Multiplication, Division, Modulus %, increment ++, decrement --

Relational Operator :

  • equal to ==, not equal to !=, >, <, >=, <=,

Bitwise Operator :

  • operations are performed on individual bits
  • converts decimal to binary and perform the required operation
  • learn about && in java
  • bitwise right shift >>, bitwise left shift <<, zero fill right shift >>>

Logical Operator :

and &&, or ||, not !

package com.hitarth.packages;


public class random {


    public static void main(String[] args) {
        int x = 10, y = -10;
        System.out.println(x << 2); // → 40
        System.out.println(x >> 2); // → 2
        System.out.println(x >>> 2); // → 2
        System.out.println(y << 2); // → -40
        System.out.println(y >> 2); // → -3
        System.out.println(y >>> 2); // → 1073741821

    }
}

Literals:

A value assigned to a variable is known as literals. int a = 10, literal = 10, variable = a, int = data type.

  • Literals are of type integral, float, char, string, etc.

Keyword :

In Java, keywords are reserved words that have a specific meaning and cannot be used as identifiers (e.g., variable names, class names, method names).

  1. abstract
  2. assert
  3. boolean
  4. break
  5. byte
  6. case
  7. catch
  8. char
  9. class
  10. const (not used, reserved for future use)
  11. continue
  12. default
  13. do
  14. double
  15. else
  16. enum (introduced in Java 5)
  17. extends
  18. final
  19. finally
  20. float
  21. for
  22. if
  23. goto (not used, reserved for future use)
  24. implements
  25. import
  26. instanceof
  27. int
  28. interface
  29. long
  30. native
  31. new
  32. package
  33. private
  34. protected
  35. public
  36. return
  37. short
  38. static
  39. strictfp
  40. super
  41. switch
  42. synchronized
  43. this
  44. throw
  45. throws
  46. transient
  47. try
  48. void
  49. volatile
  50. while

Identifier :

  • It is any name given to a method or a class or a variable or interface.
  • int a =10; : a is a variable name = Identifier
  • class Abc{...}; : Abc here is an identifier

Rules :

In Java, identifiers are used to name classes, methods, variables, and other program elements. Here are the rules for defining identifiers in Java:

  1. Must Begin with a Letter, Currency Character, or an Underscore:
    • Identifiers must start with a letter, currency character ($), or underscore (_).
  2. Can Be Followed by Letters, Digits, Currency Characters, or Underscores:
    • After the initial character, the identifier can consist of letters, digits, currency characters, or underscores.
    • integer values can't be used at the first place.
  3. No Spaces or Special Characters:
    • Spaces and special characters (except for currency characters and underscores) are not allowed within an identifier.
  4. Cannot be a Reserved Keyword:
    • Identifiers cannot be a reserved keyword. Java has a set of reserved words that have predefined meanings in the language and cannot be used as identifiers.
  5. Case-Sensitive:
    • Java is case-sensitive, so myVariable and myvariable would be considered different identifiers.
  6. Length is Not Limited:
    • The length of an identifier is not limited, but it's a good practice to keep identifiers reasonably short and meaningful.

Naming Convention :

three words are given : my java demo

Variable :

  • my_java_demo
  • myJavaDemo

Method:

Use Camel Case

  • my()
  • myJavaDemo()

Class:

  • First letter should be an UPPERCASE letter.
  • MyJavaDemo{}

JAVA Programming Paradigms :

  • Java is based on the concept of OOP.
    4 basic JAVA Paradigms are :
    Encapsulation, Inheritance, Abstraction (information hiding), Polymorphisms

1. Encapsulation :

It is a process of wrapping data and method together into a single unit.
In OOP we have to build objects, and objects are developed by means of classes. Defining classes in OOP is termed as encapsulation.

2. Inheritance :

Telusko YT > Inheritance
Inheritance in JAVA is a mechanism in which one object acquires all the properties and behavior of a parent object.

3. Information Hiding / Abstraction :

It is a process of hiding some data or method, so that it is not easily accessible to others.

4. Polymorphism :

https://www.geeksforgeeks.org/difference-between-compile-time-and-run-time-polymorphism-in-java/
Function having same name, but it performs different operations.
For example : If we use print operation then, method for printing an image and document will be different.

  • It is of two types : Compile Time Polymorphism and Runtime Polymorphism :
    • Compile Time : Method Overloading
    • Runtime : Method Overriding (Class extend karke parent class ke method ko @Override use karke uska method ko override karna (@Override use karna is not necessary))

JAVA Software Installation :

CMD ke through java program run and save karna padhle bhai

  • Assignment : Prime no., Factorial, reversing numbers., random number

Control Statements in JAVA :

Java program normally executes from top to bottom, but if you want to control the order of execution of the program based on some logic and values we use control statements.
Control statements are of three types :

  • Selection and conditional statements : if, if else ,else if, nested if, switch case
  • Iteration and Looping Statements : for, while, do while
  • Jump Statements : return, break, continue

Array

Array is a collection of finite set of elements of same type.
Three steps are to be followed to create an array :

  • Declaration of an array

    • <type> array_name[] : int a[] or int[] a
  • Allocate memory for an array

    • <arrayName> = new <type>[size] : here new is used to allocate memory
    • int a[] = new int[100] or int a[] then do a = new int[100];
  • Initialization of an array.

    • for loop se karlo bhai initialize
    • int a[] = {1,2,3,4,5}
  • a.length will give the length of the array

2D array

  • khudse padhlo bhai
    int a[][] = new int[2][3]
    int a[2][3] = {1,2,3,4,5,6} :
1 2 3
4 5 6

Recursion :

  • If any functions calls itself then the process is called recursion.
  • A function in JAVA can call itself, such calling of function by itself is called recursion.

Factorial by Recursion :

package com.hitarth.IIITL2024;
// factorial by recusrion
public class FactorialByRecursion {
    public static void main(String[] args) {
        int num = 5;
        System.out.println("Factorial of " + num + " is: " + factorial(num));
    }

    static int factorial(int num) {
        if (num == 0 || num == 1)
            return 1;
        else
            return num * factorial(num - 1);
    }
}

Fibonacci using recursion : DIY

  • LAB me kar rakha hai already

Array in JAVA :

1D Array :

int[]a, b; //-> a-> 1D array, b->1D array
int a[], b; // a-> 1D array, b-> variable

a = new int[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;

int[] a = {1,2,3,4,5};
// or
int[] a = new int[]{1,2,4};

2D Array :

        int[][] arr;
        int arr2[][];
        int[]a[];

        int[]a, b[]; // → a is 1D array, and b is a 2D array
        int[] a[], b[]; // → both are 2D arrays
        int[][] a, b[]; // → a is 2D and b is 3D array
int[][]a;
a= new int[2][3];
int[][]a = {{1,2,3},{4,5,6}};

2D Jagged Array :

        int[][] a;
        a = new int[2][];
        a[0] = new int[4];
        a[1] = new int[2];

        // this jagged array will look like this : 

        // x x x x
        // x x

        // doing all of this in a single line : 

        int[][] b = {{1, 2, 3, 4}, {1, 2}};

3D Jagged Array :

        // 3D Jagged Array :
        int[][][]a;
        a=new int[2][][];
        
        a[0] = new int[2][];
        a[0][0] = new int[3];
        a[0][1] = new int[2];
        a[1] = new int[2][];
        a[1][0] = new int[2];
        a[1][1] = new int[3];

Length of array & Accessing values

package com.hitarth.IIITL2024;

public class temp {
    public static void main(String[] args) {
        int[][] arr = {{1,2,3,4}, {1,2}};
        System.out.println(arr[0].length); // → 4
    }
}
package com.hitarth.IIITL2024;

import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        int[][] arr = {{9, 8}, {1,2,3,4}};

        for(int i =0; i<arr.length; i++)
        {
            for(int j = 0; j<arr[i].length; j++)
            {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  • Output :
    Pasted image 20240214152007.png

3D Array :

package com.hitarth.IIITL2024;

import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        int[][][] arr = {{{20, 30}, {10, 40, 60}}, {{80, 25}, {76, 23, 44}} };
        for(int i=0; i< arr.length; i++)
        {
            for(int j = 0; j< arr[i].length; j++)
            {
                for(int k = 0; k< arr[i][j].length; k++)
                {
                    System.out.print(arr[i][j][k] + " ");
                }
                System.out.println();
            }
                System.out.println();
        }
    }
}
  • Output :
    Pasted image 20240214152611.png

Sorting :

  • Sorting is the process of arranging the elements in a logical form (asc or desc) in case of alphanumerical values it can be in dictionary order.
  • Different Ways of sorting are: bubble, selection, insertion, merge, quick, heap

Bubble Sorting :

  • It is a comparison based algorithm, it is also referred as syncing sort. It compares each pair of adjacent items and swap them if they are in wrong order.
  • the pass through the list is repeated until no swaps are needed, which indicates that the list is sorted.
  • No. of rounds = no. of elements in an array - 1
  • Asc and desc dono ka padh le bhai

Selection Sort:

  • First find the index of the smallest number.
  • We'll interchange it with the element at first position.
  • | 36 19 29 12 5< => 5 | 19 29 12< 36 => 5 12 | 29 19< 36 => 5 12 19 | 29< 36 => 5 12 19 29 36
Info

2 Lectures missed


Inheritance :

  • Inheritance in JAVA is a mechanism in which one object acquires all the properties and behavior of a parent object.
package com.hitarth.packages;
/* ------------------------------------------------------ */

//superclass or parent class
class Calc {
    public int add(int n1, int n2) {
        return n1 + n2;
    }

    public int sub(int n1, int n2) {
        return n1 - n2;
    }
}

//subclass or child class
class AdvCalc extends Calc
{
    public int mult(int n1, int n2)
    {
        return n1*n2;
    }
}

/* ------------------------------------------------------ */

public class _07_Inheritance {
    public static void main(String[] args) {
        Calc obj = new Calc();
        int r1 = obj.add(1,2);
        System.out.println(r1); // → 3

        AdvCalc obj2 = new AdvCalc();
        int r2 = obj2.mult(2,3);
        int r3 = obj2.add(1,3);
        System.out.println(r2); // → 6
        System.out.println(r3); // → 4
    }
}

AdvCalc IS-A (read as "is a") Calc : means that AdvCalc is a child class and Calc is a parent class.

  • Inheritance offers IS-A relationship
  • The main advantage of Inheritance is code reusability. If we require to reuse a class then we can simply use the extend keyword.
  • We can achieve polymorphism by using inheritance.
    Disadvantage :
  • Two classes will be tightly coupled. Child class will inherit / access all the classes of the parent class.
  • When there are many child classes of a parent class then when a change is made to the parent class then that change will be reflected in all the child classes of that parent class which may or may not be required.
  • Child class will be tightly coupled with the parent class, so any change in the parent class will cause impact on all the child classes.

Types of Inheritance :

1. Single Inheritance :

  • Ek parent class hogi and ek child class hogi
  • Pasted image 20240314142416.png

2. Multilevel Inheritance

  • Pasted image 20240314142446.png
example khud se padh lena bhai

Pasted image 20240314143125.png

3. Hierarchical Inheritance :

Pasted image 20240314142532.png

example khud se padh lena bhai

4. Multiple Inheritance :

Pasted image 20240314142629.png

5. Hybrid Inheritance :

When any two inheritance types are combined :
Pasted image 20240314142758.png

Only 1,2,3 types of inheritances are used in JAVA.

Can a child class Access all the properties of the parent class ?

  • If a method is private in a parent class then the child class will not be able to access that private method.
  • If there is a constructor in a parent class then a child class will not be able to access/call the constructor of its parent class.
  • Constructor and private methods of parent class do not get inherited into child classes.

Relationship between Classes :

Pasted image 20240314144106.png

  • Inheritance : IS-A relationship : IS-A relationship always refers to Inheritance.
  • Association : HAS-A Relationship

Inheritance : Is - a relationship

class Animal
{
}

class Dog extends Animal
{
}

Association : Has - a relationship

class Student
{
	string name;
	int roll_no;
}
  • Here we can observe that Student HAS-A roll_no, Student HAS-A name
  • If we create an object of this class then it'll have these props in it.
class Engine
{}

class Car
{
	psvm()
	{
		Engine ob1 = new Engine();
	}
}
  • Here, Car HAS-A Engine

The difference b/w the two is tight coupling

  • in has-a relationship we have to separately mention the method that we want to access.
  • in is-a relationship it is not necessary to do so
  • When writing large programs we prefer to use has-a relationships.

Difference b/w Is-a and Has-a Relationship :

  • Is-a : Extend keyword is used.
  • Has-a : Reference keyword or new keyword.
  • Is-a : Blood relationship b/w parent and child class.
  • Has-a : No blood relationship.
  • Is-a : Tightly Coupled
  • Has-a : Not tightly coupled.

Sorting

  • Bubble, Insertion, Selection, Merge Sort (Tail recursion and cache friendliness)

Polymorphism :

Compile Time Polymorphism : Method Overloading
Run Time Polymorphism : Method Overriding

Method Overloading & Overriding

  • We make multiple methods of same name.
  • In overloading, methods should be in the same class.
  • In overriding, methods should be in different class.
  • In overloading : The method should have different arguments. This can be achieved by :
    • Either changing the number of arguments or by changing the sequence of arguments ( (int a, string b) and (string a, int b) ) or by changing the type arguments.
  • In overriding : method should have same arguments
    • Either the number of arguments should be same or the sequence of args should be the same or the type should be the same.

Method Overloading :

package com.hitarth;

import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        fun(67); // → 67
        fun("hello!"); // → hello!
    }

    static void fun (int a)
    {
        System.out.println(a);
    }
    static void fun (String b)
    {
        System.out.println(b);
    }

}

Questions :

Q : Can we achieve method overloading in JAVA by changing the return type of the method only :

package tempPackage;

public class promotion {
    public static void printInt(int value) {
        System.out.println("Integer value: " + value);
    }

    public static void main(String[] args) {
        char c = 'A';  // Unicode value of 'A' is 65
        int i = 10;

        // Call printInt method with char argument
        // Char will be promoted to int automatically
        printInt(c); // Output: Integer value: 65

        // Call printInt method with int argument
        printInt(i); // Output: Integer value: 10
    }

}
  • at the time of execution when the compiler does not find any matching arguments it automatically promotes the argument in following way (upar wala code dekh le bhai), this is an important concept of automatic promotion in method overloading in which one type is promoted to another implicitly if no matching data type is found.
  • Pasted image 20240318155242.png
package tempPackage;

public class promotion {
    void show(int a, float b) {
        System.out.println("1");
    }
    void show(float a, int b){
        System.out.println("2");
    }

    public static void main(String[] args) {
        promotion obj = new promotion();
        obj.show(1, 34.30f); // → 1
        obj.show(1, 5); // error
    }

}
  • ! Question : To Do :

    float double and long hai methods me to if we pass an integer value to wo float double long me se kisko call karega ?

Method Overriding :

It means methods with same name but in different classes.

package com.hitarth.packages;

class A
{
    public void show()
    {
        System.out.println("in A show");
    }
    public void config()
    {
        System.out.println("in A config");
    }
}

class B extends A
{
    // method overriding
    public void show()
    {
        System.out.println("in B show");
    }
}

public class _08_Overriding {

    public static void main(String[] args) {
        B obj = new B();
        obj.show(); // → in B show
        obj.config(); // → in A config
    }
}
  • If we still want to use the method from the parent class after overriding it in the child class then we can either make an object of the parent class or use super().
// child class ka method : 

@Override
void show()
{
	super.show(); // calls the method of the parent class
	System.out.println("Child Class"); //prints "Child Class"
}

Abstraction :

Detail / Implementation Hiding : Abstraction
Data hiding : Encapsulation

Difference b/w abstraction and encapsulation

  • Abstraction is detail / implementation hiding.
  • Encapsulation is data / information hiding.
  • Data abstraction deals with exposing the interface to the user and hiding the details of the implementation.
  • Encapsulation groups together data and a method that acts upon the data.

Abstraction :

  • Pasted image 20240216234945.png
    • You need to add an abstract keyword to only declare a method.
In this lecture we will learn:
- What is Abstraction?
- Abstract method in Java
- Abstract class in Java
- Abstract vs Concrete classes

#1
Abstraction is a process of hiding the implementation details and showing only functionality to the user.

#2
Abstract method:-
- Instead of defining the method, we can declare the method.
- If we put a semicolon at the end of a method, it means that you only declare the method like:
 public void drive();
- This method does not contain any features and you will not be able to create an object of it.
- You need to add an abstract keyword to only declare a method.

#3
Abstract class:-
- Abstract methods can only be defined in an abstract class.
- We need to add an abstract keyword before a class to make it an abstract class.
- Objects of an abstract class can not be created.
- If you are extending an abstract class, then it is compulsory to define all abstract methods.
- It is not necessary that an abstract class should have an abstract method.
- Abstract class can have an abstract or a normal method or both.
- An abstract class can have more than one abstract method.

#4
Concrete class: A class other than an abstract class is known as a concrete class.
- An object of a concrete class can be created.
  • A method without body (no implementation) is known as an abstract method.

  • An abstract method must always be declared inside of an Abstract class, or we can say that if a class has an abstract method it should be declared abstract as well

  • It is not necessary that an abstract class will have abstract methods only, we can create simple methods too which has a defined body.

  • If a child class extends an abstract class then the class must have to implement all the abstract methods of the abstract parent class or it has to be declared abstract as well.

  • Interfaces can be used to implement abstraction as well.

  • Abstraction in JAVA can be implemented in two ways :

    • By using Abstract Keyword or by using Interfaces
  • In interfaces all the methods are abstract.

Interface :

They are used to achieve abstraction. It is a blueprint of the class, in which all the methods are abstract and all methods are public.

  • field/variable : Compiler by default adds public static final keyword
  • methods : all methods are abstract and public. By default, compiler adds public static keyword before a method in an interface.
  • only default concrete methods, static methods or private methods can be created inside of an interface.
  • implements keyword is used when a class inherits the methods of an interface.
  • We can't create an object of abstract as well as interface class.
  • In JAVA Multiple Inheritance is not supported but with interfaces Multiple Inheritance can be implemented. Multiple interfaces implements kar sakte hai ek class me.
Info

The reason behind this is to prevent ambiguity. Consider a case where class B extends class A and Class C and both class A and C have the same method display(). Now java compiler cannot decide, which display method it should inherit. To prevent such situation, multiple inheritances is not allowed in java.

interface Interface1 {
    void method();
}

interface Interface2 {
    void method();
}

class MyClass implements Interface1, Interface2 {
    @Override
    public void method() {
        System.out.println("Implemented method");
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.method(); // Output: Implemented method
    }
}
  • In the above example, MyClass implements both Interface1 and Interface2, each of which declares a method method(). MyClass provides a single implementation for method() that satisfies both interfaces. When you call method() on an instance of MyClass, the implemented method is invoked, and you get the output "Implemented method".

Differences b/w Abstract Class and Interface :

  • ! DIY

Encapsulation :

  • It means Data Hiding.
  • Encapsulation in JAVA is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit.
  • Two ways to perform encapsulation
    • Declare the variable of the class as primitive (might be private).
    • Provide public setter and getter methods to modify and view the variable values.
  • Getters and Setters can be used to get or set a value of a variable in an object.

this keyword :

  • There are 6 main uses of this keyword.
    • This keyword is a reference variable that refers to instance variable of the current class.
    • This keyword can be used to invoke current class methods.
    • this() can be used to invoke current class constructors.
    • this keyword can be used to pass as an argument in the method call
    • this keyword can be used to pass as an argument in the constructor call
    • It can be used to return the current class instance from the method
Class Test
{
	int i;
	void start(int a)
	{
		i = a;
	}
	void display()
	{
		sop(i);
	}
}
Class Test
{
	psvm()
	{
		Test ob = new Test();
		ob.start(10);
		ob.display(); // Prints : 10
	}
}
Class Test
{
	int i;
	void start(int a)
	{
		this.i = i;
	}
	void display()
	{
		sop(i);
	}
}

This keyword can be used to invoke current class methods

Class ThisDemo
{
	void Display()
	{
	
	}
	void show()
	{
	
	}
}
Class Test
{
	psvm()
	{
		ThisDemo ob = new ThisDemo();
		ob.Display(); // Here we are "Directly Calling" the a method from ThisDemo Class/Object.
	}
}

this() can be used to invoke current class constructors.

Class A
{
	A()  // No Arg Constructor
	{
		this(10); // calls the parameterized constructor
	}
	A(int a) // Parameterized constructor
	{
		this(); // will call the No Arg Constructor
		sout(a + "parameterized constructor");
	}
	
}

// ---

	psvm()
	{
		A ob = new A(); // invokes the constructor of class A which in turn invokes the parameterized constructor with parameter value 10.
	}


this Keyword can be used to pass as an argument in the method call

method1()
{

}
method2()
{
	method1(this)
}
  • ! Baaki bache points khudse padhle bhai

Super Keyword :

Class A
{
	int a = 10;
}
Class B extends A
{
	int a = 20;
	void Dipslay(int a)
	{
		sout(a); // 30
		sout(this.a); // 20
		sout(super.a); // 10
	}
}

// ---

psvm()
{
	B ob = new B();
	ob.Dsiplay(30);
}
  • Super keyword can be used to refer immediate parent class instance variable.
  • It can be used to invoke immediate parent class method.
  • super() can be used to invoke immediate parent class constructor.
Class A
{
	m1()
	{
		sout("Class A");
	}
}

Class B extends A
{
	m1()
	{
		sout("Class B");
	}
	void Display()
	{
		m1(); // Prints : Class B
		super.m1(); // Prints : Class A
	}
}

// --

psvm()
{
	B ob = new B();
	ob.Display();
}

Final Keyword :

  • Can be used with variables, methods and class.
  • Method which is final can not be overridden.
  • Class which is final can't be extended.

Static Keyword :

Class A
{
	static int a = 10; // instance variable
	void Display()
	{
		int b = 10; // Local Variable
	}
}
  • Static keyword can only be used with class/instance variable and not with local variables. They can also be used with methods like static void Display().
  • Static variables can directly be accessed using Class Names. sout(A.a).

Static keyword with a method :

  • A static method can be accessed without first making an object of the container class and just by using the class name.
  • Static keyword saves memory
  • it belongs to the class and not to the object
  • a static method can be accessed directly by class name and does not need any object
  • a static method can access only static data, it cannot access non-static data (instance data)
  • a static method can call only static method and cannot call non-static methods
  • a static method can't refer to this and super keywords in any way

Static Block :

  • Static block is executed even before the main method is executed.
Class test
{
	static {
		sout("static block");
	}

	psvm() {
		sout("Main Method");
	}
}
Output : static block Main Method
  • Static block executes automatically when the class is loaded into the memory
  • Static block is used to initialize the static members, a program can have multiple static blocks.

Exception handling :

  • What is an exception ?
  • Any unexpected event that disrupts the normal flow of a program is called an exception.
  • Keywords associated with Exception handling: try-catch, finally, throw, throws
  • An exception is an unwanted / unexpected event which occurs during the execution of the program (i.e. at runtime) that disrupts the normal flow of the program.
  • Handling such unwanted / unexpected events is known as Exception Handling.
  • An exception handling is taking some alternative way so that the normal flow of program does not get disturbed.
Class tes
{
	psvm()
	{
		sout("1");
		sout("2");
		sout("3");
		sout("100/2"); // suppose it was (100/0) instead then the compiler will show us an exception
		sout("4");
		sout("5");
		sout("6");
	}
}

Pasted image 20240408154015.png
Pasted image 20240408154447.png

Exception :

  • ClassNotFoundException, NoSuchMethodException, IOException, SQLException, RemoteException, InterruptedException, RuntimeException, VirtualMachineException, LinkageError, AssertionError
    - IOException has child classes : EOFException (end of file), FileNotFoundException, InterruptedIOException
    - RuntimeException : ArithmeticException, ClassCastException, NullPointException, IndexOutOfBoundException, IllegalArgumentException
    - VirtualMachineException : StackOverflowError, OutOfMemoryError
    - LinkageError : VerifyError, ClassFormatError, NoClassDefFoundError
    WhatsApp Image 2024-04-08 at 15.57.58_7140a37b.jpg

Try and Catch Block :

Try Block:

  • The try block encloses the code that may generate exceptions.
  • It is followed by one or more catch blocks.
  • If an exception occurs within the try block, the execution of the try block is halted, and the control is transferred to the corresponding catch block.

Catch Block:

  • A catch block catches and handles exceptions thrown within the associated try block.
  • Each catch block specifies the type of exception it can handle, allowing for selective exception handling.
  • If an exception of the specified type occurs, the code inside the corresponding catch block is executed.
  • If no catch block matches the thrown exception, it propagates up the call stack, potentially halting the program if unhandled.
try {
    // Code that may throw exceptions
} catch (ExceptionType1 e1) {
    // Exception handling for ExceptionType1
} catch (ExceptionType2 e2) {
    // Exception handling for ExceptionType2
} finally {
    // Optional: Code that always executes, regardless of exceptions
}

Finally Block:

  • Optionally, a finally block can be used after all catch blocks.
  • The code inside the finally block executes whether an exception occurs or not.
  • Commonly used for cleanup operations like closing files or releasing resources.

Example:

try {
    int result = 10 / 0; // This will throw an ArithmeticException
} catch (ArithmeticException e) {
    System.out.println("An error occurred: " + e.getMessage());
} finally {
    System.out.println("This code always executes.");
}
public class Example {
    public static void main(String[] args) {
        try {
            // Creating and throwing a NullPointerException with a "custom" esxception explicitly
            throw new NullPointerException("Custom NullPointerException message");
        } catch (NullPointerException e) {
            System.out.println("Caught NullPointerException: " + e.getMessage());
        }
    }
}

Difference between throw and throws :

  1. throw:

    • throw is a keyword used to explicitly throw an exception from within a method or block of code.
    • It is used when a specific condition occurs that warrants the interruption of the normal flow of execution due to an exceptional situation.
    • With throw, you can throw both built-in exceptions provided by Java (such as NullPointerException, IllegalArgumentException, etc.) and custom exceptions that you define in your code.
    • When you throw an exception, you are responsible for creating and specifying the exception object to be thrown.

    Example:

    public void method() {
        if (condition) {
            throw new SomeException("Custom message");
        }
    }
    
  2. throws:

    • throws is used in the method declaration to indicate that the method may throw certain types of exceptions during its execution.
    • It specifies the types of exceptions that a method might throw but does not actually throw them itself.
    • When you use throws, you are declaring the exceptions that can be thrown by a method, allowing the caller of the method to handle those exceptions.

    Example:

    public void method() throws SomeException {
        // Method code that may throw SomeException
    }
    

    The caller of this method would then need to handle the SomeException either by catching it or declaring it to be thrown further.

In summary, throw is used to throw an exception explicitly within a method, while throws is used to declare the types of exceptions that a method might throw, allowing the caller to handle them appropriately.

Custom Exception Message

In Java, you can create your own custom exceptions by extending the built-in Exception class or one of its subclasses. Here's how you can create and use a custom exception:

  1. Create Custom Exception Class:
    First, create a new class that extends Exception or one of its subclasses. You can define constructors and methods specific to your custom exception.

    public class CustomException extends Exception {
        public CustomException() {
            super("Custom exception message");
        }
        
        public CustomException(String message) {
            super(message);
        }
    }
    
  2. Throw Custom Exception:
    In your code, when you encounter a situation that warrants throwing your custom exception, use the throw keyword followed by an instance of your custom exception class.

    public void someMethod() throws CustomException {
        // Condition that triggers the exception
        if (condition) {
            throw new CustomException("Custom message for the exception");
        }
    }
    
  3. Handle Custom Exception:
    When calling the method that can throw your custom exception, handle it using a try-catch block.

    try {
        someObject.someMethod();
    } catch (CustomException e) {
        // Handle the custom exception
        System.out.println("Custom exception occurred: " + e.getMessage());
    }
    

Putting it all together, here's an example demonstrating the creation, throwing, and handling of a custom exception:

// CustomException.java
public class CustomException extends Exception {
    public CustomException() {
        super("Custom exception message");
    }

    public CustomException(String message) {
        super(message);
    }
}
// Example.java
public class Example {
    public void someMethod() throws CustomException {
        // Simulating a condition that triggers the custom exception
        boolean condition = true;
        if (condition) {
            throw new CustomException("Custom message for the exception");
        }
    }
}
// Main.java
public class Main {
    public static void main(String[] args) {
        Example example = new Example();
        try {
            example.someMethod();
        } catch (CustomException e) {
            System.out.println("Custom exception occurred: " + e.getMessage());
        }
    }
}

In this example, we define a custom exception CustomException and then throw and handle it in the Example and Main classes, respectively.


  • ! AI Generated :
    In Java, you can achieve multitasking, multiprocessing, and multithreading using various features of the language and the Java Runtime Environment (JRE). Let's explore each concept in the context of Java:
  1. Multitasking in Java:

    • Java supports multitasking through its multithreading capabilities. You can run multiple threads within a single Java process, allowing you to perform multiple tasks concurrently.
    • Multitasking in Java is typically achieved by creating and managing multiple threads using the Thread class or implementing the Runnable interface.
  2. Multiprocessing in Java:

    • Multiprocessing, which involves utilizing multiple CPUs or CPU cores, can be achieved indirectly in Java by running multiple Java Virtual Machine (JVM) instances on a multicore system.
    • Each JVM instance runs as a separate process and can execute Java applications independently. Therefore, if you have multiple CPU cores, you can run multiple Java processes concurrently, effectively achieving multiprocessing.
  3. Multithreading in Java:

    • Multithreading is a fundamental feature of Java, allowing you to create and manage multiple threads within a single Java process.
    • Java provides built-in support for multithreading through the Thread class and the java.util.concurrent package.
    • You can create threads by extending the Thread class or implementing the Runnable interface and then starting these threads using the start() method.
    • Java also provides high-level concurrency utilities such as ExecutorService, ThreadPoolExecutor, and ConcurrentHashMap to simplify multithreaded programming and manage thread execution, synchronization, and communication.
    • Java provides predefined APIs for multithreading, for e.g. : Thread, Runnable, ThreadGroup, Concurrency, ThreadPool etc.

Here's a simple example demonstrating multithreading in Java:

class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            try {
                Thread.sleep(1000); // Simulate some work
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        thread1.start(); // Start the first thread
        thread2.start(); // Start the second thread
    }
}

This example creates two threads (thread1 and thread2) that execute concurrently, each printing numbers from 0 to 4 with a 1-second delay between each iteration.

In summary:

  • Multitasking refers to running multiple tasks concurrently on a single CPU.
  • Multiprocessing involves using multiple CPUs or CPU cores to execute tasks concurrently.
  • Multithreading involves running multiple threads within a single process to achieve concurrency.
    • Executing multiple threads (subtasks) at a single time is known as multithreading.
    • It is used in various softwares, games, animations etc.

These concepts are fundamental to understanding how modern computer systems handle concurrent execution and optimize resource utilization.

Difference between Process and Thread in JAVA :

Creating of thread in JAVA :

There are two ways to create threads in JAVA

  1. By using a thread class
  2. By using a runnable interface.

Thread Class :

  • package.java.lang
public class Thread { 
	- constructors
	- methods
	- run()
	- start()
	- join()
	- getName() & setName()
	- .
	- .
	- .
}
  • extend to thread class
  • Override the run method, create an object of the class or start the thread.
  • Task of the thread will be written inside the run method
Class Test extends Thread
{
	@Override
	void run() // overriding the run method
	{
		// thread task
	}
	psvm()
	{
		Test t = new Test();
		t.run(); // X (crossed out) // Wrong way
		t.start();
	}
}

Starting the Thread:

  • In Java, you start a thread by calling the start() method, not the run() method directly. Invoking the run() method directly will execute the run() method in the current thread, without creating a new thread of execution.
  • Therefore, the correct way to start the thread is by calling the start() method on the Test object.
  • The start() method is called on the Test object to start the thread, which will execute the run() method asynchronously in a separate thread of execution.

Pasted image 20240423154605.png

The lifecycle of a thread in Java consists of several states through which a thread transitions during its execution. Here's a short explanation of the lifecycle stages of a thread:

  1. New:

    • When a thread is created, it is in the "New" state. In this state, the thread has been instantiated but has not yet started.
  2. Runnable:

    • After calling the start() method on a thread object, it enters the "Runnable" state. In this state, the thread is eligible to run, but the scheduler has not yet selected it to run on the CPU.
  3. Running:

    • When the scheduler selects a thread from the "Runnable" pool and allocates CPU time to it, the thread enters the "Running" state. In this state, the thread is actively executing its code.
  4. Blocked/Waiting:

    • A thread may transition to the "Blocked" or "Waiting" state due to various reasons, such as waiting for I/O operations to complete, waiting for a lock, or waiting for another thread to notify it. In these states, the thread is not actively executing but is waiting for a specific condition to be satisfied.
  5. Timed Waiting:

    • Similar to the "Blocked/Waiting" state, a thread may enter the "Timed Waiting" state when it needs to wait for a specific period. For example, when invoking Thread.sleep() or waiting for the completion of a timed operation.
  6. Terminated / Dead State:

    • A thread enters the "Terminated" state when it completes its execution or when an unhandled exception occurs within its run() method. Once a thread is terminated, it cannot be restarted or run again.
    • Once the thread enters the dead state, if a start method is called again an exception occurs because after completion of the task the thread will go in dead state and waking it up again from the dead state will show an exception.

Throughout its lifecycle, a thread may transition between these states based on various conditions and events, such as CPU scheduling decisions, I/O operations, synchronization, and signaling between threads. Proper management and understanding of thread lifecycle states are essential for developing concurrent and multithreaded applications in Java.

Runnable Interface :

  • package.java.lang
public interface Runnable
{
	- method
	- run()
}
Class Test implements Runnable
{
	public void run()
	{
		// thread task
	}
}

psvm()
{
	Test t = new Test();
}

  • implement the Runnable interface

  • Override the run method

  • Create an object of user defined class

  • Create an object of thread class and pass the parameter in the constructor

  • start the thread

  • ! AI Generated content starts : Fixing the code block above.
    To fix the provided code, we need to complete the psvm() method by creating a Thread object and starting it to execute the run() method defined in the Test class, which implements the Runnable interface. Here's the corrected version:

class Test implements Runnable {
    public void run() {
        // Thread task
        System.out.println("Thread task is running");
    }

    public static void main(String[] args) {
        // Create an instance of Test
        Test t = new Test();
        
        // Create a Thread object and pass the Test instance to its constructor
        Thread thread = new Thread(t);
        
        // Start the thread
        thread.start();
    }
}

In this corrected version:

  • We have implemented the run() method in the Test class to define the task that the thread will execute.

  • In the main() method, we create an instance of Test and a Thread object, passing the Test instance to the Thread constructor.

  • Finally, we start the thread using the start() method. This will execute the run() method of the Test class concurrently with the main thread, printing "Thread task is running" to the console.

  • ! AI Generated content ends

Info

Using Runnable interface is preferred

  1. Better Separation of Concerns: When a class extends the Thread class, it becomes tightly coupled with the threading mechanism, which limits its flexibility. On the other hand, implementing the Runnable interface allows the class to focus on its primary responsibility while leaving the threading concerns to be handled separately. This promotes cleaner and more modular code.
  2. Inheritance Flexibility: Java supports single inheritance, meaning a class can only extend one superclass. By implementing Runnable, your class is free to extend another class if needed, allowing for more flexible class hierarchies.
    class A extends B extends thread : Not Possible
    Class A extends B implements Runnable

Thread Execution Patterns in Java

  • Performing single task from a single thread
  • Performing single task from multiple thread
  • Performing multiple tasks from single thread
  • Performing multiple tasks from multiple threads

Performing single task from a single thread

  • Seen above already

  • ! AI GENERATED :
    Here's an example demonstrating performing a single task from a single thread in Java:

public class SingleThreadExample {
    public static void main(String[] args) {
        // Create a task to perform
        Runnable task = () -> {
            // Perform the task
            System.out.println("Task is being performed by Thread: " + Thread.currentThread().getName());
        };

        // Create a thread and execute the task
        Thread thread = new Thread(task);
        thread.start();
    }
}

Explanation:

  • We define a simple task using a Runnable lambda expression.
  • We create a new Thread object and pass our task to its constructor.
  • We start the thread using the start() method. This initiates the execution of the task in a new thread.

When you run this code, it will output something like:

Task is being performed by Thread: Thread-0

This indicates that the task is being performed by a single thread (in this case, Thread-0).

  • ! AI Gen ends

Performing single task from a multiple thread

AI

Sure, here's an example demonstrating performing a single task from multiple threads by extending the Thread class:

public class MultipleThreadsExample extends Thread {
    public void run() {
        // Perform the task
        System.out.println("Task is being performed by Thread: " + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // Create multiple threads and execute the task
        for (int i = 0; i < 5; i++) {
            MultipleThreadsExample thread = new MultipleThreadsExample();
            thread.start();
        }
    }
}

Explanation:

  • We create a new class MultipleThreadsExample that extends the Thread class.
  • We override the run() method to define the task that each thread will perform.
  • Inside the main method, we create a loop to create multiple instances of MultipleThreadsExample and start each thread.

When you run this code, you'll see output similar to the following (order may vary):

Task is being performed by Thread: Thread-0
Task is being performed by Thread: Thread-1
Task is being performed by Thread: Thread-2
Task is being performed by Thread: Thread-3
Task is being performed by Thread: Thread-4

Each thread is executing the same task concurrently, as in the previous example. However, extending the Thread class limits the flexibility of your class and is generally not recommended because it does not follow the principle of favoring composition over inheritance. Using Runnable is typically a better approach for creating threads in Java.

AI Ends

Performing multiple tasks from single thread :

  • Not possible to perform Multiple tasks from a single thread at the same time

    AI

Performing multiple tasks from a single thread by extending the Thread class is not a typical practice because a single thread usually handles one task at a time. However, if you still want an example where a single thread performs multiple tasks sequentially, here it is:

public class SingleThreadMultipleTasks extends Thread {
    
    public void run() {
        task1();
        task2();
        task3();
    }

    private void task1() {
        System.out.println("Task 1 is being performed by Thread: " + Thread.currentThread().getName());
    }

    private void task2() {
        System.out.println("Task 2 is being performed by Thread: " + Thread.currentThread().getName());
    }

    private void task3() {
        System.out.println("Task 3 is being performed by Thread: " + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // Create a single thread to perform multiple tasks
        SingleThreadMultipleTasks thread = new SingleThreadMultipleTasks();
        thread.start();
    }
}

Explanation:

  • The SingleThreadMultipleTasks class extends the Thread class.
  • Inside the run() method, which is overridden from the Thread class, we call three different private methods (task1(), task2(), and task3()), each representing a separate task.
  • Each task prints a message indicating its execution along with the name of the current thread.
  • In the main() method, we create a single instance of SingleThreadMultipleTasks and start the thread.

When you run this code, you'll see output similar to the following:

Task 1 is being performed by Thread: Thread-0
Task 2 is being performed by Thread: Thread-0
Task 3 is being performed by Thread: Thread-0

Keep in mind that while this example demonstrates executing multiple tasks from a single thread, it's generally more efficient to use multiple threads when dealing with multiple tasks to leverage parallelism and better utilize system resources.

AI Ends

Performing multiple tasks from multiple threads:

AI

Certainly! Here's an example illustrating performing multiple tasks from multiple threads by extending the Thread class:

public class MultipleTasksMultipleThreads extends Thread {
    private String taskName;

    public MultipleTasksMultipleThreads(String taskName) {
        this.taskName = taskName;
    }

    public void run() {
        // Perform the respective task based on taskName
        if (taskName.equals("Task1")) {
            task1();
        } else if (taskName.equals("Task2")) {
            task2();
        } else {
            System.out.println("Invalid task name");
        }
    }

    private void task1() {
        System.out.println("Task 1 is being performed by Thread: " + Thread.currentThread().getName());
    }

    private void task2() {
        System.out.println("Task 2 is being performed by Thread: " + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        // Create multiple threads for performing multiple tasks
        MultipleTasksMultipleThreads thread1 = new MultipleTasksMultipleThreads("Task1");
        MultipleTasksMultipleThreads thread2 = new MultipleTasksMultipleThreads("Task2");

        // Start the threads
        thread1.start();
        thread2.start();
    }
}

Explanation:

  • The MultipleTasksMultipleThreads class extends the Thread class.
  • It takes a taskName parameter in its constructor to identify which task the thread should perform.
  • Inside the run() method, it invokes the appropriate task method (task1() or task2()) based on the provided taskName.
  • The task1() and task2() methods contain the implementations of the respective tasks.
  • In the main() method, we create multiple instances of MultipleTasksMultipleThreads, each representing a different task, and start them as separate threads.

When you run this code, you'll see output similar to the following:

Task 1 is being performed by Thread: Thread-0
Task 2 is being performed by Thread: Thread-1

Each task is executed by a separate thread concurrently, demonstrating the execution of multiple tasks from multiple threads.

AI Gen


  • Thread()
  • Thread(Runnable Target)
  • Thread(String name)
  • Thread(ThreadGroup tg, Runnable target)
  • Thread(ThreadGroup tg, String name)
  • Thread(ThreadGroup tg, Runnable target, String name)
  • Thread(ThreadGroup tg, Runnable target, String name, Long stackSize)

ThreadClass Methods :

Categories :

  1. Basic Methods : Run Method, Start Method, CurrentThread Method, IsAlive Method
  2. Naming Related Methods : getName, setName
  3. Daemon Thread Related Methods : isDaemon, setDaemon(boolean b)
  4. Priority Related Methods : getPriority, setPriority(int)
  5. Thread Execution Prevention Method : Sleep, yield, join
  6. Interrupt related method : Interrupt, isInterrupted, interrupted
  7. Inter Thread Communication Related Methods : Break, Notify, NotifyAll : These are present in the object class
Class Test
{
	psvm() // Main Thread
	{
		sout("hello");
		Thead.currentThread().setName("xyz");
		sout(Thread.currentThread().getName());
		sout(10/0); // will print an error saying something like "Error in `thread_name`"
	}
}

currentThread() and getName():

  • CurrentThread() provides a reference to the current thread
  • Thead.CurrentThread().setName("xyz"); By default the name provided will be : DIY
class Test extends Thread {
    public void run() {
        System.out.println("Thread Task");
        System.out.println(Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.start();
        
        System.out.println(Thread.currentThread().getName());
    }
}

  • Output :
main
Thread Task
Thread-0
  • Here in total there will be two threads : one thread will be the main thread and the other will be the thread-0 which we have created using Test t = new Test(); implementing the run method

isAlive() :

class Test extends Thread {
    public void run() {
        System.out.println("Thread Task");
        System.out.println(Thread.currentThread().getName() + " is alive : " + Thread.currentThread().isAlive());

    }

    public static void main(String[] args) {
        Test t = new Test();
        t.start();
        
        System.out.println(Thread.currentThread().getName());
        System.out.println("t is alive : " + t.isAlive());

    }
}
  • Output :
main
Thread Task
t is alive : true
Thread-0 is alive : true

Last class topics :

Thread class naming : getName(), setName()

Daemon Thread runs in the background of another thread, it provides service to the thread.

  • Example : Garbage Collector, Finalizer, Attach Listeners, Signal Dispatchers, etc.
  • isDaemon, setDaemon
    Example :
Class Test extends Thread
{
	public void run()
	{
		// thread basic
	}
	psvm() // main thread
	{
		Test t = new Test();
		t.setDaemon(true);
		t.start();
	}
}
  • We have to create Daemon Thread before starting the thread, if we create a daemon thread after starting the thread it will throw a runtime exception i.e. Illegal Thread State Exception (Illegal Thread State Exception padh lena, exam me aa sakta hai)
  • We cannot create main thread as the Daemon thread.
  • The life of Daemon thread depends on the life of thread on the background of which the Daemon thread is running
  • The Daemon thread inherits the properties from the parent thread.
  • When all the normal thread goes into the dead state then JVM shuts down. But if Daemon thread goes into the dead state then JVM does not get shut down.
  • The priority of Daemon thread is kept at low priority, but we can change the priority according to our needs.
  • Default priority is 5. Use getPriority to check the priority.

Thread Execution Methods :

  • Sleep Method : Argument me ms me values dalenge.
    Interrupt related methods :
  • It used to interrupt an executing thread.
  • Interrupt() method will only work when the thread is in waiting or sleeping state. If it is not in sleeping / waiting thread then calling Interrupt() method will perform normal behavior.
  • When we use the Interrupt() method the exception associated with it is the Interrupted Exception.
Class Test extends Thread
{
	public void run()
	{
		try
		{
			for(int i=1; i<=5; i++)
				sout(i);
		}
		catch(Exception e)
		{
			sout("Exception")
		}
	}

	psvm()
	{
		Test t = new Test();
		t.start();
	}
}