[go: up one dir, main page]

0% found this document useful (0 votes)
0 views202 pages

Core Java Merged

Uploaded by

riteshbarik3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views202 pages

Core Java Merged

Uploaded by

riteshbarik3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 202

Introduction to JAVA

●​ Java is a programming language using which either we are going to develop a software
or test a software.
●​ The code we are writing in our system is called Java source code, which is a high-level
language or human understandable language. This is not understandable by our system.
●​ To make this code understandable our developer made two software (translators).
They are -
○​ compilers
○​ JVM (Java virtual machine)

Compiler-
●​ The compiler is a software that compiles our Java code and then forwards it to JVM by
converting to JVM understandable language which is called byte code.

JVM-
●​ JVM is software that receives bytecode from the compiler and processes it, then converts
it to system-understandable binary code and transfers it to the system.
●​ At the end the system processes the binary code and gives us output.
IDE-
●​ To perform this operation we need a platform or environment called IDE, which is
software.
●​ IDE stands for Integrated Development Environment. It will provide the programmer a
platform to perform java related operations.
●​ Some of the IDE's are
○​ Editors
■​ Notepad
■​ Notepad++
■​ EditPlus
○​ Advanced tools
■​ Eclipse
■​ VS Code
■​ IntelliJ
■​ Sublime
●​ The word "Integrated" means combining multiple parts into a unified whole to work
together efficiently.
●​ In the context of IDE (Integrated Development Environment), "Integrated" refers to
multiple tools (editor, compiler, debugger, etc.) being combined into one software for
easier development.

JDK-
●​ To perform Java-related operations in IDE another tool we need is called JDK.
●​ If we tell IDE as a platform JDK will be the ingredients to perform operations.
●​ JDK stands for Java Development Kit. It will provide all Java-related tools or kits to
perform JAVA operations.

Major Components Of Java-


●​ The major components of JAVA are
○​ Class (similar to house)
○​ Method (similar to rooms)
○​ Variables (similar to cupboards)
○​ Objects (similar to members of the house)

Basic Syntax-
class Hello
{
public static void main(String[] args)
{

System.out.println("Hello");

}
}

●​ The curly braces start from class Hello to end called a class of the program.
●​ The curly braces start from public static void main(String[] args) and end after
system.out.println("Hello"); is called as method.

Steps need to follow to get the output -


●​ After writing the program, we need to follow certain steps to get the output.
○​ Save the program—
■​ To save the program, it is recommended that we create a folder where we
will save all our Java source code using the .java extension.
○​ compile -
■​ After saving the code, we need to compile it. To compile it, we have to give
the command to the compiler in cmd (command prompt). A .class file will
be generated after successful compilation.
■​ Command for the JVM: javac filename.java.
○​ run/execute -
■​ After successful compilation of the code, we need to execute it, for which
the JVM is responsible and as it is also a software, we need to give a
command to it in the same command prompt.
■​ command for the JVM : java className

Write a program to print our name 5 times.


class Hello {
public static void main(String[] args) {
System.out.println("Tanmoy");
System.out.println("Tanmoy");
System.out.println("Tanmoy");
System.out.println("Tanmoy");
System.out.println("Tanmoy");
}
}

Identifier-
●​ Identifiers are the names given in a Java program for identification purposes.
●​ We will identify classes, methods, and variables
●​ example -
○​ class(predefined) - String, System
○​ class(User defined) - Hello
○​ methods(predefined) - main(), println()
○​ variables(predefined) - args, out
Rules to follow for naming an identifier-
●​ Rule 1-
○​ Allowed characters-
■​ A-Z upper case
■​ a-z lower case
■​ 0 - 9 digits (can't use in the beginning)
■​ $(dollar), _(underscore) special characters/numbers
○​ ex- class paneer, class $paneer, class _paneer, class PANEER, class Paneer,
class paneer65
●​ Rule 2-
○​ Digits can't be at the beginning of the identifier
○​ ex-class 99North {}
●​ Rule 3 -
○​ We can't use a reserved keyword for naming purposes
○​ static, public, void, if, etc. are reserved keywords
○​ ex - class static, class public, class void, class if

●​ Rule 4 -
○​ Identifiers are case sensitive.
■​ Ex -
■​ Class if {
} // invalid

■​ Class If {
} //valid
○​ Unfortunately, we won't be able to use a single underscore for naming purposes
according to the latest Java 9.
■​ Ex -
■​ Class _{
} //invalid
■​ Class __{
} //valid

Why are identifiers case sensitive?


●​ Identifiers are case sensitive because the uppercase A-Z and their corresponding
lowercase have different ASCII values.

What are ASCII values?


●​ ASCII stands for American Standard Code for Information Interchange, and these codes
will be used for conversion purposes.

Data Types -
●​ Every data has a type, and that type is known as a data type.
●​ The data type will define which data type a variable can store or hold in its memory
location.
●​ There are two types of data types-
○​ primitive
○​ non primitive

Primitive -
●​ These are the datatypes that will store only values.

Types Keyword Size Range

integer/integral byte 1 byte -128 to 127

short 2 byte -32,768 to 32,767

int 4 byte -2,147,483,648 to


2,147,483,647

long 8 byte -9,223,372,036,854,775,808


to
9,223,372,036,854,775,807

decimal/floating float 4 byte upto 7 decimal digits

double 8 byte upto 16 decimal digits

characters char 2 byte Characters representation of


ASCII values 0 to 255

Bool (true, false) boolean 1 byte true, false

Examples of primitive data types


class Happy
{
​ public static void main(String[] args) {
​ ​ byte a = 127; // range -128 to 127
​ ​ short b = 1234;
​ ​ int c =10;
​ ​ long d = 12L; //denoted as L or l
​ ​ float e = 1.1F; //denoted as F or f
​ ​ double f = 1.1; //denoted as simple or D or d
​ ​ char g = 'a';
​ ​ boolean h = true;
​ }
}

Nonprimitive -
●​ These are data types that will store only objects.
●​ All the Java classes are considered non primitive data types.
●​ ex-
○​ Predefined - String, System, StringBuffer, StringBuilder, etc.
○​ User defined - Hello, My class, Java...etc.

Object -
●​ Object is a real time entity, which will have some state and behavior.
●​ The state is represented by variables, and behavior is represented by methods.
●​ We will always create an object of a class only.
Syntax to create an object-
class Dog
{
public static void main(String[] args) {
Dog d = new Dog();
}
}
○​ d is the reference variable
○​ new is a keyword
○​ Dog() is a constructor caller

●​ We can create more than one object of a class, but we need to make sure that the
reference variable names are different.

Type casting -
●​ Converting one type of data value into a different kind of datatype is known as type
casting.
●​ This type of casting is known as primitive type casting, as it applies to all primitive data
types except Boolean.

●​ There are two types of type casting-


○​ Implicit type casting
○​ Explicit type casting

Implicit type casting-


●​ Converting a smaller data value into a bigger data type is known as implicit type casting.
●​ byte->short->int->long->float->double

example -
class implicit
{
​ public static void main(String[] args)
​ {
​ ​ int x = 12;
​ ​ double d = x;
​ ​ System.out.println(x); //12
​ ​ System.out.println(d); //12.0
​ }
}

●​ This type casting is done automatically by the compiler.


●​ There will be no data loss.
●​ The other names of implicit type casting are upcasting and widening.

example -
class implicit1
{
​ public static void main(String[] args)
​ {
​ ​ char myChar = 'a';
​ ​ double d = myChar;
​ ​ System.out.println(myChar); // a
​ ​ System.out.println(d); //97.0
​ }
}

Explicit type casting -


●​ Converting a bigger data value into a smaller data type is known as explicit type casting.
example -
class explicit
{
​ public static void main(String[] args)
​ {
​ ​ double d = 12.12;
​ ​ int a = (int)d;
​ ​ System.out.println(d); //12.12
​ ​ System.out.println(a); //12
​ }
}
●​ This type conversion needs to be done by the programmer explicitly.
●​ There will be a loss of data.
●​ This typecasting is otherwise known as downcasting and narrowing
example -
class explicit1
{
​ public static void main(String[] args)
​ {
​ ​ double d = 97.9;
​ ​ char a = (char)d;
​ ​ System.out.println(d); //97.9
​ ​ System.out.println(a); //a
​ }
}

How can an 8-byte long value get stored in 4-byte float values
implicitly?
●​ The internal volume of the float data type is much larger than an 8-byte long data type.
example-
class longToFloat
{
​ public static void main(String[] args)
​ {
​ ​ long d = 9223372036854775807L;
​ ​ float a = d;
​ ​ System.out.println(d); //9223372036854775807
​ ​ System.out.println(a); //9.223372E18
​ }
}

Variable -
●​ The variable is the name of a memory location used to store some values.
●​ Variables have two parts-
○​ declaration - int num1;
○​ definition - num1 = 10;
●​ The variable can be declared and defined in a single line
○​ int num1 = 10;

●​ There are three types of variables in Java.


○​ non-static
○​ static
○​ Local
●​ The categorization of variable has been done on the basis of how we declaring the
variable and where we are declaring

Non-static -
●​ If the variable's value varies from object to object, then it is known as a non-static or
instance variable.
●​ The non-static variable can be declared inside the class, but outside any method, block,
or constructor.
example -
class nonStatic
{
​ int num1 = 10;
​ public static void main(String[] args)
​ {
​ ​ //System.out.println("Hello World!");
​ }
​ int num2 = 20;
}

●​ The non-static variable is stored in heap memory.


●​ The non-static variable is getting allocated at the time of object creation.
●​ There is only one way to access the non-static variable inside any static area, that is by
using the object.
●​ But if we are trying to access it inside any static area directly then we will get a
compile-time error.
example -
class nonStaticAccess
{
​ int num1 = 10;
​ public static void main(String[] args)
​ {
​ ​ System.out.println(num1);
​ }
​ int num2 = 20;
}
example - of creating an object and accessing a variable
class nonStaticAccessObj
{
​ int num1 = 10;
​ public static void main(String[] args)
​ {
​ ​ nonStaticAccessObj t1 = new nonStaticAccessObj();
​ ​ System.out.println(t1.num1);
​ }
​ int num2 = 20;
}
●​ It is not mandatory to initialize the non-static variable; if we are not initializing, then JVM is
responsible for providing the default value according to the data type.
What is the Default value?
These are values which will be assigned according to the data type to a variable when a
programmer is not initializing.
example-
class nonStaticDefault
{
​ byte myByte;
​ short myShort;
​ int num1;
​ long myLong;
​ float myFloat;
​ double myDouble;
​ char myChar;
​ boolean myBool;
​ String myString;
nonStaticDefault obj;
System obj2;

​ public static void main(String[] args)
​ {
​ ​ nonStaticDefault t1 = new nonStaticDefault();
​ ​ System.out.println("_______Primitive type_______");
​ ​ System.out.println("Default byte: " + t1.myByte);
​ ​ System.out.println("Default short: " + t1.myShort);
​ ​ System.out.println("Default int: " + t1.num1);
​ ​ System.out.println("Default long: " + t1.myLong);
​ ​ System.out.println("Default float: " + t1.myFloat);
​ ​ System.out.println("Default double: " + t1.myDouble);
​ ​ System.out.println("Default char: " + t1.myChar);
​ ​ System.out.println("Default boolean: " + t1.myBool);
​ ​ System.out.println("_______Non Primitive type_______");
​ ​ System.out.println("Default string: " + t1.myString);
​ ​ System.out.println("Default obj: " + t1.obj);
​ ​ System.out.println("Default obj2: " + t1.obj2);
​ }
}
●​ The non-static variable shares a different copy with different objects
example -
class NonstaticObjToobj
{
​ int x = 10;
​ public static void main(String[] args)
​ {
​ ​ NonstaticObjToobj t1 = new NonstaticObjToobj();
​ ​ NonstaticObjToobj t2 = new NonstaticObjToobj();
​ ​
​ ​ System.out.println("Before changing x of t1: "+t1.x);
​ ​ t1.x = 20;
​ ​ System.out.println("After changing x of t1: "+t1.x);
​ ​ System.out.println("Value of x of t2: "+t2.x);
​ }
}

Static variable-
●​ If the variable's value does not vary from object to object, then it is called a static variable.
●​ A static variable can be declared inside the class but outside the method, blocks, or
constructor by using the static keyword.
●​ A static variable can be stored in the method area/class area of the JVM. After getting
updated on Java 8 it is getting allocated in the heap area.
●​ A static variable is allocated at the time of class loading.
●​ There are three ways to access the static variable inside any static area.
○​ by directly
○​ by class name
○​ by object

Example -
class StaticEx {
static int x = 10;
public static void main(String[]args) {
System.out.println(x);//by directly
System.out.println(StaticEx.x);//by class name
StaticEx obj = new StaticEx();
System.out.println(obj.x);//by object

}
}
●​ It is not mandatory to initialize a static variable, if we are not initializing then the JVM will
provide a default value to the variable.

class StaticDefault {
static int x;
public static void main(String[]args) {
System.out.println(x);//by directly

}
}

●​ The static variable shares the same copy with every object.
example -
class StaticCopy {
static int x = 10;
public static void main(String[]args) {
StaticCopy obj1 = new StaticCopy();
StaticCopy obj2 = new StaticCopy();
System.out.println(obj1.x);
System.out.println(obj2.x);
obj1.x = 200;
System.out.println(obj1.x);
System.out.println(obj2.x);
}
}
●​ Two static variable name cant be same and static and non static variable name cant be
same too.
Qst 1 -
What is the difference between static and non static variables?

Static Non static

●​ A static variable does not vary from ●​ Static variables vary from object to
object to object. object.
●​ A single copy of a static variable gets ●​ Multiple copies of a non-static variable
shared among multiple objects. get shared among multiple objects.
●​ A static variable gets allocated during ●​ Non-static variable gets allocated at
class loading in the metaspace. the time of object creation inside the
object in heap memory.
●​ The static variable needs to be ●​ There is no specific keyword needed
declared with the static keyword, ex, to declare non-static keywords.
static int x;
●​ A Static variable can be accessed in ●​ The non-static variable can be
three ways: by directly, by class name, accessed only by the object name.
and by object.
Qst 2 -
Can a static variable and non static variable have the same name?
A static variable and a non-static variable can't have the same name in the same class. This is
because we can access both static and non-static variables using reference (by creating objects)
and the compiler will not be able to decide whether we mean to call the static variable or
non-static variable.
Example -
class StaticNonStaticConfusion
{
​ int x = 20;
​ static int x = 10; //error: variable x is already defined in class StaticNonStaticConfusion
static int x = 10;
​ public static void main(String[] args)
​ {
​ ​ StaticNonStaticConfusion obj = new StaticNonStaticConfusion();
​ ​ System.out.println(obj.x);​ //here compiler get confused which variable we are
calling​ ​ ​ ​ ​ ​ ​ ​ ​
​ }
}

Problem 1 - Predict Output


class example1
{
​ int x = 10;
​ static int y = 20;

​ public static void main(String[] args)
​ {
​ ​ example1 t1 = new example1();
​ ​ example1 t2 = new example1();
​ ​ System.out.println(t1.x);
​ ​ System.out.println(t1.y);
​ ​ System.out.println(t2.x);
​ ​ System.out.println(t2.y);
​ ​ t1.x = 111;
​ ​ t2.y = 222;
​ ​ System.out.println(t1.x);
​ ​ System.out.println(t1.y);
​ ​ System.out.println(t2.x);
​ ​ System.out.println(t2.y);
​ ​
​ ​
​ }
}
o/p -
10
20
10
20
111
222
10
222

Problem 2 - Predict output


class example2
{
​ int x = 10;
​ int y = 20;

​ public static void main(String[] args)
​ {
​ ​ example2 t1 = new example2();
​ ​ example2 t2 = new example2();
​ ​ System.out.println(t1.x);
​ ​ System.out.println(t1.y);
​ ​ System.out.println(t2.x);
​ ​ System.out.println(t2.y);
​ ​ t1.x = 111;
​ ​ t2.y = 222;
​ ​ System.out.println(t1.x);
​ ​ System.out.println(t1.y);
​ ​ System.out.println(t2.x);
​ ​ System.out.println(t2.y);
​ ​
​ ​
​ }
}
o/p -
10
20
10
20
111
20
10
222

Problem 3 -
Write a program to add two numbers by using a non-static variable and store it in another
variable and print it.
class Sum
{
​ int num1 = 10;
​ int num2 = 20;
​ int sumNum = num1 + num2;
​ public static void main(String[] args)
​ {
​ ​ Sum obj = new Sum();
​ ​ System.out.println(obj.sumNum);
​ }
}
Ans 2-
class SumW2
{
​ int num1 = 10;
​ int num2 = 20;
​ int sumNum;
​ public static void main(String[] args)
​ {
​ ​ SumW2 obj = new SumW2();
​ ​ obj.sumNum = obj.num1 + obj.num2;
​ ​ System.out.println(obj.sumNum);
​ }
}

Problem 4 -
Write a program to swap two numbers by using non-static variables.
Ans -
class Swap
{
​ int num1 = 10;
​ int num2 = 20;
​ int temp;
​ public static void main(String[] args)
​ {
​ ​ Swap obj = new Swap();
​ ​ System.out.println("Before swap:\n"+ "num1: " + obj.num1 + " num2: " + obj.num2);
​ ​ obj.temp = obj.num1;
​ ​ obj.num1 = obj.num2;
​ ​ obj.num2 = obj.temp;
​ ​ System.out.println("After swap:\n"+ "num1: " + obj.num1 + " num2: " + obj.num2);
​ }
}
o/p -
Before swap:
num1: 10 num2: 20
After swap:
num1: 20 num2: 10
Qst 3-
What is variable?
The variable is the name of a memory location or reference to a memory location used to store
some values.
Qst 4-
What is the purpose of variables?
Purpose of variables to store data. Or refer to a storage which stores data. So that we can
perform different operations based on the data.
It varies.
Qst 5-
What are the different parts of a variable?
Declaration
Int x;
Initialization -
X = 10;
Qst 6-
What are the different types of variables?
Three types of variables are there:
Non static / instance variable
Static variable
Local variable
Local variable -
●​ Local variables are known as temporary variables.
Declaration of local variable -
●​ The local variables are declared inside the class as well as inside the method, block, and
constructor.
●​ Example -
class Local{
public static void main(String[] args) {
int x;
}
}

How to access a local variable -


●​ There is only one way in which we can access a local variable, and that is directly.

class Local{
public static void main(String[] args) {
int x = 10; //local variable
System.out.println(x); //Accessing directly
}
}

Storage area-
●​ The local variables are stored in stack memory.
Memory allocation -
●​ The memory of the local variable will be allocated at the time of the execution of the
method where it has been declared.
Why are local variables known as temporary variables?
●​ Local variables are known as temporary variables because after the execution of the
method, in which it has been declared JVM will destroy the memory allocation.
class Local1 {
public static void main(String[] args) {
m1();
System.out.println(x);//error: cannot find symbol
}
public static void m1() {
int x = 10;
}
}
●​ Initializing a local variable is mandatory before using it

class Local2 {
public static void main(String[] args) {
int x;
System.out.println(x);//error: variable x might not have been
initialized
}
}

Correct way-

class Local3 {
public static void main(String[] args) {
int x;
System.out.println("Hello");
x = 20;//initialize x before printing
System.out.println(x);//20
}
}

“final” is the only modifier that applies to local variables.

●​ Non-static variable and local variable names can be the same, while accessing them, we
will not get any compilation error because both have different ways of accessing.

class Nonlocal {
boolean x = true;
public static void main(String[] args) {
int x = 12;
System.out.println(x); //accessing local variable
Nonlocal obj = new Nonlocal();
System.out.println(obj.x);//accessing non static variable
}
}

●​ Local variable and static variable names can be the same, but while accessing directly, the
priority will be given to the local variable.

class Stalocal {
static int x = 12;
public static void main(String[] args) {
int x = 10;
System.out.println(x); //10 //priority will be given to local
variable
}
}

Operator -
●​ Operators are the special symbols used in Java for performing operations on the
operands.
●​ Based on the number of operands, we will use it to perform an operation with an operator.
●​ There are three types of operators -
○​ Unary operator -
■​ Increment operator(++)
■​ Decrement operator(--)
■​ Bitwise complement(~)
■​ Boolean complement(!)
○​ Binary operators -
■​ Arithmetic operator(+,-,*,/,%)
●​ String concatenation
■​ Assignment operator(=)
■​ Relational operator(<,>)
■​ Equality operator(==)
■​ Bitwise operator(&,|,^)
■​ Logical operator(&&,||)
○​ Ternary operator -
■​ Conditional operator (?,:)

Unary operator -
●​ Whenever an operator requires only one operand to perform an operation then that type
of operator is known as unary operator.

Increment operator -
●​ It is a type of operator where the JVM will add 1 to the value of the variable.
●​ There are two types of increment operations-
○​ Pre increment (++x)
○​ Post increment (x++)

Pre increment -
●​ In pre-increment, first the value will increase, then after it will be assigned.
●​ Example -

class preincrement {
public static void main(String[] args) {
int x = 10;
System.out.println(x);//10
int y = ++x;
System.out.println(x);//11
System.out.println(y);//11
}
}

Steps -
●​ increase(x value increase from 10 to 11)
●​ assign(++x get assigned with 11)
●​ Initialize (y get initialized with 11)

Post increment -
●​ In post increment, first the value will be assigned, then after it will be increased.
●​ Example -

class Postincrement {
public static void main(String[] args) {
int x = 10;
System.out.println(x);//10
int y = x++;
System.out.println(x);//11
System.out.println(y);//10
}
}

Steps -
●​ Assign (x++ get assigned with 10)
●​ Increase (x value increases from 10 to 11)
●​ Initialize (y gets initialized with 10 as x++ is 10)

Decrement operator -
●​ It is a type of operator that will decrease the value of a variable by subtracting 1 from it.
●​ There are two types of decrement operators -
○​ Pre decrement (--x)
○​ Post decrement (x–)

Pre-decrement -
●​ In pre-decrement, first the value will be decreased, then it will be assigned.
Example -

class Predecrement {
public static void main(String[] args) {
int x = 14;
System.out.println(x);//14
int y = --x;
System.out.println(x);//13
System.out.println(y);//13
}
}

Steps -
●​ Decrease (x value decreases from 14 to 13)
●​ assign(--x get assigned with 13)
●​ Initialize (y get initialized with 13)

Post decrement -
●​ In post-decrement, first the value will be assigned, then it will be decreased.
●​ Example -

class Postdecrement {
public static void main(String[] args) {
int x = 14;
System.out.println(x);//14
int y = x--;
System.out.println(x);//13
System.out.println(y);//14
}
}

Problem 5 - Predict output


class IncDecMis {
public static void main(String[] args) {
int x = 10;
int y = ++x + ++x;
System.out.println(x);//12
System.out.println(y);//23
}
}

Problem 6 - Predict output


class IncDecMis2 {
public static void main(String[] args) {
int x = 10;
int y = ++x + ++x - x++ * x++;
System.out.println(x);//14
System.out.println(y);//-133
}
}

Problem 7 - Predict output


class IncDecMis3 {
public static void main(String[] args) {
int x = 11;
int y = ++x + ++x;
System.out.println(x);//13
System.out.println(y);//25
int z = y++ - ++x;
System.out.println(x);//14
System.out.println(y);//26
System.out.println(z);//11
}
}

Problem 8 - Predict output


class IncDecMis4 {
public static void main(String[] args) {
int x = 14;
x = ++x;
System.out.println(x); //15
x = x++;
System.out.println(x);//15
x = x++;
System.out.println(x);//15
x = x++;
System.out.println(x);//15
}
}

Self-assignment variable -
●​ Self-assignment variable is a condition where the JVM is performing an operation and
assigns the value to the variable.
●​ When having operation with the same variable, JVM creates a cache memory and stores
the main memory value into it. Again cache transfers the value to main before finishing
execution of the class.
●​ example-
○​ x = 14;
○​ In the main memory for x, 14 will be assigned.
○​ Then x = ++x;
○​ X will increment to 15 as x = 15 so a cache memory will be created and stored the
value 15 in it. Before finishing the execution the value assigned to the main
memory of x.
○​ Similarly, x = x++.
○​ Here again, a cache memory will create a value of x, 15, and get copied to it. In
main memory, the value will change to 16. Before finishing the execution, the
cache memory value gets copied to main memory. Means 15 will get copied to
main memory.
Rules for increment and Decrement operator -
●​ These operators apply to all the primitive data types except Boolean.
●​ We can't use these operators with any constant value -
Example -

class ConstantInc {
public static void main(String[] args) {
int x = 1;
int y = ++1;
System.out.println(x);
System.out.println(y);

}
}
/*
error: unexpected type
int y = ++1;
^
required: variable
found: value
*/

●​ We can't use these operators more than once with a variable because after the first
operation, it will become a constant value and we can't use these operations with a
constant value.
●​ It's because Java does not allow nested increments on a non-variable result.
●​ ++x returns a value, not a variable (an r-value), and we can’t apply ++ to an r-value.
●​ Example -

class Morethanoneince {
public static void main(String[] args) {
int x = 1;
int y = ++(++x);
System.out.println(x);
System.out.println(y);
}
}
/*
error: unexpected type
int y = ++(++x);
^
required: variable
found: value
*/

Bitwise complement-
●​ In the bitwise complement JVM will first add 1 to the value and then change the sign.
●​ (Internally The bitwise complement ~ inverts all the bits.)
Example -

class Bitwise {
public static void main(String[] args) {
int x = 10;
int y = ~x;
System.out.println(y);//-11
}
}

Boolean complement -
●​ In Boolean complement, it will just reverse the value from true to false and vice versa.
Example -

class Boolean {
public static void main(String[] args) {
boolean x = true;
boolean y = !x;
System.out.println(y);//false
}
}
Binary operator -
●​ Whenever we are performing an operation by using two operands, the operator used is
known as a binary operator.

Arithmetic operator -
●​ Operators performing arithmetic operations are known as arithmetic operators.
Example -

class Arithmatic {
public static void main(String[] args) {
int a = 20;
int b = 4;
System.out.println(a + b);//24
System.out.println(a - b);//16
System.out.println(a * b);//80
System.out.println(a / b);//5
System.out.println(a % b);//0
}
}

String concatenation -
●​ String concatenation is the process of merging two operands.
Example -
class Stringconcat {
public static void main(String[] args) {
String s1 = "paneer" + "tikka";
System.out.println(s1);//paneertikka
}
}

●​ To perform string concatenation between two operands, both can be string values, or one
of the operands must be a string value.
Example -

class Stringconcat2 {
public static void main(String[] args) {
String s = "paneer" + 65;//
String s1 = 5 + "star";
String s3 = "robot" + 2.0;
String s4 = "Char" + 'c';
String s5 = "You" + true;
System.out.println(s);//paneer65
System.out.println(s1);//5star
System.out.println(s3);//robot2.0
System.out.println(s4);//Charc
System.out.println(s5);//Youtrue
}
}

●​ The "+" operator is known as the overloaded operator in Java. Because it can perform
addition as well as concatenation in the same statement.

class Concatenation2 {
public static void main(String[] args) {
String s = 10 + 20 + "Hello" + 10 + 20;
System.out.println(s); //30Hello1020
}
}

class Concatenation3 {
public static void main(String[] args) {
String s = 10 + 20 + "" + 10 + 20;
System.out.println(s); //301020
}
}

class Concatenation4 {
public static void main(String[] args) {
String s = 10 + "10";
System.out.println(s);//1010
}
}

●​ To make our output more informative, we will use string concatenation.


class Concatenation5 {
public static void main(String[] args) {
int a = 100;
int b = 20;
int sum = a + b;
System.out.println("The addition of " + a + " and " + b + " is " +
sum); //The addition of 100 and 20 is 120
}
}

Program -
Write a program to print your name, address and age in a paragraph format.
class Hi {
public static void main(String[] args) {
String name = "Tanmoy Pramanick";
String address = "Cuttack";
int age = 27;
System.out.println("I am " + name + " and i am from "+address+ ".
I am "+ age+ " years old.");
}
}

Relational operator -
●​ These operators will perform a comparison between two operands. The output of the
operation is always in a Boolean expression.

class Boolean {
public static void main(String[] args) {
boolean a = 10 > 2;
boolean b = 3 < 2;
System.out.println(a); //true
System.out.println(b);// false
}
}
Equality operator (==)-
●​ These operators will also perform a comparison between two operands, where they will
check whether both operands are equal or not.
○​ If equal, it will return true or
○​ otherwise false.
●​ Example -
class Equality {
public static void main(String[] args) {
boolean a = 10 == 10;
boolean b = 3 == 2;
System.out.println(a);//true
System.out.println(b);//false
}
}

Not equal operator(!=) -


●​ This operator will also perform comparison and give us output as
○​ true if both operands are different
○​ False if both operands are the same
●​ Example -

class NotEqual {
public static void main(String[] args) {
boolean a = 10 != 10;
boolean b = 3 != 2;
System.out.println(a);
System.out.println(b);
}
}

Assignment operator -
●​ This operator will assign a value to a variable or a variable to an object.
●​ There are three types of assignment operators -
○​ Simple
○​ Chain
○​ Compound

Chain assignment -
●​ It is a type of assignment operation that will be used whenever we want to assign the
same value to multiple variables.
Example -
class ChainAssignmet {
public static void main(String[] args) {
int a, b, c, d, e, f;
a = b = c = d = e = f = 10;
System.out.println(a+" "+b+" "+c+" "+d+" "+e+" "+f);//10 10 10 10
10 10
}
}

Compound assignment -

class compound {
public static void main(String[] args) {
int a = 10;
a += 10;
System.out.println(a);//20
a -= 2;
System.out.println(a);//18
a *= 12;
System.out.println(a);//216
}
}

Bitwise operator -
●​ Three types of bitwise operator are there-
○​ Bitwise AND
○​ Bitwise OR
○​ Bitwise XOR

Bitwise AND(&)-
●​ In the bitwise AND operator, it will give us true as the output if both operands are true;
otherwise, false.

a b a&b

true true true

true false false

false true false

false false false

Example-
class BitwiseAND {
public static void main(String[] args) {
boolean a = (10 > 2) & (10 == 10);
boolean b = true & false;
System.out.println(a);//true
System.out.println(b);//false
}
}

Bitwise OR -
●​ In the bitwise OR operator, it will give us
○​ true if either of the operands is true,
○​ otherwise false.

a b a|b
true true true

true false true

false true true

false false false

class bitwiseOR {
public static void main(String[] args) {
boolean a = (10 > 2) | (12 != 12);
boolean b = false | false;
System.out.println(a);//true
System.out.println(b);//false
}
}

Bitwise XOR -
●​ In bitwise XOR, it will give the output as
○​ true, if both the operands are different
○​ False, if both operands are the same

a b a^b

true true false

true false true

false true true

false false false

class bitwiseXOR {
public static void main(String[] args) {
boolean a = true ^ false;
boolean b = (2 <= 3) ^ (0 == 0);
System.out.println(a);//true
System.out.println(b);//false
}
}

class problem {
public static void main(String[] args) {
int a = 35 & 25;
System.out.println(a);//1
}
}

1 - true
0 - false

25 24 23 22 21 20 AND

32 16 8 4 2 1 &

1 0 0 0 1 1 35

0 1 1 0 0 1 25

0 0 0 0 0 1 1

class problem2 {
public static void main(String[] args) {
int a = 99 ^ 110;
System.out.println(a);//13
}
}

26 25 24 23 22 21 20 XOR

64 32 16 8 4 2 1 ^

1 1 0 0 0 1 1 99

1 1 0 1 1 1 0 110

0 0 0 1 1 0 1 13
Logical operator -
●​ These are the operators that will execute the second operand based on the output of the
first operand. Because the execution of the second operand is optional.
●​ Types of logical operators -
○​ Logical AND operator
○​ Logical OR operator

Logical AND operator-


●​ In a logical and operator, the second operand will be executed if and only if the output of
the first operand is true.

a b a&&b

true true true

true false false

false No need for false


execution!

false No need for false


execution!

class logicalAND {
public static void main(String[] args) {
int a = 12, b = 10;
if ((++a < ++b) && (++a < ++b)) {
System.out.println("IF-wala");
System.out.println(a + " " + b);
} else {
System.out.println("Else-wala");
System.out.println(a + " " + b);
}
}
}
// Else-wala
// 13 11
Logical OR operator-
●​ In a logical OR operator, the second operand will be executed if and only if the output of
the first operand is false.
a b a||b

true No need for true


execution!

true No need for true


execution!

false true true

false false false

class logicalOR {
public static void main(String[] args) {
int a = 12, b = 10;
if ((++a > ++b) || (++a < ++b)) {
System.out.println("IF wala");
System.out.println(a + " " + b);
} else {
System.out.println("else wala");
System.out.println(a + " " + b);
}
}
}
// IF wala
// 13 11

Ternary operator -
●​ Whenever we are performing an operation by using three operands, the operator used is
known as a ternary operator.
Example -
class ternary {
public static void main(String[] args) {
String s = (10 > 100) ? "true" : "false";
System.out.println(s);//false
}
}

●​ In this JVM will execute either statement1 or statement2, where


○​ Statement 1 will be executed if and only if the output of the condition is true
○​ Statement 2 will be executed if and only if the output of the condition is false
●​ Example -
class ternary2 {
public static void main(String[] args) {
int x = (true) ? 100 : 1000;
System.out.println(x);//100
x = (false) ? 100 : 1000;
System.out.println(x);//1000
}
}

Flow control -
●​ The sequential order in which all the statements are executed at runtime by the JVM is
known as flow control.
●​ To execute the program according to our requirements, we will use flow control
statements.
●​ They are -
○​ Selection statements
■​ If-else
■​ Else-if
■​ switch
○​ Iterative statements
■​ For loop
■​ While loop
■​ Do-while loop
○​ Transfer statements
■​ Break
■​ continue

Selection statements
●​ It is the type of flow control statement that will execute any one selection among multiple
choices.

if .. else
●​ Syntax-

●​ If the output of the condition is true, then the if block will execute; otherwise, the else
block will be executed on getting output is false.

class selection {
public static void main(String[] args) {
if (true) {
System.out.println("Statement 1");
}
else{
System.out.println("Statement 2");
}
}
}
//op - Statement 1

class selection2 {
public static void main(String[] args) {
if (false) {
System.out.println("Statement 1");
}
else {
System.out.println("Statement 2");
}
}
}
//Op - Statement 2

Write a program to check if a number is even or odd.

class Evenodd {
public static void main(String[] args) {
int a = 5;

if (a % 2 == 0) {
System.out.println("Even");
}
else {
System.out.println("Odd");
}
}
}
//op Odd

Write a program to find the greatest of two numbers.

class Greatest {
public static void main(String[] args) {
int a = 10;
int b = 9;
if (a > b) {
System.out.println(a + " is greater!");
}
else {
System.out.println(b + " is greater!");
}
}
}

Write a program to find the greatest of three numbers.


class Greatest {
public static void main(String[] args) {
int x, y, z;
x = 30;
y = 20;
z = 40;
if (x > y) {
if (x > z) {
System.out.println(x + " is greatest!");
}
else {
System.out.println(z + " is greatest!");
}
} else {
if (y > z) {
System.out.println(y + " is greatest!");
}
else {
System.out.println(z + " is greatest!");
}
}
}
}
//op: 40 is greatest!

Write a program to check whether a person is eligible to give a vote or not.


class Vote {
public static void main(String[] args) {
int age = 23;
if (age >= 18) {
System.out.println("Eligible to vote!");
}
else {
System.out.println("Not eligible for vote!");
}
}
}
//op- Eligible to vote!
Write a program to check if a given integer is positive or negative.

class checkpositive {
public static void main(String[] args) {
int x = -10;
if (x >= 0) {
System.out.println(x + " is positive!");
}
else {
System.out.println(x + " is negative!");
}
}
}
// -10 is negative!
Else if()
●​ Whenever we want multiple choices in an if-else, then we go for else if().
●​ Syntax -

Example -

class elseIF {
public static void main(String[] args) {
if (false) {
System.out.println("Statement 1");
}
else if (false) {
System.out.println("Statement 2");
}
else if (true) {
System.out.println("Statement 3");
}
else {
System.out.println("Statement 4");
}
}
}
// Statement 3

●​ In the condition part, we can write a Boolean expression directly, or we can perform an
operation whose output will be in the form of a Boolean expression.

class ifelseexample {
public static void main(String[] args) {
if (10 == 10) {
System.out.println("Hi");
}
else {
System.out.println("Getout!");
}
}
}
// op - Hi

class ifelseexample2 {
public static void main(String[] args) {
boolean x = true;
if (x) {
System.out.println("Hii");
}
else {
System.out.println("Getout!");
}
}
}
// op - Hii

class ifelseexample3 {
public static void main(String[] args) {
if (10 = 10) {
System.out.println("Hii");
}
else {
System.out.println("Getout!");
}
}
}
// compilation error

●​ The else block is optional.

class ifelseexample3 {
public static void main(String[] args) {
if (true) {
System.out.println("Home");
}
}
}
// op - Home

class ifelseexample4 {
public static void main(String[] args) {
else {
System.out.println("Home");
}
}
}
// Compilation error

●​ We can not write any statement in between the if and else block because else will always
expect that there must be an if block immediately before it.

class ifelseexample4 {
public static void main(String[] args) {
if (true) {
System.out.println("hii");
}
System.out.println("Home");
else {
System.out.println("bye");
}
}
}
// compilation error: 'else' without 'if'

●​ Curly braces are optional. If we are not using any curly braces, then the JVM will consider
the very next and the only statement as part of the if block.

public class ifelseexample5 {


public static void main(String[] args) {
if(true)
System.out.println("Hiii");
System.out.println("Home");
}
}
// op -
// Hiii
// Home

class ifelseexample6 {
public static void main(String[] args) {
if(false)
System.out.println("Hiii");
System.out.println("Home");
}
}
// op - Home

●​ The single statement that will be part of the if block must not be a declarative type
statement.

class ifelseexample8 {
public static void main(String[] args) {
if(true)
int x = 10;
System.out.println(x);
}
}
// compilation error: variable declaration not allowed here

class ifelseexample8 {
public static void main(String[] args) {
if(false)
int x = 10;
}
}
// compilation error: variable declaration not allowed here

class ifelseexample8 {
public static void main(String[] args) {
if(true)
int x = 10;
}
}
// compilation error: variable declaration not allowed here

class ifelseexample9 {
public static void main(String[] args) {
int x;
if(true)
x = 10;
System.out.println(x);
}
}
// op - 10

class ifelseexample10 {
public static void main(String[] args) {
int x;
if(false)
x = 10;
System.out.println(x);
}
}
// error: variable x might not have been initialized

Write a program to determine the grade of a student


For 100 - 91 = grade A+
90 - 81 = grade A
80 - 71 = grade B+
70 - 61 = grade B
60 - 51 = grade C
50 - 41 = grade D
40 - 33 = grade E
Less than 33 = grade F(fail)

class GRADE {
public static void main(String[] args) {
int x = 45;
if (x <= 100 && x >= 91) {
System.out.println("A+");
}
else if (x <= 90 && x >= 81) {
System.out.println("A");
}
else if (x <= 80 && x >= 71) {
System.out.println("B+");
}
else if (x <= 70 && x >= 61) {
System.out.println("B");
}
else if (x <= 60 && x >= 51) {
System.out.println("C");
}
else if (x <= 50 && x >= 41) {
System.out.println("D");
}
else if (x <= 40 && x >= 33) {
System.out.println("E");
}
else if (x <= 33) {
System.out.println("F");
}
}
}
// D

Nested if
●​ Whenever we want a condition inside another condition, we will go for nested if
statements

class NESTEDIF {
public static void main(String[] args) {
if (true) {
if (true) {
System.out.println("Hii");
}
}
}
}
// Hii

class NESTEDIF2 {
public static void main(String[] args) {
if (true) {
if (false) {
System.out.println("hii");
}
System.out.println("hello");
}
System.out.println("Main");
}
}
// hello
// Main

class NESTEDIF3 {
public static void main(String[] args) {
if (true)
System.out.println("Hello");
if (false)
System.out.println("hi");
System.out.println("Main");
}
}
// Hello
// Main

●​ Here, the curly brackets are not there. Both the if conditions are considered as individual.
Second, if not nested.
class NESTEDIF4 {
public static void main(String[] args) {
if (true)
if (false)
System.out.println("hi");
System.out.println("Main");
}
}
// Main

●​ Here, the second if is nested as it is exactly next to the if.

Nested if-else
●​ Declaring if-else inside another if-else is known as nested if-else.
class NESTEDIFELSE {
public static void main(String[] args) {
if (false) {
if (false) {
System.out.println("A");
} else {
System.out.println("B");
}
} else {
if (false) {
System.out.println("C");
} else {
System.out.println("D");
}
}
}
}
// D

class NESTEDIFELSE2 {
public static void main(String[] args) {
if (true)
if (false)
System.out.println("A");
else
System.out.println("B");
else
if (false)
System.out.println("C");
else
System.out.println("D");
}
}
// B

Switch
●​ Switch is a multiple-choice argument selection statement.
class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x) {
case 0:
System.out.println("Statement 1");
break;
case 12:
System.out.println("Statement 2");
break;
case 15:
System.out.println("Statement 3");
break;
default:
System.out.println("Default statement");
break;
}
}
}
// Default statement

●​ Both the case label and the default case label are optional.
class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x) {
case 0:
System.out.println("Statement 1");
break;
}
}
}
// no output

class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x) {
default:
System.out.println("Statement 1");
break;
}
}
}
// Statement 1

●​ An empty switch is a valid Java syntax.


class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x){
}
}
}

●​ If we want to write any statement inside the switch, then it must be under a case label or
under a default case label.
class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (args) {
System.out.println("null");
}
}
}
// case, default, or '}' expected
// System.out.println("null");

class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x) {
case 0:
System.out.println("Statement 1");
break;
System.out.println("Statement 2");
default:
System.out.println("Statement 3");
break;
}
}
}
// error: unreachable statement
// System.out.println("Statement 2");
// ^

●​ The declaration position of the case label and default case is not fixed.
class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x) {

default:
System.out.println("Statement 3");
break;

case 0:
System.out.println("Statement 1");
break;
}
}
}
// Statement 3
●​ In switch, the curly braces are mandatory.
class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x)
case 0:
System.out.println("Statement 1");
break;

default:
System.out.println("Statement 3");
break;
}
}
// error: '{' expected
// switch (x)
// ^
// SWITCH1.java:13: error: reached end of file while parsing
// }
// ^

●​ Can't terminate switch statement without curly brackets.


class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x);
{
case 0:
System.out.println("Statement 1");
break;

default:
System.out.println("Statement 3");
break;
}
}
}
// error: '{' expected
// switch (x);
// ^
// error: case, default, or '}' expected
// {
// ^

●​ Putting a semicolon after the ending of the switch block is valid. Similarly, putting a
semicolon after if-else is also valid.
class SWITCH1 {
public static void main(String[] args) {
int x = 120;
switch (x)
{
case 0:
System.out.println("Statement 1");
break;

default:
System.out.println("Default Statement");
break;
};
}
}
//Default Statement

Case 1
●​ Switch case label must be within the range of the switch argument's datatype.
example -
class ex1 {
public static void main(String[] args) {
byte b = 123;
switch (b) {
case 1000:
System.out.println("statement 1");
break;

default:
System.out.println("default");
break;
}
}
}
// error: incompatible types: possible lossy conversion from int to byte
// case 1000:

●​ switch (b) where b is of type byte.


●​ case 1000: is invalid because 1000 exceeds the range of byte (-128 to 127).
●​ This causes a compilation error due to possible lossy conversion from int to byte.

case 2
●​ The case label can't be duplicated.
class ex2 {
public static void main(String[] args) {
int b = 97;
switch (b) {
case 'a':
System.out.println("hi");
break;

case 97:
System.out.println("hello");

default:
System.out.println("no");
break;
}
}
}
// error: duplicate case label
// case 97:

●​ 'a' is a char literal with ASCII value 97.


●​ So both case 'a': and case 97: refer to the same constant value.
●​ This results in a duplicate case label error.
case 3
●​ We can only use a constant expression in the case label.
example-
class ex3 {
public static void main(String[] args) {
int b = 123;
switch (b) {
case b:
System.out.println("Statement 1");
break;

default:
System.out.println("Statement 2");
break;
}
}
}
// error: constant expression required
// case b:
// ^

●​ You cannot use a variable like case b: inside the switch — only compile-time constant
expressions are allowed.
●​ Making b final turns it into a constant, so case b: is valid in that situation.

●​ Case b is a variable. It needs to be constant.


●​ If we declare a variable as final, then we can't reinitialize the variable because the value
has been assigned to the variable, making it a constant value(fixed) for that variable.
example
class ex4 {
public static void main(String[] args) {
final int b = 123;
switch (b) {
case b:
System.out.println("Statement 1");
break;

default:
System.out.println("Statement 2");
break;
}
}
}
// Statement 1

case 4

fall through inside switch


●​ A fall through switch is a scenario, while executing a match case label, if the JVM does not
find the break statement. Then it will keep on executing all the statements below it,
irrespective of whether it is an unmatched case label or a default case label, until it finds a
break statement or reaches the end of the switch.
example
class ex5 {
public static void main(String[] args) {
int b = ?;
switch (b) {
case 10:
System.out.println("Statement 1");

case 100:
System.out.println("Statement 2");
break;

case 1000:
System.out.println("Statement 3");

default:
System.out.println("default statement");
break;
}
}
}

Op table-
For value b Output

10 Statement 1
Statement 2

100 Statement 2

1000 Statement 3
default statement

Other values(0, 1, 6, 34..etc) default statement

●​ When no break is present after a matching case, the execution falls through to
subsequent cases or the default label.
●​ In your example, case 1000: prints:
Statement 3
default statement
●​ Because there's no break after Statement 3.

Iterative statements -
●​ It is a type of flow control statement, where we will execute a particular statement or a
block of code more than one time according to our requirement without rewriting it
multiple times.

For loop-
●​ Whenever we know the exact number of iterations for how many times a particular or a
block of code is going to be executed, then at the moment of time we will go for a "for
loop".
●​ Syntax-

●​ There are two parts of a for loop.


Example 1- print 1 to 10 using a for loop.
class example1 {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
}
}
//1
// 2
// 3..10

Example- Print 10 to 1 reverse using a for loop.


class example1 {
public static void main(String[] args) {
for (int i = 10; i >= 1; i--) {
System.out.println(i);
}
}
}
// 10
// 9
// 8
// 7
// 6
// 5
// 4
// 3
// 2
// 1

example - Print the sum of 1 to 10 using a for loop.


class example2 {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum = sum + i;
}
System.out.println(sum);
}
}
// 55

Example- Print the even numbers within 10 using a for loop.


class example3 {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}
// 2
// 4
// 6
// 8
// 10

for loop initialization part


●​ It is the part that will be executed first and only once.
example -
class example4 {
public static void main(String[] args) {
int i = 1;
for (System.out.println("hii"); i <= 10; i++) {
System.out.println(i);
}
}

}
// hii
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10

●​ Initialization for the for loop in the initialization part is optional. If we are using any variable
in the for loop, then we can declare those variables before the for loop.
Example -
class example5 {
public static void main(String[] args) {
int i = 1;
for (; i <= 10; i++) {
System.out.println(i);
}
}
}
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10

class exa1 {
public static void main(String[] args) {
for (int i = 0, j = 1, k = 2; i < 5; i++) {
System.out.println(i+" "+j+" "+k);
j++;
k++;
}
}
}
// 0 1 2
// 1 2 3
// 2 3 4
// 3 4 5
// 4 5 6

●​ We can declare multiple variables of the same type in the initialization part.
class exa1 {
public static void main(String[] args) {
for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
System.out.println(i+" "+j+" "+k);
j++;
k++;
}
}
}
// xa1.java:3: error: <identifier> expected
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
// ^
// exa1.java:3: error: '.class' expected
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
// ^
// exa1.java:3: error: '.class' expected
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
// ^
// exa1.java:3: error: not a statement
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
// ^
// exa1.java:3: error: illegal start of type
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
// ^
// exa1.java:3: error: not a statement
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
// ^
// exa1.java:3: error: ';' expected
// for (int i = 0, float j = 1.3f, char k = '2'; i < 5; i++) {
●​ We can't declare multiple variables of different types in the initialization.

condition part(For loop)


●​ It is the part that will get executed in the second place. This part is also optional. If we are
not giving any condition, then the condition output will be taken as true.
class exa1 {
public static void main(String[] args) {
for (int i = 0;; i++) {
System.out.println(i);
}
}
}

●​ Here, the condition part will be considered by default to be true.


●​ In the condition part either we can either pass boolean expressions directly or we can
perform an operation whose output will be in the form of a boolean expression
class exa1 {
public static void main(String[] args) {
for (int i = 0;System.out.println("hii"); i++) {
System.out.println(i);

}
}
}
// exa1.java:3: error: incompatible types: void cannot be converted to
boolean
// for (int i = 0;System.out.println("hii"); i++) {

class exa1 {
public static void main(String[] args) {
boolean b = true;
for (int i = 0;b; i++) {
System.out.println(i);

}
}
}
The updation part of the for loop
●​ It is the part that will be executed at the end.
●​ The “updation”part is also optional.
example -
class exa1 {
public static void main(String[] args) {
for (int i = 0;i <= 5;) {
System.out.println(i);
}
}
}

class exa1 {
public static void main(String[] args) {
for (int i = 0;i <= 5;) {
System.out.println(i);
i++;
}
}
}
// 0
// 1
// 2
// 3
// 4
// 5

While loop
●​ Whenever we do not know the exact number of iterations for how many times a particular
statement or a block of code is going to get executed, then we will go for a while loop.
Example -
class example1{
public static void main(String[] args) {
while (true){
System.out.println("Hello");
}
}
}
//hello ...infinity times

example -
class example2 {
public static void main(String[] args) {
int i = 1, j = 10;
while(j < i) {
System.out.println("Hii");
}
System.out.println("Main");
}
}
// Main

Example- print 1 to 10 using a while loop.


class example3 {
public static void main(String[] args) {
int i = 1;
while(i <= 10) {
System.out.println(i);
i++;
}
}
}
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10

example - Print the even numbers using a while loop.


class example4 {
public static void main(String[] args) {
int i = 1;
while (i <= 10) {
if (i % 2 == 0) {
System.out.println(i);
}
i++;
}
}
}
// 2
// 4
// 6
// 8
// 10

Do while loop -
●​ If we want to execute any statement or code at least once, irrespective of the condition,
we should use a do-while loop.
class example1 {
public static void main(String[] args) {
do {
System.out.println("Hello");
} while (true);
}
}
// Hello
// .
// .
// infinity

class example1 {
public static void main(String[] args) {
do {
System.out.println("Hello");
} while (false);
}
}
// Hello
●​ The below code shows an error as an unreachable statement, as we are using a
constant Boolean value "true". So there will be no chance that the next statement will
execute in the future once the program runs.

class example1 {
public static void main(String[] args) {
do {
System.out.println("Hello");
} while (true);
System.out.println("Abc");
}
}
// example1.java:6: error: unreachable statement
// System.out.println("Abc");

class example1 {
public static void main(String[] args) {
int x = 10;
int y = 10;
do {
System.out.println("Hello");
} while (10 == 10);
System.out.println("Abc");
}
}
// example1.java:6: error: unreachable statement
// System.out.println("Abc");

class example1 {
public static void main(String[] args) {
final int x = 10;
final int y = 10;
do {
System.out.println("Hello");
} while (x == y);
System.out.println("Abc");
}
}
// example1.java:6: error: unreachable statement
//
●​ The compiler gives an unreachable code error only when it can statically determine that
a loop is infinite. If the condition is a constant expression like true or two final values that
are equal, it flags an error.
●​ If we are using boolean expressions using the variable whose output is true, then it would
not show any error.
example-
class example1 {
public static void main(String[] args) {
int x = 10;
int y = 10;
do {
System.out.println("Hello");
} while (x == y);
System.out.println("Abc");
}
}

●​ The compiler does not assume the condition will always be true since x and y are
variables (even if initialized with the same value).

Programs-
Wap to print all the even numbers in between a range.
class printEven {
public static void main(String[] args) {
int x = 10;
int y = 20;
for (int i = x; i <= y; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}
// 10
// 12
// 14
// 16
// 18
// 20

Wap to print the sum of all the even numbers in between a range
class printEvenSum {
public static void main(String[] args) {
int sum = 0;
int x = 10;
int y = 20;
for (int i = x; i <= y; i++) {
if (i % 2 == 0) {
sum = sum + i;
}
}
System.out.println(sum);
}
}
// 90

Wap to print the factorial of a number.


class factorial {
public static void main(String[] args) {
long fact = 1l;
int num = 20;
for (int i = 1; i <= num; i++) {
fact = fact * i;
}
System.out.println(fact);
}
}
// 2432902008176640000

Wap to print alternate even numbers in between a range


class AlternateEven {
public static void main(String[] args) {
boolean flag = true;
int st = 10;
int en = 20;
for (int i = st; i <= en; i++) {
if (i % 2 == 0) {
if (flag) {
System.out.println(i);

}
flag = !flag;
}

}
}
}
// 10
// 14
// 18

Wap to check a number is prime or not


class CheckPrime {
public static void main(String[] args) {
int count = 0;
int num = 30;
for (int i = 1; i <= num; i++) {
if (num % i == 0) {
count++;
}
}
if (count == 2) {
System.out.println(num+" is a Prime!");
} else {
System.out.println(num+" is not a Prime!");
}
}
}
// 30 is not a Prime!

Wap to print prime in between a range


class PrimeRange {
public static void main(String[] args) {
int low = 5;
int up = 20;
for (int i = low; i <= up; i++) {
int count = 0;
for (int j = 1; j <= i; j++) {
if(i % j == 0) {
count++;
}

}
if(count == 2) {
System.out.println(i+": Prime!");
}
}
}
}
// 5: Prime!
// 7: Prime!
// 11: Prime!
// 13: Prime!
// 17: Prime!
// 19: Prime!

Wap to count the digits of a number.


class countDigits {
public static void main(String[] args) {
int num = 12345;
int count = 0;
while (num > 0) {
count++;
num = num / 10;
}
System.out.println(count);
}
}
// 5

Wap to print digits of a number.


class printDigits {
public static void main(String[] args) {
int num = 12245;
while (num > 0) {
System.out.println(num % 10);
num = num / 10;
}
}
}
// 5
// 4
// 2
// 2
// 1

Another way -
class printDigits {
public static void main(String[] args) {
int num = 12245;
int rev = 0;
while (num > 0) {
int rem = num % 10;
rev = rev * 10 + rem;
num = num / 10;
}
while (rev > 0) {
System.out.println(rev % 10);
rev = rev / 10;
}
}
}
// 1
// 2
// 2
// 4
// 5

Wap to print the sum of the numbers of a digit.


class sumDigitis {
public static void main(String[] args) {
int sum = 0;
int num = 45678;
while (num > 0 ) {
sum = sum + num % 10;
num = num / 10;
}
System.out.println(sum);
}
}
// 30

Scanner class -
●​ We should go for a scanner class whenever we want input from the user at run time.
●​ The Scanner class is present in the "java.util" package.
●​ We need to import the "java.util" package to use the Scanner class in our program.
●​ Syntax: import package_name.Class_name
●​ ex: import java.util.Scanner;

Methods of the scanner class -

Input type Methods of Scanner class

integer nextByte(), nextShort(), nextInt(), nextLong()

decimal nextFloat(), nextDouble()

boolean nextBoolean()

string next(), nextLine()

character next().charAt(0)

●​ All the above methods of the Scanner class are non-static means to access all the above
methods, we need to create an object of the Scanner class.
●​ Example:
Scanner sc = new Scanner(System.in);
sc.nextInt();
sc.nextDouble();
sc.nextLine()

next() vs nextLine()
●​ next(): It takes all the characters until the space.
●​ example -
import java.util.Scanner;
class example5 {
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("Your name is: " + name);

}
}
// Enter your name:
// Tanmoy Pramanick
// Your name is: Tanmoy

●​ nextLine(): It takes all the characters, including the space.


●​ example -
import java.util.Scanner;
class example5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter your name:");
String name = sc.nextLine();
System.out.println("Your name is: " + name);

}
}
// Enter your name:
// Tanmoy Pramanick
// Your name is: Tanmoy Pramanick
Wap to print the name, age, salary, and address of an employee.

import java.util.Scanner;
public class example3 {
public static void main(String[] args) {
String name, address;
int age, salaray;
Scanner s = new Scanner(System.in);
System.out.println("Enter your name:");
name = s.nextLine();
System.out.println("Enter your Age:");
age = s.nextInt();
System.out.println("Enter your Salary:");
salaray = s.nextInt();
System.out.println("Enter your Address:");
address = s.nextLine();
System.out.println("Your name is: "+name);
System.out.println("Your age is: "+age);
System.out.println("Your salary is: " + salaray);
System.out.println("Your address is: " + address);
}
}
// Enter your name:
// Tanmoy Pramanick
// Enter your Age:
// 24
// Enter your Salary:
// 224
// Enter your Address:
// Your name is: Tanmoy Pramanick
// Your age is: 24
// Your salary is: 224
// Your address is:

●​ The above program will skip the address input, as after typing the salary, we press Enter.
The nextLine() method takes the Enter key and simply terminates. To overcome this, we
need to use a nextLine() before taking input for the address.
Example -
import java.util.Scanner;
public class example3 {
public static void main(String[] args) {
String name, address;
int age, salaray;
Scanner s = new Scanner(System.in);
System.out.println("Enter your name:");
name = s.nextLine();
System.out.println("Enter your Age:");
age = s.nextInt();
System.out.println("Enter your Salary:");
salaray = s.nextInt();
System.out.println("Enter your Address:");
s.nextLine();
address = s.nextLine();
System.out.println("Your name is: "+name);
System.out.println("Your age is: "+age);
System.out.println("Your salary is: " + salaray);
System.out.println("Your address is: " + address);
}
}
// Enter your name:
// Tanmoy Pramanick
// Enter your Age:
// 24
// Enter your Salary:
// 224
// Enter your Address: CDA Cuttack
// Your name is: Tanmoy Pramanick
// Your age is: 24
// Your salary is: 224
// Your address is: CDA Cuttack

Wap to print even numbers in between a range by taking user input


import java.util.Scanner;
class printEvenInARange {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the lower num:");
int low = sc.nextInt();
System.out.println("ENter the upper num:");
int up = sc.nextInt();

if (low > up) {


System.out.println("Alert ! You have entered an incorrect
range!");
} else {
System.out.println(
"The even numbers between " + low + " and " + up + "
are:");
for (int i = low; i <= up; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}
}
// Enter the lower num:
// 23
// ENter the upper num:
// 30
// The even numbers between 23 and 30 are:
// 24
// 26
// 28
// 30

Programs-
Wap a program to swap the numbers by taking the user input
import java.util.Scanner;
class swapNumber {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the first num:");
int f = sc.nextInt();
System.out.println("Enter the second num:");
int s = sc.nextInt();
System.out.println("Before swap: "+ "\n" + "First num is:" + f +
"\n" + "Second num is:" + s);
int swap = f;
f = s;
s = swap;
System.out.println("After swap: "+ "\n" + "First num is:" + f +
"\n" + "Second num is:" + s);
}
}
// Enter the first num:
// 23
// Enter the second num:
// 45
// Before swap:
// First num is:23
// Second num is:45
// After swap:
// First num is:45
// Second num is:23

Wap to print a table of a number by taking user input.


import java.util.Scanner;
class printTable {
void table(int num) {
for (int i = 1; i <= 10; i++) {
System.out.println(num + " * " + i + " = " + num * i);
}

}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter a number: ");
int num = sc.nextInt();
printTable p = new printTable();
p.table(num);

}
}
// Enter a number:
// 3
// 3 * 1 = 3
// 3 * 2 = 6
// 3 * 3 = 9
// 3 * 4 = 12
// 3 * 5 = 15
// 3 * 6 = 18
// 3 * 7 = 21
// 3 * 8 = 24
// 3 * 9 = 27
// 3 * 10 = 30

Wap to print table from 1 to that number


import java.util.Scanner;
class printTable2 {
void table2(int num) {
for (int i = 1; i <= num; i++) {
System.out.println("Table of: " + i);
for (int j = 1; j <= 10; j++) {
System.out.println(i + " * " + j + " = " + i * j);
}

}
public static void main(String[] args) {
printTable2 p2 = new printTable2();
Scanner sc = new Scanner(System.in);
System.out.println("Enter a number: ");
int num = sc.nextInt();
p2.table2(num);
}
}
// Enter a number:
// 3
// Table of: 1
// 1 * 1 = 1
// 1 * 2 = 2
//.
// .
// .
// Table of: 2
// 2 * 1 = 2
// 2 * 2 = 4
//.
//.
//.
// Table of: 3
// 3 * 1 = 3
// 3 * 2 = 6
//.
//.
//.

Star pattern-
Wap to print the star pattern
Square pattern:
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
import java.util.Scanner;
class starpattern {
void square(int num) {
System.out.println("Square pattern:");
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= num; j++) {
System.out.print('*' + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner cs = new Scanner(System.in);
System.out.println("Enter a number:");
int num = cs.nextInt();
starpattern s = new starpattern();
s.square(num);
}
}

triangle 1:
*
* *
* * *
* * * *
* * * * *
import java.util.Scanner;
void triangle1(int num) {
System.out.println("traiangle 1:");
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= i; j++) {
System.out.print('*' + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner cs = new Scanner(System.in);
System.out.println("Enter a number:");
int num = cs.nextInt();
starpattern s = new starpattern();
s.square(num);
s.triangle1(num);
}
}

Triangle 2:
*
* *
* * *
* * * *
* * * * *
import java.util.Scanner;
class starpattern {
void triangle2(int num) {
System.out.println("Triangle 2:");
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= num; j++) {
if (i + j > num) {
System.out.print('*' + " ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner cs = new Scanner(System.in);
System.out.println("Enter a number:");
int num = cs.nextInt();
starpattern s = new starpattern();
s.triangle2(num);
}
}

Triangle 3
* * * * *
* * * *
* * *
* *
*
import java.util.Scanner;
class starpattern {
void triangle3(int num) {
System.out.println("Triangle 3");
// for (int i = num; i >= 0; i--) {
// for (int j = 1; j <= i; j++) {
// System.out.print("*" + " ");
// }
// System.out.println();
// }
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= num; j++) {
if (i + j <= num + 1) {
System.out.print('*' + " ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner cs = new Scanner(System.in);
System.out.println("Enter a number:");
int num = cs.nextInt();
starpattern s = new starpattern();
s.triangle3(num);
}
}

Triangle 4
* * * * *
* * * *
* * *
* *
*
import java.util.Scanner;
class starpattern {
void triangle4(int num) {
System.out.println("Triangle 4");
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= num; j++) {
if (j >= i) {
System.out.print("*"
+ " ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner cs = new Scanner(System.in);
System.out.println("Enter a number:");
int num = cs.nextInt();
starpattern s = new starpattern();
s.triangle4(num);
}
}

OOPs-

Why is Java known as an object-oriented programming language?

●​ Java's object-oriented nature allows developers to model real-world entities as objects,


encapsulating their properties and behaviors. This makes the code more intuitive,
relatable, and easier to maintain.
●​ By creating objects that mimic real-world entities, developers can:
○​ - Represent complex systems in a more natural way
○​ - Write code that's more modular and reusable
○​ - Improve code readability and understandability

Why is Java not a fully object-oriented programming language?


Here's why this is the main point of contention:

●​ Primitive Data Types: Java includes eight primitive data types (byte, short, int, long, float,
double, boolean, char). These primitive types are not objects. They do not have methods
or properties associated with them in the same way that objects of classes do. They are
treated as basic value types for performance reasons.
●​ Java does offer wrapper classes (like Integer, Double, etc.) which are objects, but using
primitives is common and allowed.
●​ You can use static methods without creating an object. OOP ideally promotes behavior
being tied to objects, but static methods operate at the class level.

Pillars of OOP-
There are five pillars of OOps
●​ Inheritance
●​ Data hiding
●​ Abstraction
●​ Encapsulation
●​ Polymorphism
Methods -
●​ Method is a block of code or set of instructions which is used for business logic or
application logic according to the programmer.
●​ Methods have two parts
○​ declaration
○​ implementation
●​ The declaration part contains some modifiers, return type, method name, and arguments.
●​ But the implementation part of any method contains some code according to the
programmer.
syntax -

Example -
class example1 {
public static void m1() {

}
public static void main(String[] args) {

}
}

class example1 {
public void m2() {

}
public static void main(String[] args) {

}
}

Types of methods-
●​ Static method
●​ Non-static method
Static method
●​ The method that contains a static modifier is known as a static method.
Example-
class example1 {
public static void m1() {
System.out.println("Static");
}
public static void main(String[] args) {
}
}

Non-Static Method-
●​ The method that does not contain a static modifier is known as a non-static method.
class example1 {
public void m1() {
System.out.println("Non static");
}
public static void main(String[] args) {
}
}

Method calling -
●​ Calling a method means going to that method and executing every statement inside that
method in an organized manner. After the execution is completed, the process returns to
its calling location.

Calling of a non-static method -


●​ There is only one way to access the non-static methods inside any static area, that is by
the help of an object. If we are trying to access it directly inside any static area, then we
will get a compile-time error.
class ex1 {
public void m2() {
System.out.println("Non static");
}
public static void main(String[] args) {
m2();
}
}
// error: non-static method m2() cannot be referenced from a static
context
// m2();
// ^
// 1 error

●​ non-static method m2() cannot be referenced from a static context


class ex1 {
public void m2() {
System.out.println("Non static");
}
public static void main(String[] args) {
ex1 e = new ex1();
e.m2();
}
}
// Non static

class ex1 {
public void m2() {
System.out.println("Non static");
}
public static void main(String[] args) {
ex1 e = new ex1();
e.m1();
}
}
// error: cannot find symbol
// e.m1();
// ^
// symbol: method m1()
// location: variable e of type ex1
// 1 error

●​ throws an error because m1() is undefined in class ex1.

Calling a static method-


●​ There are three ways to access any static method inside any static area
○​ By directly
○​ By class name (Recommended)
○​ By object
●​ Example -
class example2 {
public static void m1() {
System.out.println("Static method");
}
public static void main(String[] args) {
// By directly
m1();
//By class name
example2.m1();
//by object
example2 e = new example2();
e.m1();
}
}
// Static method
// Static method
// Static method

●​ We can access any non-static method inside any non-static area directly.
Example -
class example3 {

public void func1() {


System.out.println("Function 1");

}
public void func2() {
System.out.println("Function 2");
func1();

}
public static void main(String[] args) {
example3 x = new example3();
x.func2();
}
}
// Function 2
// Function 1

●​ We can access any static method inside any non-static area directly.
class example4 {
public void func_non_st () {
System.out.println("Non Static Function");
func_st();
}
public static void func_st() {
System.out.println("static Function");
}
public static void main(String[] args) {
example4 obj = new example4();
obj.func_non_st();
}
}
// Non Static Function
// static Function

Argument-
●​ Argument means input to the method.
●​ There are two types of arguments.
○​ Primitive argument
○​ Non Primitive argument
●​ At the time of method declaration, we can declare any variable inside the argument, but
we can't initialize it.
●​ invalid arguments-
○​ func (int x = 10)
○​ func (x = 10)
○​ func (x)
○​ func (10)
●​ Valid arguments-
○​ func (int x)
○​ func (int x, int y)
○​ func (int x, boolean b)
●​ The variable declared inside the argument inside the argument part of any method is
known as a local variable of that method.

class argument {
public void func(int x) {
System.out.println("Argument value: " + x);
}
public static void main(String[] args) {
argument a = new argument();
a.func(20);
a.func('s');
a.func((int)20.9);
}
}
// Argument value: 20
// Argument value: 115
// Argument value: 20

Calling a method with a nonprimitive type argument-


●​ We have two options for calling a method with a nonprimitive type argument. We can pass
null or an object of the class as per the method requirements.
Example-
class objectArgument {

public void func(objectArgument obj) {


System.out.println("Java");

}
public static void main(String[] args) {
objectArgument o = new objectArgument();
//calling by object
o.func(new objectArgument());
//calling by providing null
o.func(null);
//calling by object variable
o.func(o);
}
}
// Java
// Java
// Java
Class type String Demo Test Object

Valid arguments null null null null

Valid arguments new String() new Demo() new Demo() new Object()

Java allows passing either:


●​ a reference to an object (e.g., new Object(), or a reference variable), or
●​ null

Return type-
●​ Return type means the output of the method.
●​ There are three types of return types.
○​ void
○​ primitive
○​ nonprimitive
●​ If any method contains a void return type, then it is not required to provide any return
statement because void returns nothing.
●​ If any method contains any primitive or nonprimitive type return type, then it is mandatory
to provide the return statement with a return value according to the return type.

valid return type Invalid return type

public void m1() { public int Func(){


}
}

public void m1(){ public void fun(){


return; return 0;
} }

public int m1(){ public int m1(){


return 0; return “string”;
} }

public float m1(){


return 0.0f;
}

public String str(){


return new String()/null/any string value;
}

public Test func(){


return new Test()/null;
}

●​ The return statement must be the last statement of any method.


(The return statement must be the last reachable statement in a code path — but it
doesn't have to be the last line of code.)
Example -
●​ Valid-
public class return_test {
public int func() {

System.out.println("Int function");
return 0;
}

●​ Invalid -
public class return_test {
public int func() {
return 0;
System.out.println("Int function");
}
// return_test.java:6: error: unreachable statement
// System.out.println("Int function");

How to print the return value of a method


●​ There are two ways to print the return value of a method.
○​ By directly
○​ Storing it within a variable
●​ By directly-
(By directly printing the method, we can able to get the return value)
Example-
public class return_test {
public int func() {

System.out.println("Int function");
return 0;
}
public static int func2() {
System.out.println("Static int function");
return 0;
}
public static void main(String[] args) {
return_test obj = new return_test();
System.out.println(obj.func());
System.out.println(func2());
}
}
// Int function
// 0
// Static int function
// 0

●​ By storing the value within a variable


(We can store the return value within a variable.)
example-
class gettingReturnValue {
public int func() {
System.out.println("Int function");
return 0;
}
public static int func2() {
System.out.println("Static int function");
return 1;
}
public static void main(String[] args) {
return_test obj = new return_test();
int x = obj.func();
int y = func2();
System.out.println(x);
System.out.println(y);
}
}
// Int function
// Static int function
// 0
// 1
●​ We can upcast or downcast the return value.
Example-
class returnUpcasting {
public int func() {
return 'a';
}
public static void main(String[] args) {
returnUpcasting obj = new returnUpcasting();
int ret_value = obj.func();
System.out.println(ret_value);
}
}
// 97

class returnDowncasting {
public int func() {
return (int)0.45;
}
public static void main(String[] args) {
returnUpcasting obj = new returnUpcasting();
int ret_value = obj.func();
System.out.println(ret_value);
}
}
// 0

Method signature -
●​ Method signature consists of the method name and the type of argument.
●​ example -
○​ void func(int x) → signature: func(int)
○​ int func(int s, int y) → signature: func(int, int)
●​ Creating multiple methods with the same method signature inside the same class is an
invalid Java syntax.
example -
class example1 {
public void func(int x) {
}
public int func(int y) {

}
}
// error: method func(int) is already defined in class example1
// public void func(int y) {

Inheritance -
●​ Acquiring properties of one class by another class is known as inheritance.
●​ We can inherit a class's properties with the extends keyword.
●​ The main advantage of inheritance is code reusability.
●​ The class that acquires properties is known as the child class.
●​ The class whose properties have been acquired by another class is known as the parent
class.

Example -
class syntax {
public void func1() {
System.out.println("Abc");
}
public static void func2() {
System.out.println("Static");
}
public int func3() {
System.out.println("Return type");
return 0;
}
}
class syntax2 extends syntax {
public void sfunc1() {
System.out.println("Extend class");
}
}
class Innersyntax {
public static void main(String[] args) {
syntax obj = new syntax();
syntax2 obj2 = new syntax2();
syntax.func2();
obj2.func3();
obj2.func1();
}
}
// Static
// Return type
// Abc

Types of inheritance -
●​ Single
●​ Multiple
●​ Multilevel
●​ Hierarchical
●​ Hybrid
Single inheritance -

●​ Acquiring properties of a single class by another class is known as single inheritance.


example-
class Parent {
public void parent_func(){
System.out.println("Parent Method");
}
}
class Child extends Parent {
public void child_func() {
System.out.println("Child method");
}
}
class exampl2 {
public static void main(String[] args) {
Child obj2 = new Child();
obj2.parent_func();
}
}
// Parent Method

Multiple inheritance -
●​ If a class acquires properties of more than one class simultaneously, it is known as
multiple inheritance.
●​ It is not supported in Java(using classes) because of the ambiguous issue and constructor
chaining. We can achieve it in the interface.
Example-

class Parent {

}
class Parent2 {

}
class child extends Parent, Parent2 {

Additional Information -
Not supported in Java using classes due to ambiguity (like the Diamond Problem) and
constructor chaining.

Diamond Problem: Imagine two parent classes with a common method. If a child class inherits
from both, which version of the method should it inherit and execute? This ambiguity makes it
difficult for the compiler to resolve.

Example -
class Diamond {

}
class Parent1 {
public void func() {
}
}
class Parent2 {
public void func() {
}
}
class Child extends Parent1, Parent2 {
}

Constructor Chaining: Managing the order and arguments of constructors from multiple parent
classes would introduce significant complexity.

Multilevel inheritance -

●​ If a child class is the parent class of another class, then it is known as multilevel
inheritance.
Example -
class Mutilevel {
public static void main(String[] args) {
System.out.println("==========Parent=========");
Parent obj_p = new Parent();
obj_p.Pa_func();
// obj_p.Ch_func();
// obj_p.Gr_func();
System.out.println("==========Child=========");
Child obj_c = new Child();
obj_c.Pa_func();
obj_c.Ch_func();
// obj_c.Gr_func();
System.out.println("==========GrandChild=========");
GrandChild obj_g = new GrandChild();
obj_g.Pa_func();
obj_g.Ch_func();
obj_g.Gr_func();
}
}
class Parent {
public void Pa_func() {
System.out.println("Class: Parent\nFunction: Pa_func");
}
}
class Child extends Parent {
public void Ch_func() {
System.out.println("Class: Child\nFunction: Ch_func");
}
}
class GrandChild extends Child {
public void Gr_func() {
System.out.println("Class: GrandChild\nFunction: Gr_func");
}
}
// ==========Parent=========
// Class: Parent
// Function: Pa_func
// ==========Child=========
// Class: Parent
// Function: Pa_func
// Class: Child
// Function: Ch_func
// ==========GrandChild=========
// Class: Parent
// Function: Pa_func
// Class: Child
// Function: Ch_func
// Class: GrandChild
// Function: Gr_func

The provided code accurately demonstrates multilevel inheritance. Child extends Parent, and
GrandChild extends Child. The output clearly shows that GrandChild has access to the methods
of both Parent and Child.

Hierarchical inheritance -

●​ If more than one class acquires the properties of a single class, then it is known as
hierarchical inheritance.
Example -
class Hierarchical {
public static void main(String[] args) {
System.out.println("========Parent========");
Parent obj_p = new Parent();
obj_p.p_Func();
System.out.println("========Child1========");
Child1 obj_C1 = new Child1();
obj_C1.p_Func();
obj_C1.Ch1_Func();
System.out.println("========Child2========");
Child2 obj_C2 = new Child2();
obj_C2.p_Func();
obj_C2.Ch2_Func();
}
}
class Parent {
public void p_Func() {
System.out.println("Class: Parent\nFunc: p_Func");
}
}
class Child1 extends Parent {
public void Ch1_Func() {
System.out.println("Class: Child1\nFunc: Ch1_Func");
}
}
class Child2 extends Parent {
public void Ch2_Func() {
System.out.println("Class: Child2\nFunc: Ch2_Func");
}
}
// ========Parent========
// Class: Parent
// Func: p_Func
// ========Child1========
// Class: Parent
// Func: p_Func
// Class: Child1
// Func: Ch1_Func
// ========Child2========
// Class: Parent
// Func: p_Func
// Class: Child2
// Func: Ch2_Func

Hybrid Inheritance -
●​ It is the combination of single inheritance, multilevel inheritance, multiple inheritance, and
hierarchical inheritance.
●​ It is not supported in Java because of multiple inheritance. It is possible to create a hybrid
inheritance without multiple inheritance.

Note -
●​ Object class is the supermost parent class in Java because every class
(predefined/user-defined)in Java is a child class (extends from the Object class) of the
object class.

Additional Information:
The java.lang.Object class is the root of the Java class hierarchy. All other classes in Java are
direct or indirect subclasses of Object. This means all objects in Java inherit the methods
defined in the Object class (e.g., toString(), equals(), hashCode(), getClass(), etc.).

●​ A parent class reference can hold the child class object, but a child class reference can't
hold a parent class object.
Example -
class ObjOfAnotherClass {
public static void main(String[] args) {
Parent obj_p = new Child(); //Child class gets extend from Parent
// Child obj_C = new Parent(); //Can't convert Parent object of
child reference
obj_p.P_func();
// obj_p.C_func();//Can't call child method using parent reference
}
}
class Parent {
public void P_func() {
System.out.println("Parent function of Parent Class");
}
}
class Child extends Parent{
public void C_func() {
System.out.println("Child function of Child Class");
}
}
// Parent function of Parent Class

Additional Information:
Parent reference to Child object: When you assign a child class object to a parent class
reference, it's because a child object is a type of its parent. The parent reference can then
access the methods and variables defined in the parent class that are also available in the child
class (possibly overridden). However, the parent reference cannot directly access methods or
variables that are specific to the child class. This is known as upcasting.

Child reference to Parent object: Conversely, a parent object is not necessarily a type of its
child. The parent class might not have the specific methods or variables defined in the child
class. Therefore, assigning a parent object to a child reference would lead to potential runtime
errors (specifically, ClassCastException if you try to cast it later without proper checking). This is
generally not allowed implicitly and requires explicit casting, which can be unsafe if the object is
not actually an instance of the child class. This is known as downcasting and should be done
with caution using instanceof checks.
Method overloading -
●​ Creating multiple methods with the same method name but different types of arguments
inside a single class is known as method overloading.

The Java compiler differentiates between overloaded methods based on their method signature,
which consists of the method name and the sequence of parameter types. The return type is not
part of the method signature and cannot be used to distinguish overloaded methods.The Java
compiler differentiates between overloaded methods based on their method signature, which
consists of the method name and the sequence of parameter types. The return type is not part of
the method signature and cannot be used to distinguish overloaded methods.

Example -
class ex1 {
public static void func(int x) {
System.out.println("Integer Argument function");
}
public static void func() {
System.out.println("No argument function");
}
public static void func(float fl) {
System.out.println("Float Argument function");
}
public static void func(boolean bool) {
System.out.println("Boolean Argument function");
}
public static void func(String str) {
System.out.println("String Argument function");
}
public static void main(String[] args) {
func();
func(10);
func(10f);
func(true);
func(null);
// func('a');
}
}
// No argument function
// Integer Argument function
// Float Argument function
// Boolean Argument function
// String Argument function

●​ In method overloading, the methods can be static as well as non static.

Example 1-
class ex2 {
public static void func(int num) {
System.out.println("Integer Argument Func");
}
public static void func(float fl) {
System.out.println("Floating argument Func");
}
public static void main(String[] args) {
func('a');
// func(10.3);
}
}
// Integer Argument Func

Here, for the character 'a' the upcasting is happening by the compiler. Hence, 'a is converted to
97 (ASCII value)

When func('a') is called, there is no direct func(char) method. However, Java performs implicit
widening (upcasting) of the char type to a compatible larger primitive type, which in this case is
int. Therefore, the func(int num) method is invoked with the ASCII value of 'a' (which is 97).

byte→short→char→int→long→float→double

Example 2-
class ex2 {
public static void func(int num) {
System.out.println("Integer Argument Func");
}
public static void func(float fl) {
System.out.println("Floating argument Func");
}

public static void main(String[] args) {


// func('a');
func(10.3);
}

}
// error: no suitable method found for func(double)
// func(10.3);
// ^
// method ex2.func(int) is not applicable
// (argument mismatch; possible lossy conversion from double to int)
// method ex2.func(float) is not applicable
// (argument mismatch; possible lossy conversion from double to
float)

Here, the compiler is unable to downcast the double value to an int or float. To execute it, we
have to explicitly convert the double to float or int.

When func(10.3) is called, the argument is a double literal. There are overloaded methods for int
and float, but Java does not perform implicit narrowing (downcasting) because it can lead to loss
of precision. The compiler cannot automatically convert a double to an int or a float without the
possibility of losing the decimal part. Hence, the compiler reports an error indicating that no
suitable overloaded method was found for the double argument. To make this work, you would
need to explicitly cast the double to either float (e.g., func(10.3f);) or int (e.g., func((int)10.3);).

Example 3-
class ex3 {
public static void func(long l) {
System.out.println("Long Argument Function");
}
public static void func(int num) {
System.out.println("Integer Argument Function");
}
public static void main(String[] args) {
func(10);
}
}
// Integer Argument Function
Here, the argument value 10 matches with the long as well as int, but it found the exact match
func(int), hence the Integer Argument Function executed.

When func(10) is called, the argument 10 is an int literal. There are overloaded methods for both
long and int. Java's method resolution mechanism prioritizes the most specific matching
overload. Since int is an exact match for the argument type, the func(int num) method is
executed, even though int can be implicitly widened to long.

Example 4-
class ex4 {
public static void func(byte b) {
System.out.println("Byte Argument Function");
}
public static void func(short sh) {
System.out.println("short Argument FUnction");
}
public static void main(String[] args) {
func(10);
}
}
// error: no suitable method found for func(int)
// func(10);
// ^
// method ex4.func(byte) is not applicable
// (argument mismatch; possible lossy conversion from int to byte)
// method ex4.func(short) is not applicable
// (argument mismatch; possible lossy conversion from int to short)

The 10 value is the default integer type. The compiler is unable to downcast it. Hence, we are
getting an error.

Similar to Example 2, when func(10) is called, the argument is an int. There are overloaded
methods for byte and short, which are smaller primitive types than int. Java does not perform
implicit narrowing conversions from int to byte or short because it can lead to data loss.
Therefore, the compiler cannot find a suitable overloaded method and reports an error. You
would need to explicitly cast the int to byte (e.g., func((byte)10);) or short (e.g., func((short)10);) if
you intended to call those specific overloads.

Example 5 -
class ex5 {
public static void func(String str) {
System.out.println("String Argument Function");
}
public static void func(Object obj) {
System.out.println("Object Argument Function");
}
public static void main(String[] args) {
func(null);
}
}
// String Argument Function

Here, the object is the parent of the string class when we provide a default value of null. The
compiler prioritizes the child class (String class) first.

When func(null) is called, null is a valid value for both String (since String is a reference type) and
Object (since Object is the superclass of all reference types). However, the Java compiler follows
the principle of choosing the most specific type. Since String is a more specific type than Object
for a null reference in this context, the func(String str) method is preferred and executed.

Example 6 -
class ex6 {
public static void func(String str) {
System.out.println("String class Argument Function");
}
public static void func(ex6 obj) {
System.out.println("Ex6 class Argument Function");
}
public static void main(String[] args) {
func(null);
}
}
// error: reference to func is ambiguous
// func(null);
// ^
// both method func(String) in ex6 and method func(ex6) in ex6 match

Here, it creates ambiguity as both classes can take null as an argument, and there is no relation
between the string class and user user-defined ex6 class. Hence the compiler is facing
ambiguity.
When func(null) is called here, null is a valid value for both the String parameter and the ex6
parameter (since ex6 is also a reference type). In this case, there is no inheritance relationship
between String and ex6. The compiler cannot determine which method is a "more specific"
match. Therefore, it results in an ambiguous method call error, as both methods are equally
applicable for the null argument.

You can fix this ambiguity by explicit casting:

class ex6 {
public static void func(String str) {
System.out.println("String class Argument Function");
}
public static void func(ex6 obj) {
System.out.println("Ex6 class Argument Function");
}
public static void main(String[] args) {
func((String)null);
}
}
// String class Argument Function

Examples on Method Overloading of Non Primitive argument type -


class Parent {
}
class Child extends Parent {
}
class GrandChild extends Child {
}
class Fun {
public static void func(Parent pob) {
System.out.println("Function with Parent object");
}
public static void func(Child cob) {
System.out.println("Function with Child object");
}
public static void func(Object ob) {
System.out.println("Function with Object Class");
}
}
class example1 {
public static void main(String[] args) {
Fun.func(null);
}
}
// Function with Child object

In the above code, func(null) is called. func(null) has three possible options: func(Parent),
func(Child) and func(Object). Object class is the parent of every class in Java. So, in between
Parent, Object, and Child classes, Child is the supermost child. Hence, the compiler prefers
calling func(Child) function.

class Parent {
}
class Child extends Parent {
}
class GrandChild extends Child {
}
class Fun {
public static void func(Parent pob) {
System.out.println("Function with Parent object");
}
public static void func(Child cob) {
System.out.println("Function with Child object");
}
public static void func(Object ob) {
System.out.println("Function with Object Class");
}
}
class example1 {
public static void main(String[] args) {
GrandChild gc = new GrandChild();
Fun.func(gc);
}
}
// Function with Child object

In the above code func(gc) (func(GrandChild)) is called. func(gc) has three possible options:
func(Parent), func(Child), and func(Object). Object class is the parent of every class in Java. So, in
between Parent, Object, and Child classes, Child is the supermost child. Also, func(GrandChild)
doesn't have any exact match inside the Fun class. Hence, func(gc) prefers calling the func(Child)
function.

class Parent {
}
class Child extends Parent {
}
class Random {
}
class Fun {
public static void func(Parent pob) {
System.out.println("Function with Parent object");
}
public static void func(Child cob) {
System.out.println("Function with Child object");
}
public static void func(Object ob) {
System.out.println("Function with Object Class");
}
}
class example1 {
public static void main(String[] args) {
Random rand = new Random();
Fun.func(rand);
}
}
// Function with Object Class

In the above example, we have a relationship between the Parent class and the Child class.
Random does not have any relation to Parent or Child. As usual, Object is the parent of all the
classes in Java. Hence, when func(Random) is called. It finds its relation with the func(Object).
Hence, func(Object) is executed.

class Parent {
}
class Child extends Parent {
}
class Random{
}
class Fun {
public static void func(Parent pob) {
System.out.println("Function with Parent object");
}
public static void func(Child cob) {
System.out.println("Function with Child object");
}
}
class example1 {
public static void main(String[] args) {
Random rand = new Random();
Fun.func(rand);
}
}
// error: no suitable method found for func(Random)
// Fun.func(rand);
// ^
// method Fun.func(Parent) is not applicable
// (argument mismatch; Random cannot be converted to Parent)
// method Fun.func(Child) is not applicable
// (argument mismatch; Random cannot be converted to Child)

In the above example, Random does not have any relation with Parent or Child. As the
func(Random) is unable to find any specific match it shows a compilation error.

Variable Argument Method -


●​ If we want to provide multiple numbers of values inside a single variable within the
argument part of any method then we should go for var arg method.
●​ We can denote the var arg method by using the triple dot(...).
●​ The var arg concept is otherwise known as a 1D array.
Example -
class example1 {
public static void func(int...x) {
System.out.println("Var Arg method executed");
}
public static void main(String[] args) {
func();
func(10);
func(1,2,3,4,5);
}
}
// Var Arg method executed
// Var Arg method executed
// Var Arg method executed

In the above example, functions with different signatures are executed because (int...x) takes
multiple values as an argument.
func(1,2,3,4,5)

The syntax Type... variableName in the method's parameter list indicates that the variableName
will accept zero or more arguments of the specified Type.
func()
func(1,2,3,4,5)

Inside the method, the var-arg parameter is treated as an array of the specified type. When you
call the method with a sequence of arguments, the Java compiler automatically packages these
arguments into an array and passes that array to the method.
1,2,3,4,5 as new int[] {1,2,3,4,5} and pass it to int[]x

●​ The var arg must be the last parameter of any method, or else it leads to a compilation
error.

This rule is in place to avoid ambiguity for the compiler when parsing the method arguments. If a
var-arg parameter were not the last, the compiler wouldn't know where the variable number of
arguments ends and the subsequent fixed parameters begin.

Valid invalid

func(int x, int...y) func(int...x,int y)

func(int x, String...str) func(String...str,int y)

func(int...x, int y): Invalid. If this were allowed, when calling the method, the compiler wouldn't
know how many of the initial arguments should be collected into the x array and where the
single y argument begins.

The Parent reference can access all the members that are defined in the Parent class (and
potentially overridden in the Child class).
How does a var-arg method work internally?
Step 1: Compilation Phase
When you declare func(int... x), the Java compiler internally rewrites it to:

public static void func(int[] x)

So at compile-time, this:
func(1, 2, 3, 4, 5);

is translated to:
func(new int[]{1, 2, 3, 4, 5});

Step 2: Runtime Execution

Argument Collection
The arguments 1, 2, 3, 4, 5 are collected and packed into an integer array:
int[] x = new int[] {1, 2, 3, 4, 5};

Inside the Method


At this point, x is a regular int array holding: {1, 2, 3, 4, 5}
public static void func(int... x) {
System.out.println("Var Arg method executed");
}

func(); // becomes func(new int[]{})


func(10); // becomes func(new int[]{10})
func(10, 20, 30); // becomes func(new int[]{10, 20, 30})

Example Explanation-
class P23_05_25 {
public static void func(int...x) {
}
public static void func(int[]x) {
}
public static void main(String[] args) {
}
}

The above example will show a compile-time error because (int...x) is a type of 1D array. Hence,
the method signatures are the same.
Write a program to print the sum of all the arguments passed to the var-arg
method.

class P23_05_25_2 {
public static int Sum(int...x) {
int Sum = 0;
for (int i = 0; i < x.length; i++) {
Sum+=x[i];
}
return Sum;
}
public static void main(String[] args) {
System.out.println(Sum());
System.out.println(Sum(10));
System.out.println(Sum(10,20,30));
System.out.println(Sum(10,20,30,40,50,60));
}
}
// 0
// 10
// 60
// 210

Example Explanation -
class P23_05_25_3 {
public static void func(int...x) {
System.out.println("Var arg Function");
}
public static void func(int x) {
System.out.println("Normal Function");
}
public static void main(String[] args) {
func(10);
}
}
// Normal Function

func(int) has two choices to execute. Generally, var arg has the least priority. Also, the func(int)
found its exact match.
Method overriding -
●​ Changing the implementation of the parent class method in the child class according to
the requirements of the child class is known as method overriding.
If the method has the same signature declared in both parent class and child class just
by changing the implementation part, then the parent class method gets overridden by
the child class.

Example -
class Parent {
public void func() {
System.out.println("Parent Function");
}
}
class Child extends Parent {
public void func() {
System.out.println("Child Function");//Parent method get
overridden by child method
}
}
public class mo_23_05_25 {
public static void main(String[] args) {
Parent pob = new Parent();//creating parent class object
Child cob = new Child();//Creating child class object
Parent pobj = new Child();//Creating child class object by parent
class object reference
pob.func();//Calling function using parent class reference
cob.func();//Calling function using child class reference
pobj.func();//Calling function using parent class reference but
pointing to Child class object
}
}
//Parent Function
//Child Function
//Child Function

Execution flow
pobj.func() → pobj pointing to child class object → the compiler search for the invoked func inside
the child class

●​ In method overriding method is resolved based on the runtime object or instance type.

●​ Method overriding is also known as runtime polymorphism, or dynamic polymorphism, or


late binding.

Rules for overriding -


●​ Method signature should be the same.
●​ We cannot change the return type of method overriding until version 1.5. From 1.7
onwards, the covariant concept is introduced.

Covariant concept -
●​ According to this concept, we can change the return type of method overriding.
●​ The covariant concept does not apply to primitive data types.

Introduced in Java 5 (not 1.7), the covariant return type allows you to override a method and
change the return type — but only if the new return type is a subtype of the original return type.

🔸 Covariant return types apply only to object/reference types — NOT to primitive types.

Valid Overridden Invalid Overridden

class Parent { class Parent {


public void func() { public void func() {
System.out.println("Parent Function"); System.out.println("Parent Function");
} }
} }
class Child extends Parent { class Child extends Parent {
public void func() { public int func() {
System.out.println("Child Function"); System.out.println("Child Function");
} return 10;
} }
//Same method signature and return type. }
//Return types are different, and int is a
primitive — not allowed.

class Parent { class Parent {


public int func() { public int func() {
System.out.println("Parent Function"); System.out.println("Parent Function");
return 10; return 10;
} }
} }
class Child extends Parent { class Child extends Parent {
public int func() { public double func() {
System.out.println("Child Function"); System.out.println("Child Function");
return 11; return 1.1;
} }
} }
//Same signature and return type. //Even though both are primitive, different
types are not allowed in overriding.

●​ It is applicable only for non primitive data types, but with some restrictions.
●​ Restriction -
○​ Child class method return type should be the child of the Parent class method
return type.

Valid Overridden Invalid Overridden

class Parent { class Parent {


public Parent func() { public void func() {
System.out.println("Parent Function"); System.out.println("Parent Function");
return null; return null;
} }
} }
class Child extends Parent { class Child extends Parent {
public Child func() { public String func() {
System.out.println("Child Function"); System.out.println("Child Function");
return null; return null;
} }
} }
//Child is a subtype of Parent — covariant //Return type void vs String — no relationship,
return allowed. so not allowed.

class Parent { class Parent {


public Object func() { public String func() {
System.out.println("Parent Function"); System.out.println("Parent Function");
return null; return null;
} }
} }
class Child extends Parent { class Child extends Parent {
public String func() { public Object func() {
System.out.println("Child Function"); System.out.println("Child Function");
return null; return null;
} }
} }
//String is a subtype of Object — allowed. //Object is not a subtype of String — so this is
not covariant and not allowed.

Note
Override restricts
●​ In different method signatures.
class Parent {
public void func() {
}
}
class Child extends Parent {
public void func(int x) {
}
}

●​ Static methods(static method cant be overridden)


class Parent {
public static void func() {
}
}
class Child extends Parent {
Public static void func() {
}
}

●​ Different primitive return type or changed return type


class Parent {
public int func() {
return 10;
}
}
class Child extends Parent {
public double func() {
return 1.1;
}
}

●​ In non primitive return type if child class method return type is a super class of parent
class method return type or no relation.
class Parent {
public String func() {
return null;
}
}
class Child extends Parent {
public Object func() {
return null;
}
}

When we create a parent class reference and assign it to a child class


object, it is valid, but when we try to refer a class object to another class
object, it will not be valid if those objects don't have any relation. How does
this work internally?

When a class Child extends a class Parent, it means that a Child object is a type of Parent. It
inherits all the public and protected members (fields and methods) of the Parent class.

Since a Child object inherently possesses all the characteristics of a Parent object, it's safe to
treat it through a Parent reference. The Parent reference can access all the members that are
defined in the Parent class (and potentially overridden in the Child class).
In real We are accessing all the properties (which are common in both parent and child class) of
child class but using parent class references also. That's why we are facing an overridden
method as we are accessing the child class properties only.
Bonus: Can We Assign Unrelated Objects via Casting?


A a = (A) new B(); // Compiles but throws ClassCastException at runtime
Java allows explicit casting between unrelated classes.

But it will throw a ClassCastException at runtime unless they are truly compatible.

Parent p = new Child();


Here can we access child properties using p?

No, you cannot directly access properties or methods that are unique to Child using the Parent
reference p.
Even though the object p refers to is of type Child, the reference type (Parent) doesn't know
about childMethod().

If we can't access, then what is the sense of this referral advantage?


How are the child's overridden methods accessible using that reference?

The goal isn't to access child-specific features — it's to ensure that common behavior defined in
the parent class can be extended or changed by child classes without changing the calling code.

By using parent references, your code becomes more flexible and easier to extend. You can add
new child classes without having to modify the code that operates on the parent type.

Modifier -
●​ It is something which is used to provide accessibility and deals with the functionality of
any class, methods and variables.
●​ Modifiers are of two types.
○​ Non access
○​ Access
●​ Non access -
○​ final
○​ static
○​ abstract
●​ Access -
○​ public
○​ protected
○​ default
○​ private

Access Modifier -

Public
●​ It applies to classes, methods, and variables.
●​ If any method or variable is declared as public, then we can access it inside the class,
outside the class, and outside the package also.

Example -
Inside the class -

package pac1;
public class Parent {
​ public void func() {
​ ​ System.out.println("Function called");
​ }​
​ public static void main(String[] args) {
​ ​ Parent robj = new Parent();
​ ​ robj.func();​ ​
​ }
}

Outside the class -


package pac1;
class Parent {​
​ public static void main(String[] args) {
​ ​ Random robj = new Random();
​ ​ robj.func();​ ​
​ }
}
class Random {
​ public void func() {
​ ​ System.out.println("Function calling--of random class");
​ }
}

Outside the package -


package pac2;
public class Random2 {
​ public void func() {
​ ​ System.out.println("calling function--Random2 class");
​ }
}
package pac1;
import pac2.Random2;
class Parent {
​ public static void main(String[] args) {
​ ​ Random2 robj = new Random2();
​ ​ robj.func();​ ​
​ }
}

To access a class of another package we need to import that class.


Modifier -
●​ It is something which is used to provide accessibility and deals with the functionality of
any class, methods and variables.
●​ Modifiers are of two types.
○​ Non access
○​ Access
●​ Non access -
○​ final
○​ static
○​ abstract
●​ Access -
○​ public
○​ protected
○​ default
○​ private

Access Modifier -

Public
●​ It applies to classes, methods, and variables.
●​ If any method or variable is declared as public, then we can access it inside the class,
outside the class, and outside the package also.

Example -
Inside the class -
package pac1;
public class Parent {
​ public void func() {
​ ​ System.out.println("Function called");
​ }​
​ public static void main(String[] args) {
​ ​ Parent robj = new Parent();
​ ​ robj.func();​ ​
​ }
}

Outside the class -


package pac1;
class Parent {​
​ public static void main(String[] args) {
​ ​ Random robj = new Random();
​ ​ robj.func();​ ​
​ }
}
class Random {
​ public void func() {
​ ​ System.out.println("Function calling--of random class");
​ }
}

Outside the package -


package pac2;
public class Random2 {
​ public void func() {
​ ​ System.out.println("calling function--Random2 class");
​ }
}
package pac1;
import pac2.Random2;
class Parent {
​ public static void main(String[] args) {
​ ​ Random2 robj = new Random2();
​ ​ robj.func();​ ​
​ }
}

To access a class of another package we need to import that class and that class needs to have
public access.

Protected -
●​ It is applicable for variables and methods, but not for any classes.
●​ If any method or variable is declared protected, we can access it inside the class, outside
the class, and outside the package, but inside an extended class (using a child class
object).

Inside the class -


package Protected1;
class Demo {
​ protected void func() {
​ ​ System.out.println("Protected function");
​ }
​ public static void main(String[] args) {
​ ​ Demo obj = new Demo();
​ ​ obj.func();
​ }
}
//Protected function

Outside the class -


package Protected1;
class Random {
​ protected void func2() {
​ ​ System.out.println("Protected function!!");
​ }
}
class Demo {
​ public static void main(String[] args) {
​ ​ Random obj = new Random();
​ ​ obj.func2();
​ }
}
//Protected function!!

Outside the package -


package Protected1;
public class Random {
​ protected void func2() {
​ ​ System.out.println("Protected function!!");
​ }
}
package Protected2;
import Protected1.Random;
class RanChild {
public static void main(String[] args) {
​ Random obj = new Random();
​ obj.func2(); //Not accessible
}
}
//The method func2() from the type Random is not visible

Outside the package, the protected method is not accessible in a normal class. But it is
accessible in an extended class.
line doesn't compile because Random is from another package and func2() is protected —
hence, the reference must be of the child class (not parent) to access it.

●​ If any method is declared as protected as well as non-static, and we are trying to access it
outside the package, then it is mandatory to create an object of the child class.
package Protected1;
public class Random {
​ protected void func2() {
​ ​ System.out.println("Protected function!!");
​ }
}
package Protected2;
import Protected1.Random;
class RanChild extends Random{
public static void main(String[] args) {
​ RanChild obj = new RanChild();
​ obj.func2();
}
}

●​ If any method is declared as protected as well as static, and we are trying to access it
outside the package, then we can create objects of both the parent and child class to
access the method.

package Protected1;
public class Random {
​ protected void func2() {
​ ​ System.out.println("Protected function!!");
​ }
​ protected static void func_st() {
​ ​ System.out.println("Protected static function!!");
​ }
}
package Protected2;
import Protected1.Random;
class RanChild extends Random {
public static void main(String[] args) {
​ RanChild obj = new RanChild();//Child class object
​ obj.func2();//Calling non static protected by child object
​ obj.func_st();//Calling static protected by child object
​ Random robj = new Random();//Parent class object
​ robj.func_st();//Calling static protected by parent object
​ Random.func_st();//Calling static protected by Class name
}
}
//Protected function!!
//Protected static function!!
//Protected static function!!
//Protected static function!!
Default -
●​ It applies to classes, methods, and variables.
●​ The default data members can be accessed inside the class, outside the class, but not
outside the package.

Inside the class -


package Default1;
class Default_demo {
​ void func_def() {
​ ​ System.out.println("!!Default method!!");
​ }
​ public static void main(String[] args) {
​ ​ Default_demo obj = new Default_demo();
​ ​ obj.func_def();
​ }
}
//!!Default method!!

Outside the class -


package Default1;
class Default_demo_2 {
​ void func_def_2() {
​ ​ System.out.println("--Default method another class--");
​ }
}
class Default_demo {
​ ​ public static void main(String[] args) {
​ ​ Default_demo_2 obj2 = new Default_demo_2();
​ ​ obj2.func_def_2();
​ }
}
//--Default method another class--

Private -
●​ It is only applicable for methods and variables, not for classes.
●​ The scope of the private modifier is only inside the class. It means we can't access the
private data members outside the class.
Example -
package Private;
class Demo_pr {
​ private void func() {
​ ​ System.out.println("--Private Function--");
​ }
​ public static void main(String[] args) {
​ ​ Demo_pr obj = new Demo_pr();
​ ​ obj.func();
​ }
}
//--Private Function--

Non access Modifiers -


●​ The modifier which deals with the functionality of any class, methods and variables is
known as non-access modifier.

Final -
●​ Final is applicable for class, methods and variables.
●​ If a variable is declared as final then we can't reinitialize it.
package Final;
class Final_demo {
​ final int lo = 30;
​ public static void main(String[] args) {
​ ​ final int x = 20;
​ ​ System.out.println(x);
​ ​ x = 10;
​ }
}
//The final local variable x cannot be assigned. It must be blank and not
using a compound assignment

●​ If a class is declared as final, then we can’t inherit that class.


Invalid -
package Final;
final class final_demo_2 {
}
class child_2 extends final_demo_2{

}
//he type child_2 cannot subclass the final class final_demo_2

Valid -
package Final;
class final_demo_2 {
}
class child_2 extends final_demo_2{

}
●​ Final class can inherit the properties of a normal class. But we cant further extend that
final child class.
package Final;
class final_demo_2 {
}
final class child_2 extends final_demo_2{

}

●​ If a method is declared as final, we can't override that method.


(A normal method inside a final class behaves like any other method — it is not
automatically final. It cannot be overridden because the class itself cannot be extended.
But the method is not final unless explicitly marked.)

Example -
package Final;
class final_demo_2 {
​ final void func() {
​ ​ System.out.println("Final method");
​ }
}
class child_2 extends final_demo_2{
​ final void func() {
​ ​ System.out.println("Final method2");
​ }
}
//Cannot override the final method from final_demo_2

●​ Final class can contain both final as well as normal methods.

package Final;
class final_demo_2 {
​ final static void func() {
​ ​ System.out.println("Final method");
​ }
​ public static void func2() {
​ ​ System.out.println("Normal method");
​ }
​ public static void main(String[] args) {
​ ​ func();
​ ​ func2();
​ }
}
//Final method
//Normal method

●​ The method inside the final class acts as the final method because another class can’t
inherit the properties of a final class. Because we can't extend any class from a final class.

package Final;
final class final_demo_2 {
​ public void func3() {
​ ​ System.out.println("Normal method but act as final method");
​ }​
}
class final_demo_child extends final_demo_2{
​ public void func3() {
​ ​ System.out.println("Normal method but act as final method");
​ }​
}

●​ Final class can be instantiated , meaning we can create objects of the class.
package Final;
final class final_demo_2 {
​ final static void func() {
​ ​ System.out.println("Final method");
​ }
​ public static void func2() {
​ ​ System.out.println("Normal method");
​ }
​ public void func3() {
​ ​ System.out.println("Normal method but act as final method");
​ }​
}
class final_demo_child {
​ public static void main(String[] args) {
​ ​ final_demo_2 obj = new final_demo_2();
​ ​ obj.func3();
​ }​
}
//Normal method but act as final method

Question -
Can we change the modifier of any overridden method?
Yes, we can change. But the scope of the modifier must be increased from parent to child.
Invalid -
package Override;
class Parent {
​ public void func() {
​ ​ System.out.println("Public method");
​ }
}
class Child extends Parent {
​ protected void func() {
​ ​ System.out.println("Protected method");
​ }
}
class Over_demo {
​ public static void main(String[] args) {
​ ​ Parent obj = new Child();
​ ​ obj.func();
​ }
}
//Exception in thread "main" java.lang.Error: Unresolved compilation
problem:
//​ Cannot reduce the visibility of the inherited method from Parent
//​ at Override.Child.func(Over_demo.java:8)
//​ at Override.Over_demo.main(Over_demo.java:17)

Valid -
package Override;
class Parent {
​ protected void func() {
​ ​ System.out.println("--Protected method--");
​ }
}
class Child extends Parent {
​ public void func() {
​ ​ System.out.println("==Public method==");
​ }
}
class Over_demo {
​ public static void main(String[] args) {
​ ​ Parent obj = new Child();
​ ​ obj.func();
​ }
}
//==Public method==

Scope -
Public > Protected > Default > Private

Access Public Protected Default Private


Modifiers

Accessibility for Public methods Protected Default methods Private methods


Override can be methods can be can be can't be
methods overridden to overridden to overridden to overridden
public only protected or default, because we
public protected, and can't inherit the
public private methods

Abstract -
●​ It is applicable for methods and classes but not for variables.
●​ If a class is declared abstract, we can't create objects of that class.
class Demo {
public void func() {
System.out.println("Function calling");
}
public static void main(String[] args) {
Demo obj = new Demo();
obj.func();//Function calling
// Demo_abs obj2 = new Demo_abs();//Not instantiated
Child_abs objc = new Child_abs();
objc.func_abs();//Calling abstract function
}
}
abstract class Demo_abs{
void func_abs() {
System.out.println("Calling abstract function");
}
}
class Child_abs extends Demo_abs{

}
// rror: Demo_abs is abstract; cannot be instantiated
// Demo_abs obj2 = new Demo_abs();
// ^
// 1 error

The above example shows that we are unable to instantiate an abstract class. Hence, we
extended the abstract class and accessed the abstract class methods by the extended class.
●​ If we declare any methods as abstract, then we can't provide any implementation of that
method.
class Demo2 {
public void func() {
System.out.println("!!Method calling!!");
}
}
public abstract class Demo2_abs{
abstract void func_abs() {//Implementation is invalid
}
}
// Demo2_abs.java:8: error: abstract methods cannot have a body
// abstract void func_abs() {
// ^
// 1 error

The implementation of the abstract class shows an error.

class Demo2 {
public void func() {
System.out.println("!!Method calling!!");
}
}
public abstract class Demo2_abs{
abstract void func_abs();//Just declaring abstract method is valid
public static void main(String[] args) {
Demo2 obj = new Demo2();
obj.func();//!!Method calling!!
}
}

●​ Abstract classes contain both abstract and normal/concrete (non-abstract) methods.

public abstract class Demo2_abs{


abstract void func_abs();//Just declaring abstract method is valid
public void func() {
System.out.println("!!Method calling!!");
}
public static void main(String[] args) {
}
}

The above example contains an abstract class that contains an abstract method, a void method,
and a main method.
●​ If a method is abstract, it is mandatory to declare the class with an abstract modifier.
class Demo3 {
abstract void func();
public static void main(String[] args) {
}
}
// Demo3.java:1: error: Demo3 is not abstract and does not override
abstract method func() in Demo3
// class Demo3 {
// ^
// 1 error

●​ Abstract classes can be inherited.


abstract class Demo3 {
abstract void func();
public static void main(String[] args) {

}
}
class CHILD_abs extends Demo3{
public void func() {

}
}

Question
How to provide implementation to any abstract method?
Ans - By overriding the method.
if a subclass also doesn’t provide an implementation, it must itself be declared abstract. Also
remember to change the scope of the overridden abstract method. It should not be private.

Scope – public > protected > default > abstract > private
abstract class Demo3 {
abstract void func();
public static void main(String[] args) {
CHILD_abs obj = new CHILD_abs();
obj.func();//Implementing abstract class
}
}
class CHILD_abs extends Demo3{
public void func() {
System.err.println("Implementing abstract class");
}
}

Another example -
abstract class Demo4 {
abstract public void func1();
abstract public void func2();
}
abstract class Demo4_son extends Demo4{
public void func1() {
System.out.println("Function one Implemented");
}
}
class Demo4_grand_son extends Demo4_son{
public void func2() {
System.out.println("Function two Implemented");
}
}
public class Main_method{
public static void main(String[] args) {
Demo4_grand_son gobj = new Demo4_grand_son();
gobj.func1();// Function one Implemented
gobj.func2();// Function two Implemented
}
}

Difference between Abstract and Final


Abstract Final

Abstract modifier does not apply to variables. The final modifier applies to a variable

We can't create objects of an abstract class. We can create objects for the final class.

Abstract classes can be inherited. Final class cant be inherited.

Abstract method can’t have a body Final class has body(can implement)
(Implementation part).

Abstract method can be overridden. The final method can't be overridden.

If a method is abstract, then the class must If a method is final it is not mandatory to
have an abstract modifier. declare the class as final.

A normal (non - abstract) method inside an A normal method inside a final class behaves
abstract class behaves as a normal method. as a final method. (A normal method inside a
final class behaves like any other method — it
is not automatically final. It cannot be
overridden because the class itself cannot be
extended. But the method is not final unless
explicitly marked.)

Method Hiding -
●​ Changing the implementation of a parent class method inside the child class, as per the
child class requirement, by using a static method is known as method hiding.
●​ In method hiding, methods are of static type.
●​ The method resolution takes place based on reference type.
●​ The compiler is responsible for method resolution.
●​ It is otherwise known as compile-time polymorphism, static polymorphism, static method
dispatch, and early binding.

class Demo4 {
public static void func() {
System.out.println("Static function\nDemo4 class");
}
}
class Demo4_son extends Demo4 {
public static void func() {
System.out.println("Static function\nDemo4_son class");
}
}
public class Main {
public static void main(String[] args) {
Demo4 pobj = new Demo4();
Demo4_son cobj = new Demo4_son();
Demo4 pobj_cref = new Demo4_son();
pobj.func();
cobj.func();
pobj_cref.func();
}
}
// Static function
// Demo4 class
// Static function
// Demo4_son class
// Static function
// Demo4 class

A static method cant be overridden to a non static method. Also a non-static method cant be
hidden over a static method.
Example -
class Demo4 {
public static void func() {
System.out.println("Static function\nDemo4 class");
}
}
class Demo4_son extends Demo4 {
public void func() {//This instance method cannot override the static
method from Demo4
System.out.println("Static function\nDemo4_son class");
}
}

class Demo4 {
public void func() {
System.out.println("Static function\nDemo4 class");
}
}
class Demo4_son extends Demo4 {
public static void func() {//This static method cannot hide the
instance method from Demo4
System.out.println("Static function\nDemo4_son class");
}
}

Property Overriding Method Hiding

Applies to Non-static methods Static methods

Resolution Runtime (dynamic binding) Compile-time (early binding)


(polymorphism)

Reference type affects? No — object type decides Yes — reference type decides
method method

Keyword needed @Override (optional but No annotation for hiding


useful)

Constructor -

What is a constructor?
●​ Whenever we create an object, some piece of code gets executed automatically to
perform the initialization of the object. This piece of code is known as a constructor.
Example -
public class Demo {
public static void main(String[] args) {
new Const();
}
}
class Const {
Const() {
System.out.println("Constructor called");
}
}

●​ It is a special type of method that is executed whenever we create an object to perform


initialization of an object.
Rules for writing a constructor -
●​ Class name and constructor name should be the same.
●​ Return type is not applicable for constructors, even void. If you mention void or any
non-access modifier, then it will be considered as a method.

public class Demo {


public static void main(String[] args) {
// new Const();
new Const().Const();
}
}
class Const {
void Const() {
System.out.println("Method having constructor name");
}
}
// Method having constructor name

●​ Creating methods whose name is the same as the class name is not recommended.

public class Demo {


public static void main(String[] args) {
// new Const();
new Const().Const();
}
}
class Const {
Const() {
System.out.println("Constructor called");
}
void Const() {
System.out.println("Method having constructor name");
}
}
// Constructor called
// Method having constructor name

●​ The only modifier that applies to constructors is the access modifier.


Types of constructors -
●​ There are two types of constructors.
○​ No argument constructor: (a constructor without any arguments.)

public class Demo {


public static void main(String[] args) {
new Const2();
}
}
class Const2{
Const2(){
System.out.println("==No argument constructor==");
}
}
//==No argument constructor==

○​ Parameterized constructor: (Constructor with argument)

public class Demo {


public static void main(String[] args) {
new Const2(12);
}
}
class Const2{
Const2(int x){
System.out.println("==Parameterized constructor==");
}
}
//==Parameterized constructor==

Default constructor -
●​ The compiler is responsible for generating the default constructor.

class Const3{
Const3() {
super();
}
}
●​ The above is the visualization of the default constructor.

●​ When there is no constructor explicitly defined in our class, then the default constructor is
generated by the compiler.
●​ Every class in Java contains a constructor, either default constructor by the compiler or
customized constructor generated by the programmer.

Prototype of default constructor -


●​ Every default constructor in Java is a no-argument constructor.
●​ There is only one statement present inside the default constructor which is super()(call to
super).
●​ The default constructor will have the same modifier as class (public or default).

Case 1 :
●​ The first statement inside the constructor should be either super() or this().

invalid valid

public class Demo { public class Demo {


public static void public static void
main(String[] args) { main(String[] args) {
new Const3(); new Const3();
} }
} }
class Const3{ class Const3{
Const3() { Const3() {
super();
System.out.println("COnstructor System.out.println("COnstructor
calling"); calling");
super(); }
} }
} // COnstructor calling
// Demo.java:32: error: flexible
constructors is a preview feature
and is disabled by default.
// super();
// ^
// (use --enable-preview to
enable flexible constructors)
// 1 error

Case 2 :
●​ We cannot write both this() and super() inside a constructor.
class Const4{
Const4() {
this();
super();
System.out.println("constructor calling");
}
}

Case 3 :
●​ If we are not mentioning either super() or this(), then the compiler will always place super()
as the first statement.

Difference between keywords and constructors

this, super this(), super()

These are keywords. These are constructor calls.

These can be used to refer to super and These can be used to call super class and
current class non static variables, current class constructor, respectively.
respectively.

These can be used anywhere except static These can be used only inside the
areas. constructor.

These can be used any number of times. These can be used only once (inside
constructor).

public class demo4 {


public static void main(String[] args) {
Child cob = new Child();
cob.func();
}
}
class Parent{
int x = 10;
}
class Child extends Parent {
int x = 20;
public void func() {
System.out.println("Current class nonstatic variable:
"+this.x);//20 - this refer to current class nonstatic variable
System.out.println("Parent class nonstatic variable:
"+super.x);//10 - super refer to parent class non static variable
}
}
Current class nonstatic variable: 20
// Parent class nonstatic variable: 10

The above example shows calling this class and the parent class non static variables using the
this and super keywords.

Constructor overloading -
●​ Explicitly define multiple constructors with different types of arguments.

public class demo5 {


public static void main(String[] args) {
new Demo();
new Demo(10);
new Demo(12.5);
new Demo(true);
}
}
class Demo{
Demo() {
System.out.println("No argument constructor");
}
Demo(int x) {
System.out.println("Integer type argument constructor");
}
Demo(double x) {
System.out.println("Double type argument constructor");
}
Demo(boolean x) {
System.out.println("Boolean type argument constructor");
}
}
// No argument constructor
// Integer type argument constructor
// Double type argument constructor
// Boolean type argument constructor

Constructor Chaining -
●​ Calling one constructor from another constructor is known as constructor chaining.
●​ This can be achieved using
○​ Call to this (this())
public class demo5 {
public static void main(String[] args) {
System.out.println("=======Creating new Demo2()=======\n");
new Demo2();
System.out.println("\n=======Creating new Demo2(10)=======\n");
new Demo2(10);
System.out.println("\n=======Creating new Demo2(10.3)=======\n");
new Demo2(10.3);
System.out.println("\n=======Creating new Demo2(true)=======\n");
new Demo2(true);
}
}
class Demo2{
Demo2() {
this(10);
//Demo2(10);//is treated like a method call, but constructors
aren’t regular methods and can’t be called like that.
System.out.println("No argument cosntructor");
}
Demo2(int x) {
this(12.4);
System.out.println("Integer type argument cosntructor");
}
Demo2(double x) {
this(true);
System.out.println("Double type argument cosntructor");
}
Demo2(boolean x) {
System.out.println("Boolean type argument cosntructor");
}
}
// =======Creating new Demo2()=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor
// No argument cosntructor

// =======Creating new Demo2(10)=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor

// =======Creating new Demo2(10.3)=======

// Boolean type argument cosntructor


// Double type argument cosntructor

// =======Creating new Demo2(true)=======

// Boolean type argument cosntructor

○​ Call to super(super())

public class demo5 {


public static void main(String[] args) {
new Child();
}
}
class Parent{
Parent(int num) {
System.out.println("Parent class constructor");
}
}
class Child extends Parent{
Child() {
super(19);
System.out.println("Child constructor");
}
}
// Parent class constructor
// Child constructor
public class demo5 {
public static void main(String[] args) {
new Parent(10);
}
}
class Parent{
Parent(int num) {
System.out.println("Parent class constructor");
}
}
class Child extends Parent{
Child() {
super(19);
System.out.println("Child constructor");
}
}
// Parent class constructor

Explanation:
The main method creates an object of the Parent class.
The Child class is present but unused, so its constructor does not run.

●​ To call three constructors, we have to create three objects, which is not good
programming practice. To overcome this, we will use a call to this.

public class demo5 {


public static void main(String[] args) {
System.out.println("=======Creating new Demo2()=======\n");
new Demo2();
System.out.println("\n=======Creating new Demo2(10)=======\n");
new Demo2(10);
System.out.println("\n=======Creating new Demo2(10.3)=======\n");
new Demo2(10.3);
System.out.println("\n=======Creating new Demo2(true)=======\n");
new Demo2(true);
}
}
class Demo2{
Demo2() {
this(10);
//Demo2(10);//is treated like a method call, but constructors
aren’t regular methods and can’t be called like that.
System.out.println("No argument cosntructor");
}
Demo2(int x) {
this(12.4);
System.out.println("Integer type argument cosntructor");
}
Demo2(double x) {
this(true);
System.out.println("Double type argument cosntructor");
}
Demo2(boolean x) {
System.out.println("Boolean type argument cosntructor");
}
}
// =======Creating new Demo2()=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor
// No argument cosntructor

// =======Creating new Demo2(10)=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor

// =======Creating new Demo2(10.3)=======


// Boolean type argument cosntructor
// Double type argument cosntructor

// =======Creating new Demo2(true)=======

// Boolean type argument cosntructor

Recursive constructor invocation-

public class demo5 {


public static void main(String[] args) {
new Random();
}
}
class Random {
Random(){
this();
System.out.println("random class const");
}
}

public class demo5 {


public static void main(String[] args) {
new Dog();
}
}
class Animal {
Animal() {
System.out.println("Animal class Constructor");
}
}
class Dog extends Animal {
Dog() {
System.out.println("Dog class constructor");
}
}
// Animal class Constructor
// Dog class constructor

Can we override a constructor?


●​ The constructor can't be overridden because the class name and the constructor name
are different.

Initializing the object using the constructor.

public class Demo6 {


public static void main(String[] args) {
Employee Tan = new Employee("Tanmoy", 26, "CTC");
Tan.Info();
}
}
class Employee {
String name;
int age;
String address;

Employee(String name, int age, String address) {


this.name = name;
this.age = age;
this.address = address;
}

public void Info() {


System.out.println("Name of the employee: " + name);
System.out.println(name + " is " + age + " years old.");
System.out.println(name + " lives in " + address + ".");
}
}
// Name of the employee: Tanmoy
// Tanmoy is 26 years old.
// Tanmoy lives in CTC

What if we declare the constructor as private?


●​ If we declare the constructor private, we can’t use it outside of the class.
Copy constructor
●​ Creating a new object from an existing object(initialize a new object from a current object
by copying the properties)

public class copy_const {


public static void main(String[] args) {
constr obj1 = new constr("Tanmoy", 25);
constr obj2 = new constr(obj1);
obj1.info();
obj2.info();
}
}
class constr{
String name;
int age;
constr(String name, int age) {
this.name = name;
this.age = age;
}
constr(constr obj) {
name = obj.name;
age = obj.age;
}
public void info(){
System.err.println("Name of the employee: "+ name);
System.err.println("Age of the employee: "+ age);
}
}
// Name of the employee: Tanmoy
// Age of the employee: 25
// Name of the employee: Tanmoy
// Age of the employee: 25

Interface -
●​ It is the medium between the user and the device.
●​ Syntax -
interface interface_name{
}
Interface variable -
●​ Every variable inside the interface is by default public, static, and final.
●​ Public: We can access it from everywhere.
●​ Final: We can't change the value of the variable.
●​ Static: since we can't create an interface object, it can't be non-static.
Since it is by default public, it can't be a local variable.

Case 1:
●​ Interface variables must be initialized. (Only declarations are not acceptable as they are
final.)

invalid valid

interface Demo { interface Demo {


int x; int x = 10;
} }

Case 2:
●​ Interface variables can’t be modified. (as they are final by default).

valid invalid

public class one implements Demo { public class one implements Demo {
public static void public static void
main(String[] args) { main(String[] args) {
int x = 20; x = 20;
System.out.println(x);//20 System.out.println(x);
} }
} }
interface Demo { interface Demo {
int x = 10; int x = 10;
} }
// one.java:3: error: cannot assign
In the above example, we are declaring a new a value to static final variable x
variable inside the main method. So that new // x = 20;
variable is the local variable.
// ^
// 1 error

In the above example, we are trying to modify


the final variable of the interface. That's why
we are getting an error.

Case 3:
●​ Interface variables can be accessed with the help of the interface name.

public class one implements Demo, Remo {


public static void main(String[] args) {
System.out.println(x);
}
}
interface Demo {
int x = 10;
}
interface Remo{
int x = 20;
}
// one.java:4: error: reference to x is ambiguous
// System.out.println(x);
// ^
// both variable x in Demo and variable x in Remo match
// 1 error

✅ How to fix it?


public class one implements Demo, Remo {
public static void main(String[] args) {
System.out.println(Demo.x);
System.out.println(Remo.x);
}
}
interface Demo {
int x = 10;
}
interface Remo{
int x = 20;
}
// 10
// 20

Interface method -
●​ All the methods inside the interface are, by default, public and abstract (unless they are
explicitly default or static (Java 8+).
●​ That's why the interface is also known as an abstract class. (because of the presence of
abstract methods).

public class one implements Demo{


public void func1() {
System.out.println("Function one");
}
public void func2() {
System.out.println("Function two");
}
public static void main(String[] args) {
one obj = new one();
obj.func1();
obj.func2();
}
}
interface Demo {
void func1();
void func2();
}
// Function one
// Function two

●​ From version 1.8 onwards the default method can be declared inside the interface (with a
default keyword).
○​ Syntax -
default void func(){
System.out.println();
}
●​ We can call default methods by creating an object of the child class (implemented class).
public class one implements Remo{
public static void main(String[] args) {
one obj = new one();
obj.func();
}
}
interface Remo{
default void func() {
System.out.println("Default method");
}
}
// Default method

●​ In version 1.8, static methods are also allowed inside the interface.
●​ Static methods are not inherited by the child class means we can't call a static method of
the interface by creating an object of the child class.
●​ We can access the static methods of the interface using the interface name.

public class one implements Remo{


public static void main(String[] args) {
Remo.func_st();
}
}
interface Remo{
static void func_st() {
System.out.println("Static method");
}
}
// Static method

Note -
●​ We can declare the main method inside the interface.

Case 1 -
●​ If more than one interface contains methods with the same method signature then in the
implemented class we have to provide implementation at most once.
public class three {
public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A,B{
public void func() {
System.out.println("Multiple methods same implementations");
}
}
interface A{
void func();

}
interface B{
void func();

}
//Multiple methods same implementations

Case 2 -
●​ If more than one interface contains methods with the same method signature but different
primitive type return types, then we can't provide an implementation because of the
covariant concept.
public class four {

}
class Demo implements A,B{
public float func() {
return 0;
}
}
interface A{
int func();

}
interface B{
float func();

}
// four.java:4: error: Demo is not abstract and does not override abstract
method func() in A
// class Demo implements A,B{
// ^
// four.java:8: error: func() in Demo cannot implement func() in A
// public float func() {
// ^
// return type float is not compatible with int
// 2 errors

Case 3 -
●​ If more than one interface contains the same method signature but different non primitive
type return type we can provide implementation according to the covariant concept.
public class five {
public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A, B {
public String func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
String func();

}
interface B {
Object func();

}
//Two non primitive return one implementation

public class five {


public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A, B {
public Object func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
String func();

}
interface B {
Object func();

}
// five.java:7: error: Demo is not abstract and does not override abstract
method func() in A
// class Demo implements A, B {
// ^
// five.java:8: error: func() in Demo cannot implement func() in A
// public Object func() {
// ^
// return type Object is not compatible with String
// 2 errors

public class five {


public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A, B {
public Demo func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
A func();
}
interface B {
B func();

}
// Two non primitive return one implementation

public class five {


public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Parent{

}
class Child extends Parent {

}
class Demo implements A, B {
public Child func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
Child func();

}
interface B {
Parent func();

}
// Two non primitive return one implementation
Factory method -
●​ It is the type of method that is called by its class name, and it returns the object of that
class.

public class one {


public static void main(String[] args) {
Runtime r1 = Runtime.getRuntime();
Runtime r2 = Runtime.getRuntime();
System.out.println(r1 == r2);
}
}
//true

Runtime is a predefined class and getRuntime() is a predefined method.

Wap to create a user defined factory method -

public class two {


static two t = new two();
public static two geTwo() {
return t;
}
public static void main(String[] args) {
two t1 = two.geTwo();
two t2 = two.geTwo();
System.out.println(t1 == t2);
}
}
// true

Case for the constructor -

Case 1 -
●​ If a constructor is declared private, we can't create objects outside of the class.

Valid Invalid

public class demo8 { public class demo8 {


public static void public static void
main(String[] args) { main(String[] args) {
Demo d = new Demo(); Demo d = new Demo();
} }
} }
class Demo { class Demo {
Demo() { private Demo() {
System.out.println("Constructor System.out.println("Constructor
created"); created");
} }
} }
// Constructor created // demo8.java:3: error: Demo() has
private access in Demo
// Demo d = new Demo();
// ^
// 1 error

Case 2 -
●​ If a constructor is declared as private inside the class, then no one can inherit the
properties of that class.
public class demo8 {
public static void main(String[] args) {
}
}
class Demo {
private Demo() {
System.out.println("Constructor created");
}
}
class subDemo extends Demo {

}
// demo8.java:12: error: Demo() has private access in Demo
// class subDemo extends Demo {
// ^
// 1 error
Singleton class -
●​ If we are allowed to create only one object (maximum one) of a class, then that class is
known as the singleton class.
●​ To create a singleton class, we required a static variable, a private constructor, and a
factory method.
public class one {
private one() {
System.out.println("Private Constructor");
}
static one o = new one();
public static one getOne(){
return o;
}
public static void main(String[] args) {
one o1 = one.getOne();
one o2 = one.getOne();
System.out.println(o1 == o2);
}
}
// Private Constructor
// true

Static Block -
●​ This block type will be executed before the main method at the time of class loading.

public class one { public class one {


public static void static {
main(String[] args) { System.out.println("Static
System.out.println("Main Block");
Block"); }
} public static void
} main(String[] args) {
// Main Block System.out.println("Main
Block");
}
}
// Static Block
// Main Block

public class one {


static {
System.out.println("Static Block 1");
}
public static void main(String[] args) {
System.out.println("Main Block");
}
static {
System.out.println("Static Block 2");
}
}
// Static Block 1
// Static Block 2
// Main Block

After executing all the static blocks, the main method will execute.

Static control flow -

Step 1 (Identification) -
●​ Identification of static data members from top to bottom, and at the time of identification,
the static variable can be initialized with its default value(by the JVM).

Step 2 -
●​ Initialization of static variable and execution of static block from top to bottom.

Step 3 -
●​ Execution of the main method.

Example -
public class one {
static int x = 10;
static {
System.out.println("Static Block 1");
func1();
}
public static void func1() {
System.out.println(y);
}
public static void main(String[] args) {
System.out.println("Main Block Start");
func1();
System.out.println("Main Block End");
}
static {
System.out.println("Static Block 2");
func2();
}
public static void func2() {
System.out.println(x);
}
static int y = 20;
}
// Static Block 1
// 0
// Static Block 2
// 10
// Main Block Start
// 20
// Main Block End

Step 1 -
X=0
Y=0

o/p -

Step 2 -
X = 10
Y = 20

o/p -
Static Block 1
0
Static Block 2
10

Step 3-

o/p -
Main Start
20
Main End

●​ Without the main method, we can compile the program, but we can't run it. (Compile
using: javac -source 1.6 test.java)
public class two {
static {
System.out.println("Static block");
}
}

Javac file_name.java
Java class_name

class twoA {
static {
System.out.println("Static block");
}
}

Java file_name.java
Static block
main() not found
class twoA {
static {
System.out.println("Static block");
System.exit(0);
}
}

Java file_name.java
RIWO (Read Indirectly Write Only)
●​ At the time of identification, when the variable is assigned with default value, then we can
say that the variable is in the RIWO state.

Direct Read
●​ If we print any variable inside any static block, then it is known as a direct read.

public class three {


static int x = 10;
static {
System.out.println(x);
}
public static void main(String[] args) {

}
}
// 10

Indirect Read -
●​ If we print any variable inside the method, then it is known as an indirect read.

public class three {


static int x = 10;
static {
func1();
}
public static void func1() {
System.out.println(x);
}
public static void main(String[] args) {

}
}
// 10
Case 1 -
●​ If a variable is not in the RIWO state, then we can perform both direct read and indirect
read.

Case 2 -
●​ If a variable is in the RIWO state, then we can’t perform a direct read.
public class three {
static {
System.out.println(x);
}
static int x = 10;
public static void main(String[] args) {

}
}
// three.java:4: error: illegal forward reference
// System.out.println(x);
// ^
// 1 error

Case 3 -
●​ If a variable is in the RIWO state, then we can perform only an indirect read.
public class three {
static {
func1();
}
public static void func1() {
System.out.println(x);
}
static int x = 10;
public static void main(String[] args) {

}
}
// 0
}
}

Property Overriding Method Hiding

Applies to Non-static methods Static methods

Resolution Runtime (dynamic binding) Compile-time (early binding)


(polymorphism)

Reference type affects? No — object type decides Yes — reference type decides
method method

Keyword needed @Override (optional but No annotation for hiding


useful)

Constructor -

What is a constructor?
●​ Whenever we create an object, some piece of code gets executed automatically to
perform the initialization of the object. This piece of code is known as a constructor.
Example -
public class Demo {
public static void main(String[] args) {
new Const();
}
}
class Const {
Const() {
System.out.println("Constructor called");
}
}

●​ It is a special type of method that is executed whenever we create an object to perform


initialization of an object.
Rules for writing a constructor -
●​ Class name and constructor name should be the same.
●​ Return type is not applicable for constructors, even void. If you mention void or any
non-access modifier, then it will be considered as a method.

public class Demo {


public static void main(String[] args) {
// new Const();
new Const().Const();
}
}
class Const {
void Const() {
System.out.println("Method having constructor name");
}
}
// Method having constructor name

●​ Creating methods whose name is the same as the class name is not recommended.

public class Demo {


public static void main(String[] args) {
// new Const();
new Const().Const();
}
}
class Const {
Const() {
System.out.println("Constructor called");
}
void Const() {
System.out.println("Method having constructor name");
}
}
// Constructor called
// Method having constructor name

●​ The only modifier that applies to constructors is the access modifier.


Types of constructors -
●​ There are two types of constructors.
○​ No argument constructor: (a constructor without any arguments.)

public class Demo {


public static void main(String[] args) {
new Const2();
}
}
class Const2{
Const2(){
System.out.println("==No argument constructor==");
}
}
//==No argument constructor==

○​ Parameterized constructor: (Constructor with argument)

public class Demo {


public static void main(String[] args) {
new Const2(12);
}
}
class Const2{
Const2(int x){
System.out.println("==Parameterized constructor==");
}
}
//==Parameterized constructor==

Default constructor -
●​ The compiler is responsible for generating the default constructor.

class Const3{
Const3() {
super();
}
}
●​ The above is the visualization of the default constructor.

●​ When there is no constructor explicitly defined in our class, then the default constructor is
generated by the compiler.
●​ Every class in Java contains a constructor, either default constructor by the compiler or
customized constructor generated by the programmer.

Prototype of default constructor -


●​ Every default constructor in Java is a no-argument constructor.
●​ There is only one statement present inside the default constructor which is super()(call to
super).
●​ The default constructor will have the same modifier as class (public or default).

Case 1 :
●​ The first statement inside the constructor should be either super() or this().

invalid valid

public class Demo { public class Demo {


public static void public static void
main(String[] args) { main(String[] args) {
new Const3(); new Const3();
} }
} }
class Const3{ class Const3{
Const3() { Const3() {
super();
System.out.println("COnstructor System.out.println("COnstructor
calling"); calling");
super(); }
} }
} // COnstructor calling
// Demo.java:32: error: flexible
constructors is a preview feature
and is disabled by default.
// super();
// ^
// (use --enable-preview to
enable flexible constructors)
// 1 error

Case 2 :
●​ We cannot write both this() and super() inside a constructor.
class Const4{
Const4() {
this();
super();
System.out.println("constructor calling");
}
}

Case 3 :
●​ If we are not mentioning either super() or this(), then the compiler will always place super()
as the first statement.

Difference between keywords and constructors

this, super this(), super()

These are keywords. These are constructor calls.

These can be used to refer to super and These can be used to call super class and
current class non static variables, current class constructor, respectively.
respectively.

These can be used anywhere except static These can be used only inside the
areas. constructor.

These can be used any number of times. These can be used only once (inside
constructor).

public class demo4 {


public static void main(String[] args) {
Child cob = new Child();
cob.func();
}
}
class Parent{
int x = 10;
}
class Child extends Parent {
int x = 20;
public void func() {
System.out.println("Current class nonstatic variable:
"+this.x);//20 - this refer to current class nonstatic variable
System.out.println("Parent class nonstatic variable:
"+super.x);//10 - super refer to parent class non static variable
}
}
Current class nonstatic variable: 20
// Parent class nonstatic variable: 10

The above example shows calling this class and the parent class non static variables using the
this and super keywords.

Constructor overloading -
●​ Explicitly define multiple constructors with different types of arguments.

public class demo5 {


public static void main(String[] args) {
new Demo();
new Demo(10);
new Demo(12.5);
new Demo(true);
}
}
class Demo{
Demo() {
System.out.println("No argument constructor");
}
Demo(int x) {
System.out.println("Integer type argument constructor");
}
Demo(double x) {
System.out.println("Double type argument constructor");
}
Demo(boolean x) {
System.out.println("Boolean type argument constructor");
}
}
// No argument constructor
// Integer type argument constructor
// Double type argument constructor
// Boolean type argument constructor

Constructor Chaining -
●​ Calling one constructor from another constructor is known as constructor chaining.
●​ This can be achieved using
○​ Call to this (this())
public class demo5 {
public static void main(String[] args) {
System.out.println("=======Creating new Demo2()=======\n");
new Demo2();
System.out.println("\n=======Creating new Demo2(10)=======\n");
new Demo2(10);
System.out.println("\n=======Creating new Demo2(10.3)=======\n");
new Demo2(10.3);
System.out.println("\n=======Creating new Demo2(true)=======\n");
new Demo2(true);
}
}
class Demo2{
Demo2() {
this(10);
//Demo2(10);//is treated like a method call, but constructors
aren’t regular methods and can’t be called like that.
System.out.println("No argument cosntructor");
}
Demo2(int x) {
this(12.4);
System.out.println("Integer type argument cosntructor");
}
Demo2(double x) {
this(true);
System.out.println("Double type argument cosntructor");
}
Demo2(boolean x) {
System.out.println("Boolean type argument cosntructor");
}
}
// =======Creating new Demo2()=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor
// No argument cosntructor

// =======Creating new Demo2(10)=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor

// =======Creating new Demo2(10.3)=======

// Boolean type argument cosntructor


// Double type argument cosntructor

// =======Creating new Demo2(true)=======

// Boolean type argument cosntructor

○​ Call to super(super())

public class demo5 {


public static void main(String[] args) {
new Child();
}
}
class Parent{
Parent(int num) {
System.out.println("Parent class constructor");
}
}
class Child extends Parent{
Child() {
super(19);
System.out.println("Child constructor");
}
}
// Parent class constructor
// Child constructor
public class demo5 {
public static void main(String[] args) {
new Parent(10);
}
}
class Parent{
Parent(int num) {
System.out.println("Parent class constructor");
}
}
class Child extends Parent{
Child() {
super(19);
System.out.println("Child constructor");
}
}
// Parent class constructor

Explanation:
The main method creates an object of the Parent class.
The Child class is present but unused, so its constructor does not run.

●​ To call three constructors, we have to create three objects, which is not good
programming practice. To overcome this, we will use a call to this.

public class demo5 {


public static void main(String[] args) {
System.out.println("=======Creating new Demo2()=======\n");
new Demo2();
System.out.println("\n=======Creating new Demo2(10)=======\n");
new Demo2(10);
System.out.println("\n=======Creating new Demo2(10.3)=======\n");
new Demo2(10.3);
System.out.println("\n=======Creating new Demo2(true)=======\n");
new Demo2(true);
}
}
class Demo2{
Demo2() {
this(10);
//Demo2(10);//is treated like a method call, but constructors
aren’t regular methods and can’t be called like that.
System.out.println("No argument cosntructor");
}
Demo2(int x) {
this(12.4);
System.out.println("Integer type argument cosntructor");
}
Demo2(double x) {
this(true);
System.out.println("Double type argument cosntructor");
}
Demo2(boolean x) {
System.out.println("Boolean type argument cosntructor");
}
}
// =======Creating new Demo2()=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor
// No argument cosntructor

// =======Creating new Demo2(10)=======

// Boolean type argument cosntructor


// Double type argument cosntructor
// Integer type argument cosntructor

// =======Creating new Demo2(10.3)=======


// Boolean type argument cosntructor
// Double type argument cosntructor

// =======Creating new Demo2(true)=======

// Boolean type argument cosntructor

Recursive constructor invocation-

public class demo5 {


public static void main(String[] args) {
new Random();
}
}
class Random {
Random(){
this();
System.out.println("random class const");
}
}

public class demo5 {


public static void main(String[] args) {
new Dog();
}
}
class Animal {
Animal() {
System.out.println("Animal class Constructor");
}
}
class Dog extends Animal {
Dog() {
System.out.println("Dog class constructor");
}
}
// Animal class Constructor
// Dog class constructor

Can we override a constructor?


●​ The constructor can't be overridden because the class name and the constructor name
are different.

Initializing the object using the constructor.

public class Demo6 {


public static void main(String[] args) {
Employee Tan = new Employee("Tanmoy", 26, "CTC");
Tan.Info();
}
}
class Employee {
String name;
int age;
String address;

Employee(String name, int age, String address) {


this.name = name;
this.age = age;
this.address = address;
}

public void Info() {


System.out.println("Name of the employee: " + name);
System.out.println(name + " is " + age + " years old.");
System.out.println(name + " lives in " + address + ".");
}
}
// Name of the employee: Tanmoy
// Tanmoy is 26 years old.
// Tanmoy lives in CTC

What if we declare the constructor as private?


●​ If we declare the constructor private, we can’t use it outside of the class.
Copy constructor
●​ Creating a new object from an existing object(initialize a new object from a current object
by copying the properties)

public class copy_const {


public static void main(String[] args) {
constr obj1 = new constr("Tanmoy", 25);
constr obj2 = new constr(obj1);
obj1.info();
obj2.info();
}
}
class constr{
String name;
int age;
constr(String name, int age) {
this.name = name;
this.age = age;
}
constr(constr obj) {
name = obj.name;
age = obj.age;
}
public void info(){
System.err.println("Name of the employee: "+ name);
System.err.println("Age of the employee: "+ age);
}
}
// Name of the employee: Tanmoy
// Age of the employee: 25
// Name of the employee: Tanmoy
// Age of the employee: 25

Interface -
●​ It is the medium between the user and the device.
●​ Syntax -
interface interface_name{
}
Interface variable -
●​ Every variable inside the interface is by default public, static, and final.
●​ Public: We can access it from everywhere.
●​ Final: We can't change the value of the variable.
●​ Static: since we can't create an interface object, it can't be non-static.
Since it is by default public, it can't be a local variable.

Case 1:
●​ Interface variables must be initialized. (Only declarations are not acceptable as they are
final.)

invalid valid

interface Demo { interface Demo {


int x; int x = 10;
} }

Case 2:
●​ Interface variables can’t be modified. (as they are final by default).

valid invalid

public class one implements Demo { public class one implements Demo {
public static void public static void
main(String[] args) { main(String[] args) {
int x = 20; x = 20;
System.out.println(x);//20 System.out.println(x);
} }
} }
interface Demo { interface Demo {
int x = 10; int x = 10;
} }
// one.java:3: error: cannot assign
In the above example, we are declaring a new a value to static final variable x
variable inside the main method. So that new // x = 20;
variable is the local variable.
// ^
// 1 error

In the above example, we are trying to modify


the final variable of the interface. That's why
we are getting an error.

Case 3:
●​ Interface variables can be accessed with the help of the interface name.

public class one implements Demo, Remo {


public static void main(String[] args) {
System.out.println(x);
}
}
interface Demo {
int x = 10;
}
interface Remo{
int x = 20;
}
// one.java:4: error: reference to x is ambiguous
// System.out.println(x);
// ^
// both variable x in Demo and variable x in Remo match
// 1 error

✅ How to fix it?


public class one implements Demo, Remo {
public static void main(String[] args) {
System.out.println(Demo.x);
System.out.println(Remo.x);
}
}
interface Demo {
int x = 10;
}
interface Remo{
int x = 20;
}
// 10
// 20

Interface method -
●​ All the methods inside the interface are, by default, public and abstract (unless they are
explicitly default or static (Java 8+).
●​ That's why the interface is also known as an abstract class. (because of the presence of
abstract methods).

public class one implements Demo{


public void func1() {
System.out.println("Function one");
}
public void func2() {
System.out.println("Function two");
}
public static void main(String[] args) {
one obj = new one();
obj.func1();
obj.func2();
}
}
interface Demo {
void func1();
void func2();
}
// Function one
// Function two

●​ From version 1.8 onwards the default method can be declared inside the interface (with a
default keyword).
○​ Syntax -
default void func(){
System.out.println();
}
●​ We can call default methods by creating an object of the child class (implemented class).
public class one implements Remo{
public static void main(String[] args) {
one obj = new one();
obj.func();
}
}
interface Remo{
default void func() {
System.out.println("Default method");
}
}
// Default method

●​ In version 1.8, static methods are also allowed inside the interface.
●​ Static methods are not inherited by the child class means we can't call a static method of
the interface by creating an object of the child class.
●​ We can access the static methods of the interface using the interface name.

public class one implements Remo{


public static void main(String[] args) {
Remo.func_st();
}
}
interface Remo{
static void func_st() {
System.out.println("Static method");
}
}
// Static method

Note -
●​ We can declare the main method inside the interface.

Case 1 -
●​ If more than one interface contains methods with the same method signature then in the
implemented class we have to provide implementation at most once.
public class three {
public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A,B{
public void func() {
System.out.println("Multiple methods same implementations");
}
}
interface A{
void func();

}
interface B{
void func();

}
//Multiple methods same implementations

Case 2 -
●​ If more than one interface contains methods with the same method signature but different
primitive type return types, then we can't provide an implementation because of the
covariant concept.
public class four {

}
class Demo implements A,B{
public float func() {
return 0;
}
}
interface A{
int func();

}
interface B{
float func();

}
// four.java:4: error: Demo is not abstract and does not override abstract
method func() in A
// class Demo implements A,B{
// ^
// four.java:8: error: func() in Demo cannot implement func() in A
// public float func() {
// ^
// return type float is not compatible with int
// 2 errors

Case 3 -
●​ If more than one interface contains the same method signature but different non primitive
type return type we can provide implementation according to the covariant concept.
public class five {
public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A, B {
public String func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
String func();

}
interface B {
Object func();

}
//Two non primitive return one implementation

public class five {


public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A, B {
public Object func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
String func();

}
interface B {
Object func();

}
// five.java:7: error: Demo is not abstract and does not override abstract
method func() in A
// class Demo implements A, B {
// ^
// five.java:8: error: func() in Demo cannot implement func() in A
// public Object func() {
// ^
// return type Object is not compatible with String
// 2 errors

public class five {


public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Demo implements A, B {
public Demo func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
A func();
}
interface B {
B func();

}
// Two non primitive return one implementation

public class five {


public static void main(String[] args) {
Demo ob = new Demo();
ob.func();
}
}
class Parent{

}
class Child extends Parent {

}
class Demo implements A, B {
public Child func() {
System.out.println("Two non primitive return one implementation");
return null;
}

}
interface A {
Child func();

}
interface B {
Parent func();

}
// Two non primitive return one implementation
Factory method -
●​ It is the type of method that is called by its class name, and it returns the object of that
class.

public class one {


public static void main(String[] args) {
Runtime r1 = Runtime.getRuntime();
Runtime r2 = Runtime.getRuntime();
System.out.println(r1 == r2);
}
}
//true

Runtime is a predefined class and getRuntime() is a predefined method.

Wap to create a user defined factory method -

public class two {


static two t = new two();
public static two geTwo() {
return t;
}
public static void main(String[] args) {
two t1 = two.geTwo();
two t2 = two.geTwo();
System.out.println(t1 == t2);
}
}
// true

Case for the constructor -

Case 1 -
●​ If a constructor is declared private, we can't create objects outside of the class.

Valid Invalid

public class demo8 { public class demo8 {


public static void public static void
main(String[] args) { main(String[] args) {
Demo d = new Demo(); Demo d = new Demo();
} }
} }
class Demo { class Demo {
Demo() { private Demo() {
System.out.println("Constructor System.out.println("Constructor
created"); created");
} }
} }
// Constructor created // demo8.java:3: error: Demo() has
private access in Demo
// Demo d = new Demo();
// ^
// 1 error

Case 2 -
●​ If a constructor is declared as private inside the class, then no one can inherit the
properties of that class.
public class demo8 {
public static void main(String[] args) {
}
}
class Demo {
private Demo() {
System.out.println("Constructor created");
}
}
class subDemo extends Demo {

}
// demo8.java:12: error: Demo() has private access in Demo
// class subDemo extends Demo {
// ^
// 1 error
Singleton class -
●​ If we are allowed to create only one object (maximum one) of a class, then that class is
known as the singleton class.
●​ To create a singleton class, we required a static variable, a private constructor, and a
factory method.
public class one {
private one() {
System.out.println("Private Constructor");
}
static one o = new one();
public static one getOne(){
return o;
}
public static void main(String[] args) {
one o1 = one.getOne();
one o2 = one.getOne();
System.out.println(o1 == o2);
}
}
// Private Constructor
// true

Static Block -
●​ This block type will be executed before the main method at the time of class loading.

public class one { public class one {


public static void static {
main(String[] args) { System.out.println("Static
System.out.println("Main Block");
Block"); }
} public static void
} main(String[] args) {
// Main Block System.out.println("Main
Block");
}
}
// Static Block
// Main Block

public class one {


static {
System.out.println("Static Block 1");
}
public static void main(String[] args) {
System.out.println("Main Block");
}
static {
System.out.println("Static Block 2");
}
}
// Static Block 1
// Static Block 2
// Main Block

After executing all the static blocks, the main method will execute.

Static control flow -

Step 1 (Identification) -
●​ Identification of static data members from top to bottom, and at the time of identification,
the static variable can be initialized with its default value(by the JVM).

Step 2 -
●​ Initialization of static variable and execution of static block from top to bottom.

Step 3 -
●​ Execution of the main method.

Example -
public class one {
static int x = 10;
static {
System.out.println("Static Block 1");
func1();
}
public static void func1() {
System.out.println(y);
}
public static void main(String[] args) {
System.out.println("Main Block Start");
func1();
System.out.println("Main Block End");
}
static {
System.out.println("Static Block 2");
func2();
}
public static void func2() {
System.out.println(x);
}
static int y = 20;
}
// Static Block 1
// 0
// Static Block 2
// 10
// Main Block Start
// 20
// Main Block End

Step 1 -
X=0
Y=0

o/p -

Step 2 -
X = 10
Y = 20

o/p -
Static Block 1
0
Static Block 2
10

Step 3-

o/p -
Main Start
20
Main End

●​ Without the main method, we can compile the program, but we can't run it. (Compile
using: javac -source 1.6 test.java)
public class two {
static {
System.out.println("Static block");
}
}

Javac file_name.java
Java class_name

class twoA {
static {
System.out.println("Static block");
}
}

Java file_name.java
Static block
main() not found
class twoA {
static {
System.out.println("Static block");
System.exit(0);
}
}

Java file_name.java
RIWO (Read Indirectly Write Only)
●​ At the time of identification, when the variable is assigned with default value, then we can
say that the variable is in the RIWO state.

Direct Read
●​ If we print any variable inside any static block, then it is known as a direct read.

public class three {


static int x = 10;
static {
System.out.println(x);
}
public static void main(String[] args) {

}
}
// 10

Indirect Read -
●​ If we print any variable inside the method, then it is known as an indirect read.

public class three {


static int x = 10;
static {
func1();
}
public static void func1() {
System.out.println(x);
}
public static void main(String[] args) {

}
}
// 10
Case 1 -
●​ If a variable is not in the RIWO state, then we can perform both direct read and indirect
read.

Case 2 -
●​ If a variable is in the RIWO state, then we can’t perform a direct read.
public class three {
static {
System.out.println(x);
}
static int x = 10;
public static void main(String[] args) {

}
}
// three.java:4: error: illegal forward reference
// System.out.println(x);
// ^
// 1 error

Case 3 -
●​ If a variable is in the RIWO state, then we can perform only an indirect read.
public class three {
static {
func1();
}
public static void func1() {
System.out.println(x);
}
static int x = 10;
public static void main(String[] args) {

}
}
// 0

You might also like