Cleaned_Java_Notes
Cleaned_Java_Notes
Java is a :-
Programming Language :
For example "teacher" who gives the instructions to students to perform specific tasks,
developers use Java to instruct the system to execute desired operations like addition,
subtraction, division, login, register, add items into cart, online payment etc.
Developers can use Java to perform various tasks such as addition, subtraction, user
authentication (login and registration), adding items to a cart, or processing online
payments.
Introduction : Java SE is the core edition of the Java platform and provides the foundational
APIs and tools for general-purpose programming. It includes basic libraries for data
structures, networking, I/O, and more.
Applications :
Command-Line Tools : Java SE is also used for developing command-line tools and utilities
that run on various operating systems.
Small-to-Medium Size Application : Java SE is suitable for developing smaller-scale
applications that don’t require the extensive features of Java EE.
Introduction : Java EE (now Jakarta EE) is designed for large-scale, distributed, and multi-
tiered applications. It extends Java SE with additional libraries and APIs for enterprise-level
development, including web services, component-based architecture, and database
interaction.
Applications :
Web Applications : Java EE is used to build robust web applications using technologies like
Servlets, JSP (JavaServer Pages), and JSF (JavaServer Faces). It supports frameworks like
Spring and Hibernate.
Web Services : Java EE supports the development of RESTful and SOAP-based web services
that allow different systems to communicate over the web.
E-Commerce Systems : Java EE is widely used to create large e-commerce platforms that
require high availability, scalability, and security.
Note: Java EE has been rebranded as Jakarta EE under the Eclipse Foundation. The shift is
more about the organization managing the technology rather than the technology itself.
Applications :
Mobile Applications : Before the rise of Android, Java ME was the primary platform for
developing mobile applications for feature phones and early smartphones.
Embedded Systems : Java ME is used in embedded devices such as smart cards, GPS devices,
and home automation systems.
IoT Applications : Java ME provides a lightweight platform for IoT devices, enabling the
development of applications that run on small, connected devices with limited processing
power and memory.
4. JavaFX
Introduction : JavaFX is a platform for building rich internet applications (RIAs) that can run
on various devices. It provides a modern, hardware-accelerated user interface and is often
used for creating visually appealing desktop applications.
Applications :
Rich Internet Applications (RIAs) : JavaFX is used to create interactive, visually rich
applications that can run on the desktop, web, or embedded devices.
Data Visualization Tools : JavaFX is often used in building tools that visualize complex data,
such as charts, graphs, and simulations.
5. Java Card
Introduction : Java Card is a specialized edition of the Java platform designed for secure,
resource-constrained environments like smart cards and SIM cards. It enables small
applications (applets) to run securely on devices with minimal memory and processing
power, commonly used in industries requiring high security, such as banking,
telecommunications, and government ID systems.
Applications :
Smart Cards: Java Card is used in the development of applications for smart cards, including
payment cards (credit/debit), identification cards, and access control systems. The
technology enables secure storage of sensitive data like cryptographic keys and personal
identification information.
SIM Cards: Java Card powers SIM cards used in mobile phones. It allows telecom providers
to securely manage and store subscriber information, including authentication keys and
contact information. It also enables Over-the-Air (OTA) updates of applets and services on
SIM cards.
Secure Authentication: Java Card is used in devices that require strong authentication, such
as hardware security tokens (e.g., for two-factor authentication), digital signatures, and
encryption devices. The small, secure environment of Java Card makes it ideal for
cryptographic operations and secure transaction processing.
ePassports and ID Cards: Governments use Java Card technology to power ePassports and
national ID cards. These cards securely store and manage biometric data and personal
identification details to ensure security and privacy in identification and travel systems.
Features of Java
Java is a popular programming language known for its simplicity, platform independence,
and robustness which makes it versatile for a wide range of applications. Some most
important core features in java are as below :-
1. Platform-Independent
Definition : Java applications are designed to run on any platform that has a Java Virtual
Machine (JVM) without requiring modification.
Detailed Explanation :
Bytecode : Java source code is compiled into an intermediate form called bytecode (.class
files). Bytecode is platform-independent and can be executed on any system with a
compatible JVM. This bytecode is portable across different operating systems and hardware
configurations.
2. Object-Oriented
Definition : Java is built around the principles of object-oriented programming (OOP), which
organizes software design around data, or objects, rather than functions and logic.
Detailed Explanation :
Inheritance : Inheritance allows one class (subclass) to inherit the fields and methods of
another class (superclass). This promotes code reuse and establishes a natural hierarchy.
For example, a Dog class can inherit from an Animal class, gaining all its attributes and
behaviors.
Abstraction : Abstraction involves hiding complex implementation details and showing only
the essential features of an object. In Java, abstraction is achieved through abstract classes
and interfaces, which define what methods a class should implement without specifying
how these methods should be implemented.
3. Robust
Detailed Explanation :
Exception Handling : Java uses a structured approach to handle runtime errors through
exceptions. The language provides robust exception handling mechanisms using try, catch,
finally, and throw keywords, enabling developers to handle and recover from errors
gracefully.
Type Checking : Java performs strict type checking at compile-time and runtime. This
ensures that operations are performed on compatible data types and helps catch errors
early in the development process.
4. Secure
Detailed Explanation :
Sandboxing : Java applets and applications can run in a restricted environment called a
sandbox, which limits their ability to access system resources and perform potentially
harmful operations. This is especially important for applets running in a web browser.
Security Manager : Java includes a security manager that allows applications to set security
policies and control access to sensitive system resources like files, network connections,
and system properties.
5. Portable
Definition : Java's portability allows compiled programs to run on any platform with a JVM,
ensuring cross-platform compatibility.
Detailed Explanation :
Bytecode and JVM : Java compiles code into platform-independent bytecode, executable on
any JVM.
Example : A Java app compiled on Windows runs seamlessly on Linux or macOS if JVM is
installed.
6. Simple
Detailed Explanation :
Syntax and Structure : Java’s syntax is derived from C and C++ but is simplified to remove
complex features that often lead to errors. For instance, it eliminates explicit pointers,
which can lead to memory leaks and undefined behavior.
Automatic Memory Management : Java handles memory allocation and garbage collection
automatically, reducing the burden on developers to manage memory manually. This
reduces the risk of memory leaks and errors related to memory management.
No Multiple Inheritance : Java does not support multiple inheritance (a class cannot inherit
from more than one class), which simplifies the design and avoids the “diamond problem”
found in languages like C++. Instead, Java uses interfaces to achieve multiple inheritance of
type.
7. Multithreaded
Definition : Java provides built-in support for concurrent execution, allowing multiple
threads to run simultaneously.
Detailed Explanation :
8. Distributed
Detailed Explanation :
Networking Capabilities : Java provides robust networking classes in the java.net package,
including support for sockets, URLs, and HTTP. This allows Java applications to
communicate over various types of networks.
Remote Method Invocation (RMI) : RMI enables Java objects to communicate and invoke
methods on objects located remotely. It abstracts the complexities of network
communication, making it easier to develop distributed applications.
Web Services : Java offers comprehensive support for web services through APIs such as
JAX-WS (Java API for XML Web Services) and JAX-RS (Java API for RESTful Web Services).
These APIs allow Java applications to interact with other services over the web using
standardized protocols like HTTP and SOAP.
9. Dynamic
Detailed Explanation :
Reflection : Java’s reflection API allows programs to examine and manipulate the structure
and behavior of classes, interfaces, and objects at runtime. This enables dynamic
instantiation of classes, invocation of methods, and access to fields, even if their names are
not known until runtime.
Dynamic Class Loading : Java supports dynamic class loading, where classes can be loaded
into the JVM at runtime. This allows for on-the-fly updates and extensibility, making it
possible to load and execute classes that were not known at compile-time.
Definition : Java is designed to deliver high performance while maintaining portability and
security.
Detailed Explanation :
Just-In-Time (JIT) Compiler : The JVM includes a Just-In-Time (JIT) compiler that translates
bytecode into native machine code at runtime. The JIT compiler optimizes code execution
by compiling frequently executed methods, which significantly improves performance.
Optimized Libraries : Java provides a rich set of standard libraries that are highly optimized
for performance. These libraries include efficient data structures, algorithms, and utility
classes that contribute to the overall performance of Java applications.
Detailed Explanation :
Core Libraries : Java’s core libraries cover essential functionalities such as data structures
(java.util package), input/output (java.io package), networking (java.net package), and
concurrency (java.util.concurrent package). These libraries provide ready-to-use
components that simplify common programming tasks.
Graphics and GUI : Java includes APIs for developing graphical user interfaces (GUIs) and
handling graphics. The Swing and JavaFX libraries offer components for building desktop
applications, while the java.awt package provides classes for drawing and manipulating
graphics.
Database Connectivity : Java’s JDBC (Java Database Connectivity) API allows seamless
interaction with databases. It supports SQL queries, transactions, and connection pooling,
making it easy to integrate Java applications with relational databases.
Web and Networking : Java provides extensive support for web development through APIs
like Servlets, JSP (JavaServer Pages), and WebSockets. The java.net package also includes
classes for working with URLs, HTTP, and sockets, enabling Java applications to
communicate over networks.
Enterprise APIs : Java EE (Enterprise Edition) offers a suite of APIs for building enterprise-
level applications. These include APIs for web services (JAX-WS, JAX-RS), messaging (JMS),
and persistence (JPA), among others, which provide a solid foundation for developing
scalable and robust enterprise applications.
12. Community Support
Definition : Java has a vast and active global community that contributes to its development,
provides resources, and supports developers.
Detailed Explanation :
OpenJDK and Oracle JDK : Java is available as both the open-source OpenJDK and the
commercially supported Oracle JDK. The OpenJDK community actively contributes to the
language’s development, ensuring that Java remains up-to-date and continues to evolve.
Libraries and Frameworks : The Java community has developed a wide range of libraries
and frameworks that extend the language’s capabilities. Popular frameworks like Spring,
Hibernate, and Apache Struts simplify development and are widely used in the industry.
Forums and Resources : Java developers have access to numerous online forums,
documentation, and tutorials. Websites like Stack Overflow, GitHub, and Oracle’s official
documentation provide valuable resources for learning and troubleshooting Java-related
issues.
Conferences and Meetups : The global Java community organizes conferences, meetups, and
events where developers can share knowledge, discuss trends, and collaborate on projects.
Events like JavaOne and Devoxx are prominent in the Java ecosystem.
Definition : Java is designed to be scalable and perform efficiently across different types of
applications, from small programs to large enterprise systems.
Detailed Explanation :
Thread Management : Java’s built-in support for multithreading allows developers to create
scalable applications that can handle multiple tasks simultaneously. The java.util.concurrent
package offers advanced tools for managing thread pools and executing parallel tasks.
Load Balancing and Distributed Systems : Java’s ability to handle distributed systems, along
with frameworks like Apache Kafka and Spring Cloud, makes it suitable for creating
scalable, high-performance applications. These frameworks help in load balancing, message
queuing, and managing distributed transactions.
14. Versatility
Definition : Java’s versatility allows it to be used across a wide range of domains and
application types, from mobile apps to large-scale enterprise systems.
Detailed Explanation :
Mobile Applications : Java is the foundation for Android app development, which uses the
Android SDK and Java APIs. Android apps are built using Java, making it a key player in the
mobile app ecosystem.
Web Applications : Java’s robust web frameworks, such as Spring and JavaServer Faces
(JSF), make it an excellent choice for developing dynamic and responsive web applications.
Java Servlets and JSPs are commonly used for server-side development.
Scientific Applications : Java’s reliability, portability, and high performance make it ideal for
scientific and research-based applications. Libraries like Apache Commons Math and Java
3D are used for mathematical calculations and visual simulations.
Enterprise Solutions : Java is widely used for building enterprise-level applications that
require reliability, scalability, and security. Industries such as finance, healthcare, and
telecommunications rely on Java for mission-critical systems.
15. Interoperability
Detailed Explanation :
Java Native Interface (JNI) : JNI allows Java code to interact with native applications and
libraries written in other languages like C or C++. This feature is particularly useful when
integrating Java with existing legacy systems or when performance-critical operations need
to be implemented in a lower-level language.
Web Services and API Integration : Java supports the development and consumption of web
services, enabling integration with external systems through RESTful and SOAP APIs. Java
EE provides APIs like JAX-RS and JAX-WS for building and consuming web services.
Multilingual Support : Java applications can interact with other languages using scripting
APIs and frameworks like Jython (Python on Java) or JRuby (Ruby on Java). This allows
developers to leverage the strengths of other languages within a Java environment.
Definition : Java benefits from a large, active community and a rich ecosystem that
contribute to its development and support.
Detailed Explanation :
Large Community : Java has a vast and diverse community of developers, enthusiasts, and
professionals who contribute to its growth and evolution. The community provides support
through forums, blogs, and open-source projects, helping developers solve problems and
stay up-to-date with best practices.
Rich Ecosystem : The Java ecosystem includes a wide range of tools, libraries, and
frameworks that enhance development capabilities. The ecosystem supports various
aspects of development, such as build tools (e.g., Maven, Gradle), IDEs (e.g., IntelliJ IDEA,
Eclipse), and continuous integration tools (e.g., Jenkins).
Usage
Java is a versatile and widely-used programming language known for its platform
independence, reliability, and scalability. It is employed in various domains, including web
development, mobile applications, enterprise systems, and embedded devices. Java’s "write
once, run anywhere" capability, thanks to the Java Virtual Machine (JVM), allows developers
to create applications that can run on multiple platforms without modification. Additionally,
Java's extensive ecosystem of libraries and frameworks supports efficient and effective
development across different types of software projects, making it a preferred choice for
businesses and developers worldwide.
Types of usage
1. Web Development
Servlets and JSPs : Java Servlets and JavaServer Pages (JSP) are core technologies for
building dynamic web content. Servlets handle requests and responses, while JSPs simplify
the creation of HTML pages with embedded Java code.
2. Enterprise Applications
Enterprise Resource Planning (ERP) : Java is a popular choice for building large-scale
enterprise applications. It supports a range of enterprise frameworks and standards like
Java EE (Enterprise Edition), which includes EJB (Enterprise JavaBeans), JPA (Java
Persistence API), and JMS (Java Message Service).
Scalability and Reliability : Java’s ability to handle large-scale transactions, security, and
high concurrency makes it suitable for enterprise solutions.
3. Mobile Applications
Android Development : Java has been a primary language for developing Android
applications. The Android SDK provides tools and libraries for creating mobile apps on the
Android platform. While Kotlin is now officially preferred, Java remains a significant part of
Android development.
4. Desktop Applications
GUI Applications : Java provides libraries like Swing and JavaFX for building cross-platform
desktop applications with graphical user interfaces (GUIs). These libraries allow developers
to create rich desktop applications that run on various operating systems.
Data Analysis : Java is used in scientific computing and data analysis due to its robustness,
portability, and performance. Libraries like Apache Commons Math and JAMA (Java Matrix
Library) facilitate complex calculations and data processing.
Simulation and Modeling : Java's performance and extensive libraries make it suitable for
simulations, modeling, and research applications.
Hadoop : Java is a key language for Hadoop, a popular framework for distributed storage
and processing of large data sets. Hadoop’s components, like MapReduce and HDFS
(Hadoop Distributed File System), are written in Java.
Apache Kafka : Java is also used with Apache Kafka, a distributed streaming platform that
handles real-time data feeds.
7. Embedded Systems
Java ME : Java Micro Edition (Java ME) is designed for developing applications on embedded
and mobile devices. It’s used in various devices like smartcards, IoT devices, and other
resource-constrained systems.
8. Cloud Computing
Cloud Platforms : Java is commonly used for building cloud-based applications. It integrates
with cloud platforms like AWS (Amazon Web Services), Google Cloud Platform, and
Microsoft Azure to create scalable and resilient applications.
What is JDK?
The Java Development Kit (JDK) is a software development kit used to develop applications
in the Java programming language.
It includes
various tools which are essential for compiling, running, documenting, packaging, and
debugging Java applications, such as The Java Application Launcher (java), Java Compiler
(javac), Documentation Generator (javadoc) etc and
Components of JDK :-
Development Tools:
Function: Provides the libraries, Java Virtual Machine (JVM), and other components to run
Java applications.
Included: The JRE is part of the JDK, and it includes the JVM along with the necessary
runtime libraries.
Usage of JDK :-
Installation : Requires installation on the developer’s machine and is not required for end-
users who only need to run Java applications.
What is JRE ?
The Java Runtime Environment (JRE) is a software platform that enables the execution of
Java applications. It works by providing a runtime environment that includes a set of core
libraries and Java Virtual Machine (JVM).
The JRE allows Java programs to run on any device or operating system without
modification, by translating Java bytecode into native machine code that the JVM executes.
Components of JRE :-
Java Libraries
Java libraries are collections of pre-written code that provide essential functionality for
development. They include base libraries (e.g., java.lang, java.util), additional base libraries
(e.g., java.beans, java.security), and integration libraries (e.g., JDBC, JNDI) for external
system integration.
lang & util Base Libraries (e.g., java.lang, java.util): Provide core classes for Java, including
fundamental utilities (e.g., collections, strings, math) and language features (e.g., threading,
exceptions).
Other Base Libraries (e.g., java.beans, java.security): Provide additional functionality, such
as object introspection (beans) and security features (cryptography, authentication).
Integration Libraries (e.g., JDBC, JNDI): Offer APIs for database connectivity (JDBC),
directory services (JNDI), and integrating with external systems like databases and
networks.
User interface toolkits :- User interface toolkits in JRE, like AWT, Swing, and Java 2D,
provide tools for building graphical user interfaces (GUIs). They offer components for
windows, buttons, and graphics rendering, enabling developers to create interactive,
visually-rich applications with support for both basic and advanced UI elements and 2D
graphics.
Deployment :- Deployment in JRE involves packaging and distributing Java applications for
execution on client machines. This includes delivering Java programs in formats like JAR or
WAR files, ensuring they run within the Java Runtime Environment, often using tools like
Java Web Start or applet technology for deployment.
Java Virtual Machine :- The Java Virtual Machine (JVM) is an engine that executes Java
bytecode. It provides platform independence by allowing Java programs to run on any
device with a JVM, handling tasks like memory management, garbage collection, and code
optimization.
JRE (Java Runtime Environment) = Java Libraries + Unser Interface Toolkits + Deployment +
JVM (Java Virtual Machine)
Usage of JRE :-
Java Runtime Environment (JRE) is used to provide a runtime platform for executing Java
applications. It includes the JVM, core libraries, and resources required to run Java
programs, ensuring platform independence and handling tasks like memory management,
security, and execution of compiled Java code.
What is JVM ?
The JVM is a part of the Java platform that executes Java bytecode, converting it into
machine code for the host system. It provides an abstraction layer between compiled Java
code and the operating system.
The main use of the JVM is to enable platform-independent execution of Java programs by
interpreting or compiling bytecode to machine code, managing memory, ensuring security,
and optimizing performance.
Components of JVM :-
Class Loader: The class loader is responsible for dynamically loading Java classes into
memory at runtime. It handles loading, linking, and initialization, organizing classes into
namespaces and ensuring they are available for execution.
Memory Areas: The JVM's memory areas include the heap (for objects), stack (for method
calls and local variables), method area (for class-level data), and native method stacks.
These regions manage memory allocation, storage of program data, and execution context.
Execution Engine: The execution engine interprets or compiles bytecode into machine code
for execution by the CPU. It includes the interpreter for line-by-line execution and the Just-
In-Time (JIT) compiler for optimizing frequently executed code paths.
JVM (Java Virtual Machine) = Class Loader + Memory Areas + Execution Engine
Usage of JVM :-
The JVM interprets or compiles the bytecode into native machine code that can be executed
by the host machine. This enables Java programs to run on any device or operating system
that has a compatible JVM implementation, adhering to the principle of "Write Once, Run
Anywhere.
When writing a program in any programming language, it's important to follow a basic
structure recommended by experts. Typically, a Java program is made up of the following
parts, as shown in the figure below.
The package declaration specifies the package name for the Java class. It is the first
statement in a Java program (if present).
Purpose : Package statement is used to group related classes and organize the code.
Syntax :
package packageName;
Example :
package com.example.myapp;
The import statement is used to include other Java classes or packages in the program,
enabling the use of pre-defined classes (e.g., java.util.Scanner).
Purpose : Import statement is used to import built-in or user-defined classes for reusability.
Syntax :
The class is the fundamental building block of a Java program. Every Java program must
have at least one class.
Syntax :
class ClassName {
// Class body
Example :
There should be atleast one main class which should contains the main() method as main()
method is the entry point for the program.
A class can include the following components which are known as "Class Members":
etc...
Variables are used to store data and are declared within the class (as fields) or within
methods (local variables).
Syntax :
Constructor is a special method having same name as that of class name but should name
have any return type.
Syntax :
ClassName() {
// Constructor body
Example :
public Car() {
System.out.println("Constructor called!");
Syntax :
// Method body
Example :
System.out.println("Car Started");
}
3.4 Main Method [Class Members]
main() method is the entry point for java program from where program execution starts.
main() method can have different syntax but below is the standard syntax that we should
use.
Syntax :
// Code to execute
Example :
System.out.println("Hello Deepak...!!");
In last tutorial, we have deeply explained the . Now, below is the simple Java Hello Program.
MainApp.java
System.out.println("Hello Deepak");
In this example, we have a class named MainApp, and within this class, there is a main
method. The method prints "Hello Deepak...!!" to the console.
Breaking Down the program as below:-
The "public access modifier keyword" declares that the MainApp class is accessible from
anywhere in the program (other packages are also included) and JVM can invoke it from
outside the class.
Note that when a class is declared as public, it must have the same name as the file name (in
this case, MainApp.java).
2. class (Keyword)
The "class keyword" is used to define a class in Java, which acts as a blueprint for creating
objects.
The "MainApp" is the user-defined class name which contains the overall program.
The class must follows the Java naming conventions (CamelCase starting with an uppercase
letter).
The "MainApp" class acts as the entry point of the program because it contains the main
method.
The "public access modifier keyword" here makes the main method accessible to the Java
Virtual Machine (JVM) so it can execute the program.
6. static (Keyword)
The "static keyword" denotes that the main method belongs to the class rather than an
instance of the class.
It means that the main method is called without creating an object of the MainApp class.
The "void return-type keyword" indicates that the main method does not return any value.
Since the program’s execution does not require any return value from the main method, it is
declared void.
The "main pre-defined method" is an entry point of the program from where execution
begins.
The JVM looks for this specific method (main() method) to start the program. If there is no
main() method then JVM will not start the program execution.
The "String[] parameter type" is used for Command-line Arguments. It holds the arguments
passed to the program when it is executed via the command line.
For example: If we run java MainApp Hello Deepak, the array will contain:
String[0] = "Hello"
String[1] = "Deepak"
The "args" is the user-defined variable name for the String[] parameter.
"args" is the short name for arguments, but can be renamed to any valid identifier (e.g., data
or parameters).
It contains:
"." is the member access operator which is used to access fields, methods and nested classes
of a class or an object.
For example: System.out accesses the out field of the System class.
It contains:
"out" is the static member (field or property) of "System" class that represents the standard
output stream (usually the console).
It is used to print the data like strings, numbers or objects to the console.
It prints the given text or data to the console and moves the cursor to a new line.
The text Hello Deepak is passed as an argument to the println method and will be displayed
in the console.
";" marks the end of a statement in Java. Every executable statement must be terminated
with a semicolon.
Below diagram visually explains the steps involved when writing, compiling, and executing
a Java program using Notepad and CMD.
MainApp.java
System.out.println("Hello Deepak");
The .java file contains our Java source code, including a class with a main method (the entry
point of the program).
Step 2: Compilation
In compilation phase, we open CMD, navigate to the directory where our .java file is located,
and run the javac command:
javac MainApp.java
The .class file contains the compiled bytecode, which can be executed on any system with a
Java Virtual Machine (JVM).
Bytecode ensures Java's "Write Once, Run Anywhere" principle because it is not tied to a
specific machine.
Step 4: Execution
To run the program, we execute the java command in CMD: java MainApp
Do not include the .class extension in this command.
It converts the bytecode into machine code that the operating system understands.
Step 5: Output
The JVM executes it, and the output is displayed in the Command Prompt:
Hello Deepak
Introduction
In Java, when we provide data like 101, Deepak, 91.4, etc., we need to specify that which
type of data we are providing.
For example, we need to specify that 101 is of type int, Deepak is of type String, and 91.4 is
of type float or double.
So, we can say that in Java, every piece of data has a specific type, known as a "data type".
Data types inform the compiler about the kind of data to be stored in a variable.
For example: Declaring int rollno = 101; tells the compiler that rollno will store an integer.
They help allocate the necessary memory for that data, ensuring that the program uses
memory efficiently and that data is stored and processed correctly.
For example: int rollno allocates 4 bytes of memory, same float marks will also store 4
bytes of memory.
Data is stored in variables, and each variable is assigned a specific data type.
A variable's data type determines what kind of value it can hold and what operations can be
performed on it.
For example :
// "rollno" is "variable"
Diagram :
There are total 8 primitive data types in Java i.e. boolean, char, byte, short, int, long, float
and double.
Primitive data types have fixed memory sizes for example char always occupies 2 byte of
memory, int occupies 4 byte of memory etc.
Non-Primitive data types examples are Strings, Arrays, classes, interfaces etc.
Non-Primitive data types does'nt have fixed memory sizes, they depends on the data or
objects they reference.
For example, a String object’s memory usage depends on the string's length.
In Java, a data type specifies the type of value a variable can hold.
It tells the compiler how much memory to allocate and what kind of data to expect.
For example :
Primitive data types are pre-defined, basic building blocks in Java, representing fixed-size
simple values like integers, decimals, or characters. Example: int rollno = 101;.
We have explained the primitive data types in points as below :-
Primitive data types are the most basic building blocks in Java or any other programming
language.
They are pre-defined by the Java compiler and represent simple data values, like numbers
or characters.
Primitive data types are used to store simple, fixed-size data like integers, decimal numbers,
or single characters.
The compiler knows that int can only hold whole numbers (no decimals).
Primitive Data Types are built into the language and are not created by the programmer.
Primitive Data Types are faster and more memory-efficient because they directly store the
value, unlike objects which store references.
Each primitive data type has a fixed size in memory, regardless of the system.
The fixed size ensures that any particular data type will always take a particular memory
size, no matter the operating system or hardware.
For example :
int number = 123; // Allocates 4 bytes for storage.
This fixed size ensures consistent behavior across different platforms, which is part of Java’s
"write once, run anywhere" philosophy.
byte smallNumber = 200; // Error: 200 exceeds the byte range of -128 to 127.
Non-primitive data types are more complex structures in Java or other programming
languages.
They are not pre-defined by the compiler but are created by programmers using classes or
interfaces.
Non-primitive data types can store references to objects or collections of data, such as
strings, arrays, or custom objects.
The compiler knows that String is a class capable of storing sequences of characters.
There are total 6 characters in name variable, thus it will allocates 12 bytes of memory to
store String value.
Non-Primitive Data Types are created by the programmer using classes or interfaces and
provide more flexibility.
Non-Primitive Data Types are slower and require more memory because they store
references to the data instead of directly storing values.
Non-Primitive Data Types are objects or references to objects, offering methods and
functionality beyond raw data storage.
Java provides pre-defined non-primitive types like String and collections from the java.util
package, but we can create an infinite number of non-primitive types (classes, interfaces,
etc.) as needed for your application.
Classes: User-defined types that act as blueprints for creating objects. Examples: String,
Scanner, Student, etc.
Interfaces: Abstract types that specify methods a class must implement. Examples: List,
Runnable, etc.
Arrays: Containers that hold multiple values of the same type. Examples: int[], String[].
Collections: Part of the Java Collections Framework, such as ArrayList, HashMap, HashSet,
etc.
Non-primitive data types in Java do not have a fixed memory size like primitive types. Their
memory usage depends on the data they store and the runtime environment.
For example :
String name = "deepak"; // Allocates 12 bytes for storage (1 char size is 2 byte and total
there are 6 characters)
Non-primitive types can grow or shrink in size based on the data stored. For example:-
An ArrayList grows dynamically as elements are added.
Java uses garbage collection to manage the memory of non-primitive types automatically.
Unused objects are cleaned up to free memory.
unused = null; // The memory for "Garbage" is now eligible for garbage collection
Variables in Java
Introduction
In simple words we can say, variables are the containers used to store the data values.
Java Example :
int rollno = 101;
Here data i.e. 101 is stored in memory, variable name i.e. rollno points to that memory and
variable has its data type i.e. int.
Data Type : The type of data that it stores; for example int, char, long, float etc.
Variable Name : The unique name within the scope which points to the memory location.
Java is a statically typed language, so we must declare the type of data a variable will store.
For example if we create variable rollno having data as 101, then we have to specify its data-
type i.e. int.
The value stored in a variable can change during program execution, which is why it is
called a "variable“.
For example we have one variable no having 10 value, we can change its data as below :
int no = 10;
no = no + 20;
1. Local Variables
Local variables are created when the block or method is executed and destroyed when the
block or method exits.
The scope of a local variable is limited to the block in which it is declared; it cannot be
accessed outside that block.
2. Instance Variables
A variable defined inside a class but outside any method, block, or constructor is called an
instance variable.
Instance variables are created when an object of the class is instantiated and destroyed
when the object is garbage collected.
Each object of the class has its own copy of instance variables, so their values can vary
between objects.
If we do not explicitly initialize the instance variables, then default values are assigned to
them based on their data types (e.g., 0 for integers, null for objects).
3. Static Variables
A variable defined with the static keyword inside a class is called a static variable.
Static variables are shared among all objects of the class; a single copy is created and stored
in the memory.
These variables are created when the class is loaded and destroyed when the class is
unloaded.
Static variables can be accessed without creating an object, using the class name.
{
int no = 100; //instance variable
void m1()
void m2()
System.out.println("Result 9 : "+(no1 + no2 + no3)); //error because no1 and no2 are local
variables and cannot be used outside their method scope
obj.m1();
obj.m2();
Output:
Result 1 : 110
Result 2 : 310
Result 4 : 120
Result 5 : 320
Result 8 : 230
Literals in Java
Introduction
They represent fixed values such as numeric values, characters, strings etc which are
directly assigned to the variables.
For example :
int rollno = 101;
Types of Literals
1. Integer Literals
Integer Literals represents the whole numbers and can be written in different number
systems.
Decimal (Base 10): These are regular whole numbers (e.g., int num = 42;).
Binary (Base 2): These starts with 0b or 0B (e.g., int bin = 0b1010;).
Octal (Base 8): These starts with 0 (e.g., int oct = 010;).
Hexadecimal (Base 16): These starts with 0x or 0X (e.g., int hex = 0x1F;).
Output:
Decimal Literal: 42
Binary Literal: 10
Octal Literal: 8
Hexadecimal Literal: 31
2. Floating-Point Literals
Double: These are the default type for decimal literals (e.g., double e = 2.718;).
Use scientific notation for very large or small numbers (e.g., double largeNum = 1.23e4;).
Output:
3. Character Literals
Output:
4. String Literals
// Output:
// Line1
// Line2
String quotedString = "He said, \"Hello!\""; // Using escape sequence \" for double quote
Output:
String Literal (greeting): Hello, World!
Line2
5. Boolean Literals
Boolean Literals are used for conditional expressions and control flow.
if (isJavaFun) {
} else {
// Using Boolean literals for control flow (example with boolean flags)
if (!isHot) {
} else {
Output:
Is it Hot? false
Java is fun!
6. Null Literal
null can only be assigned to reference types, not primitive data types.
Program for Null Literal :
if (str == null)
else
Output:
For example :-
Underscores cannot be used at the start or end of the literal, or next to a decimal point.
Output:
Million: 1000000
Pi value: 3.141592653
Introduction
Arithmetic operators in Java are used to perform basic mathematical operations on numeric
data types (e.g., int, float, double).
% (Modulus operator): Returns the remainder when the first operand is divided by the
second.
Program :
int a = 10, b = 5;
// Addition
// Subtraction
// Multiplication
// Division
Output:
Addition (int): 15
Subtraction (int): 5
Multiplication (int): 50
Division (int): 2
Modulus (int): 0
Integer Division: When both operands are integers, the division operator (/) performs
integer division, which truncates the decimal part. For example, 10 / 3 results in 3, not
3.333....
Modulus: The modulus operator returns the remainder of the division. For example, 10 % 3
results in 1 (because 10 divided by 3 gives a remainder of 1).
Introduction
= (Assignment Operator):
Purpose: Assigns the right-hand operand value to the left-hand operand (variable).
Purpose: Adds the right-hand operand value to the left-hand operand and assigns the result
to the left operand.
Example: a += b is equivalent to a = a + b.
Purpose: Subtracts the right-hand operand value from the left-hand operand and assigns
the result to the left operand.
Example: a -= b is equivalent to a = a - b.
Purpose: Multiplies the right-hand operand value by the left-hand operand and assigns the
result to the left operand.
Example: a *= b is equivalent to a = a * b.
Purpose: Divides the left-hand operand by the right-hand operand and assigns the result to
the left operand.
Example: a /= b is equivalent to a = a / b.
Purpose: Calculates the remainder of the division of the left operand by the right operand
and assigns the result to the left operand.
Example: a %= b is equivalent to a = a % b.
Program :
// Initialize variables
int a = 10, b = 5;
a += b; // a = a + b (5 + 5)
a -= b; // a = a - b (10 - 5)
a *= b; // a = a * b (5 * 5)
a /= b; // a = a / b (25 / 5)
x += y; // x = x + y (10.5 + 4.2)
Output:
Simple Assignment: a = 5
Addition Assignment: a = 10
Subtraction Assignment: a = 5
Multiplication Assignment: a = 25
Division Assignment: a = 5
Modulus Assignment: a = 0
Chained Assignment:
Compound operators (e.g., +=, *=) perform implicit type casting if needed.
String Concatenation:
Side Effects:
Example: 5 += 3; is invalid.
Usage in Loops:
Compound assignment operators (+=, -=) are frequently used in loops to modify counters
efficiently.
Example: a += b += c; is invalid.
Assignment operators can be used with numeric types (int, float, etc.), char,
and boolean where applicable.
Efficiency:
Compound operators are generally more efficient as they reduce the number of operations
compared to their explicit counterparts.
Introduction
Relational operators are used to compare two values or expressions and return a boolean
value (true or false).
== (Equal to Operator):
Example:
int a = 5, b = 5;
Example:
int a = 5, b = 10;
Purpose: Checks if the left operand is less than the right operand.
Example:
int a = 5, b = 10;
Purpose: Checks if the left operand is greater than the right operand.
Example:
int a = 10, b = 5;
Purpose: Checks if the left operand is less than or equal to the right operand.
Example:
int a = 5, b = 10;
Purpose: Checks if the left operand is greater than or equal to the right operand.
Example:
Program :
// Initialize variables
// Equal To (==)
System.out.println("Less Than or Equal To (a <= b): " + (a <= b)); // Output: true
System.out.println("Less Than or Equal To (x <= y): " + (x <= y)); // Output: true
System.out.println("Greater Than or Equal To (a >= b): " + (a >= b)); // Output: false
System.out.println("Greater Than or Equal To (x >= y): " + (x >= y)); // Output: true
Output:
Comparison of Primitives:
Relational operators can be used with all primitive data types except boolean.
Boolean Result:
Comparing float or double values may lead to unexpected results due to precision issues.
String Comparison:
Relational operators (<, >, etc.) cannot be used with String objects; use compareTo for
lexicographical comparison.
Equality of Objects:
== checks reference equality (if two references point to the same object), not content
equality.
Example:
String s1 = "Java";
String s2 = "Java";
Relational operators cannot directly compare arrays. Use Arrays.equals() or iterate through
elements.
Example:
Operator Precedence:
Relational operators have higher precedence than logical operators (&&, ||) but lower
precedence than arithmetic operators (+, *).
Relational operators can compare values of different numeric types (int, float, etc.). Implicit
casting applies to the smaller type.
Example:
String s = null;
Comparison of Characters:
Relational operators can compare char values based on their Unicode values.
Example: 'a' < 'b' // true (Unicode 97 < 98).
Frequently used in if, while, for and switch conditions to determine the flow of execution.
For double and float, NaN (Not a Number) is not equal to any value, including itself.
Example:
Efficiency:
Example:
Only == and != are valid for boolean values; other relational operators cannot be applied.
Example:
Introduction
Logical Operators are used to perform logical operations between two or more boolean
expressions and return a boolean value (true or false).
Logical operators are explained as below :-
Purpose: Returns true if both operands (expressions) are true, otherwise returns false.
Example:
|| (Logical OR Operator):
Purpose: Returns true if at least one of the operands (expressions) is true, otherwise
returns false.
Example:
Purpose: Inverts the value of the boolean expression. If the expression is true, it becomes
false, and vice versa.
Example:
boolean a = true;
Program :
// Logical OR (||)
System.out.println("Condition is true");
else
}
else
Output:
Condition is true
Logical operators (&&, ||, !) are primarily used with boolean values (true or false).
Short-circuit Behavior:
AND (&&): If the first operand is false, the second operand is not evaluated because the
result is already determined.
OR (||): If the first operand is true, the second operand is not evaluated because the result is
already determined.
Example: boolean result = a && (b = false); — here, b will not be assigned false if a is false.
Logical operators have lower precedence than relational and arithmetic operators but
higher than assignment operators.
Parentheses () should be used for clarity when combining logical operators with other
operators.
Efficiency:
Logical operators can be more efficient when combined with short-circuit behavior, as
unnecessary conditions are not evaluated.
Example: In the expression a && b && c, if a is false, b and c are not evaluated.
Logical operators cannot be used directly on non-boolean types. They are specifically
designed for use with boolean values.
Example: int a = 5, b = 10; // a && b is invalid and will cause a compile-time error.
Logical operators work on boolean values, and confusing them with numerical values (e.g., 1
for true, 0 for false) can lead to logical errors.
Always use explicit boolean values (true or false) when using logical operators.
Logical operators are commonly used in if, while, and for conditions to evaluate multiple
expressions and determine the flow of control.
Introduction
Logical Operators are used to perform logical operations between two or more boolean
expressions and return a boolean value (true or false).
Purpose: Returns true if both operands (expressions) are true, otherwise returns false.
Example:
|| (Logical OR Operator):
Purpose: Returns true if at least one of the operands (expressions) is true, otherwise
returns false.
Example:
Purpose: Inverts the value of the boolean expression. If the expression is true, it becomes
false, and vice versa.
Example:
boolean a = true;
Program :
// Logical OR (||)
{
System.out.println("Condition is true");
else
else
Output:
Condition is true
Not all conditions met
Logical operators (&&, ||, !) are primarily used with boolean values (true or false).
Short-circuit Behavior:
AND (&&): If the first operand is false, the second operand is not evaluated because the
result is already determined.
OR (||): If the first operand is true, the second operand is not evaluated because the result is
already determined.
Example: boolean result = a && (b = false); — here, b will not be assigned false if a is false.
Logical operators can be combined to form complex conditions, making them useful for
decision-making and flow control.
Logical operators have lower precedence than relational and arithmetic operators but
higher than assignment operators.
Parentheses () should be used for clarity when combining logical operators with other
operators.
Logical operators can be more efficient when combined with short-circuit behavior, as
unnecessary conditions are not evaluated.
Example: In the expression a && b && c, if a is false, b and c are not evaluated.
Logical operators cannot be used directly on non-boolean types. They are specifically
designed for use with boolean values.
Example: int a = 5, b = 10; // a && b is invalid and will cause a compile-time error.
Logical operators work on boolean values, and confusing them with numerical values (e.g., 1
for true, 0 for false) can lead to logical errors.
Always use explicit boolean values (true or false) when using logical operators.
The ! (logical NOT) operator is only applicable to boolean values. Using ! on non-boolean
types will result in a compile-time error.
Logical operators are commonly used in if, while, and for conditions to evaluate multiple
expressions and determine the flow of control.
Introduction
Logical Operators are used to perform logical operations between two or more boolean
expressions and return a boolean value (true or false).
Purpose: Returns true if both operands (expressions) are true, otherwise returns false.
Example:
|| (Logical OR Operator):
Purpose: Returns true if at least one of the operands (expressions) is true, otherwise
returns false.
Example:
Purpose: Inverts the value of the boolean expression. If the expression is true, it becomes
false, and vice versa.
Example:
boolean a = true;
Program :
// Logical OR (||)
System.out.println("Condition is true");
else
else
}
}
Output:
Condition is true
Logical operators (&&, ||, !) are primarily used with boolean values (true or false).
Short-circuit Behavior:
AND (&&): If the first operand is false, the second operand is not evaluated because the
result is already determined.
OR (||): If the first operand is true, the second operand is not evaluated because the result is
already determined.
Example: boolean result = a && (b = false); — here, b will not be assigned false if a is false.
Logical operators can be combined to form complex conditions, making them useful for
decision-making and flow control.
Logical operators have lower precedence than relational and arithmetic operators but
higher than assignment operators.
Parentheses () should be used for clarity when combining logical operators with other
operators.
Efficiency:
Logical operators can be more efficient when combined with short-circuit behavior, as
unnecessary conditions are not evaluated.
Example: In the expression a && b && c, if a is false, b and c are not evaluated.
Logical operators cannot be used directly on non-boolean types. They are specifically
designed for use with boolean values.
Example: int a = 5, b = 10; // a && b is invalid and will cause a compile-time error.
Logical operators work on boolean values, and confusing them with numerical values (e.g., 1
for true, 0 for false) can lead to logical errors.
Always use explicit boolean values (true or false) when using logical operators.
The ! (logical NOT) operator is only applicable to boolean values. Using ! on non-boolean
types will result in a compile-time error.
Logical operators are commonly used in if, while, and for conditions to evaluate multiple
expressions and determine the flow of control.
Introduction
It evaluates a boolean expression and returns one of two values based on the result of the
evaluation.
Usage:
Simplified if-else: Instead of writing an entire if-else block, the ternary operator allows you
to decide between two values in one line.
Program:
System.out.println("The maximum value is: " + max); // Output: The maximum value is: 20
int largest = (a > b) ? ((a > 15) ? a : 15) : ((b > 15) ? b : 15);
System.out.println("The largest value is: " + largest); // Output: The largest value is: 20
Output:
Program Explanation:
The ternary operator checks whether a > b. Since a is 10 and b is 20, it returns b (20)
because the condition is false.
Even/Odd Check:
This checks if a is divisible by 2 (i.e., whether it is even). Since a = 10 is even, the result is
"Even".
int largest = (a > b) ? ((a > 15) ? a : 15) : ((b > 15) ? b : 15);
Simple Conditional Logic: For simple checks, the ternary operator provides a cleaner, more
compact alternative to if-else statements.
Complex Conditions: If the condition is too complicated or the ternary operator becomes
hard to read, it’s better to use traditional if-else blocks.
Multiple Statements: The ternary operator is not suitable when multiple statements need to
be executed in each branch (for example, in the if or else block).
Concise Syntax:
The ternary operator is used to perform conditional logic in a single line, making the code
more compact.
Return Values:
The ternary operator returns one of two values depending on the condition. The values
must be of the same type or compatible types.
Type Consistency:
Both value1 and value2 in the ternary operator must be of the same type or must be
compatible types.
Example: We cannot have one value as an int and another as a String unless there’s an
explicit type cast.
We can nest ternary operators within each other, but excessive nesting can make the code
harder to read.
Example: int largest = (a > b) ? ((a > 15) ? a : 15) : ((b > 15) ? b : 15);.
Short-Circuit Evaluation:
The ternary operator performs short-circuit evaluation, meaning the second expression
(value2) is only evaluated if the condition is false.
Introduction
Unary operators are used to simplify expressions and perform operations like incrementing
or negating a value with minimal syntax.
For example :-
Negating a value: Achieved using the unary minus (-) or logical NOT (!).
etc...
Purpose: Represents a positive value. Often used to emphasize that a value is positive,
though it is not commonly used because values are positive by default.
Example:
int a = +5;
System.out.println(a); // Output: 5
Purpose: Negates a value, changing its sign from positive to negative or vice versa.
Example:
int a = 5;
System.out.println(-a); // Output: -5
++ (Increment Operator):
Example:
int a = 5;
System.out.println(a); // Output: 7
- (Decrement Operator):
Purpose: Decreases the value of a variable by 1. Can also be used in two forms:
Example:
int a = 5;
System.out.println(a); // Output: 3
Purpose: Inverts the value of a boolean expression. If the expression is true, it becomes
false, and vice versa.
Example:
Program:
// Initialize variables
int a = 5, b = -10;
// Pre-Increment (++a)
// Post-Increment (a++)
// Pre-Decrement (--a)
// Post-Decrement (a--)
Output:
Pre-Increment (++a): 6
Post-Increment (a++): 6
Pre-Decrement (--a): 6
Post-Decrement (a--): 6
The unary plus (+) operator is valid only for numeric types.
When used in complex expressions, the result depends on whether the operator is pre or
post.
Example:
int a = 5;
Increment/Decrement on Non-Variables:
Increment (++) and decrement (--) operators must be applied to variables, not constants or
expressions.
Unary operators have higher precedence than binary operators but lower than parentheses.
Example:
int a = 5, b = 10;
Chained Increment/Decrement:
Multiple increments or decrements can be chained, but their evaluation follows left-to-right
associativity.
Example:
int a = 5;
Example:
final int a = 5;
Increment and decrement can operate on char types, moving to the next or previous
Unicode value.
Example:
char c = 'A';
System.out.println(++c); // Output: B
Pre-increment (++i) is slightly more efficient than post-increment (i++) in loops due to
avoiding a temporary variable.
Example:
System.out.println(i);
Example:
int a = Integer.MAX_VALUE;
Example:
int a = 5;
Example:
arr[0]++;
System.out.println(arr[0]); // Output: 2
Multiple ! operators can be chained, effectively toggling the boolean value multiple times.
Example:
Introduction
Bitwise operators perform operations at the binary (bit) level on integer types such
as int, long, short, byte and char.
Usage:
Useful for tasks such as:
Operation:
They operate on the binary representation of numbers, modifying individual bits based on
the operator.
Operand Types:
Works only with integer data types (int, long, short, byte and char) but not with floating-
point or boolean values.
Efficiency:
Bitwise operations are computationally faster than arithmetic or logical operations, making
them ideal for performance-critical code.
Common Applications:
Shift Operations: Combine with shift operators (<<, >>, >>>) for tasks like scaling numbers
or accessing specific bits.
Purpose: Performs a bit-by-bit AND operation between two integer values. Each bit in the
result is 1 if the corresponding bits in both operands are 1; otherwise, it is 0.
Example:
| (Bitwise OR Operator):
Purpose: Performs a bit-by-bit OR operation between two integer values. Each bit in the
result is 1 if at least one of the corresponding bits in the operands is 1; otherwise, it is 0.
Example:
Purpose: Performs a bit-by-bit XOR (exclusive OR) operation between two integer values.
Each bit in the result is 1 if the corresponding bits in the operands are different; otherwise,
it is 0.
Example:
Purpose: Inverts each bit of its operand (also called one's complement). Each 1 becomes 0
and each 0 becomes 1. The result is equivalent to -(operand + 1).
Example:
Program:
// Initialize variables
System.out.println("Bitwise AND (a & b): " + (a & b)); // Output: 1 (Binary: 0001)
// Bitwise OR (|)
System.out.println("Bitwise AND (x & y): " + (x & y)); // Output: 8 (Binary: 1000)
Output:
Bitwise OR (a | b): 7
Bitwise OR (x | y): 14
Example:
Bitwise operators work only with integer types such as byte, short, int, long and char.
Applying bitwise operators to floating-point types (float, double) will result in a compilation
error.
Using it on non-integer types like boolean or String will result in a compilation error.
Bitwise operators have lower precedence than arithmetic operators but higher precedence
than comparison and logical operators.
Example: int result = (5 | 3) & 2; // Binary: (0101 | 0011) & 0010 = 0111 & 0010 = 0010 = 2
The behavior of bitwise operations is influenced by the number of bits in the data type.
For example, a byte uses 8 bits, so bitwise operations are limited to this range,
while int uses 32 bits.
The ~ operator flips all bits, including the sign bit in two's complement representation.
Example:
Example:
byte a = 5, b = 3;
Bitwise operators (&, |, ^) are not interchangeable with logical operators (&&, ||).
Introduction
Shift operators in Java are used to shift the bits of integer types (int, long, short, byte, char)
either to the left or right, allowing efficient manipulation of binary data.
Usage:
Useful for tasks such as:
Low-level programming: Used for manipulating binary data and hardware interaction.
Operation:
Binary Manipulation: Shift bits left or right to perform efficient binary tasks.
Operand Types:
Works only with integer data types (int, long, short, byte and char) but not with floating-
point or boolean values.
Efficiency:
Shift operations are faster than multiplication/division, ideal for performance-critical code.
Common Applications:
Scaling numbers: Left shift (<<) for multiplication by 2, right shift (>>) for division by 2.
Purpose: Shifts the bits of a number to the left by the specified number of positions, filling
the empty positions with zeros.
Effect: Multiplies the number by 2 for each position the bits are shifted.
Example:
int a = 5;
Purpose: Shifts the bits of a number to the right by the specified number of positions. The
empty positions on the left are filled based on the sign of the number (for signed types).
Effect: Divides the number by 2 for each position the bits are shifted, maintaining the sign of
the number.
Example:
int a = 20;
Purpose: Shifts the bits of a number to the right by the specified number of positions, filling
the empty positions with zeros, regardless of the sign.
Effect: Divides the number by 2 for each position the bits are shifted but does not preserve
the sign.
Example:
int a = -20;
System.out.println(a >>> 2); // Output: 1073741815 (binary of -20 shifted right with zero-
fill)
Program:
// Initialize variables
System.out.println("Left Shift (a << 1): " + (a << 1)); // Output: 10 (Binary: 1010)
System.out.println("Right Shift (a >> 1): " + (a >> 1)); // Output: 2 (Binary: 0010)
System.out.println("Unsigned Right Shift (a >>> 1): " + (a >>> 1)); // Output: 2 (Binary:
0010)
System.out.println("Left Shift (b << 1): " + (b << 1)); // Output: -20 (Binary:
11111111111111111111111111101100)
System.out.println("Unsigned Right Shift (b >>> 1): " + (b >>> 1)); // Output: 2147483643
(Binary: 01111111111111111111111111111011)
Output:
Example:
System.out.println(4 << 2); // Output: 16 (Binary: 0100 << 2 positions results in 10000)
System.out.println(8 >> 1); // Output: 4 (Binary: 1000 >> 1 position results in 0100)
Shift operators work only with integer types such as byte, short, int, long and char.
Applying shift operators to floating-point types (float, double) will result in a compilation
error.
System.out.println(5.5 << 1); // Compilation error: incompatible types: possible lossy
conversion from double to int
Example :
int x = 3;
The right shift operator (>>) is used for efficient division by powers of two.
Example :
int x = 16;
The unsigned right shift operator (>>>) behaves differently for negative numbers by filling
with zeros instead of extending the sign bit.
Example :
int x = -8;
The behavior of shift operators is distinct when applied to negative numbers, especially the
sign extension in the right shift (>>).
The left shift (<<) of a negative number behaves the same as for positive numbers but can
result in sign changes if the leftmost bit is shifted into the sign bit.
Example :
int x = -5;
The unsigned right shift (>>>) on negative numbers replaces the sign bit with 0, making it
useful for operations like bit masks or extracting specific parts of a number.
Example:
int x = -4;
The shift operators can be used on larger integer types like long. However, the right
operand should be masked with & 0x3F (for long shift) to avoid shifting more than 63
positions (for 64-bit long).
Example:
long x = 100L;
Negative values in the right shift operator (>> and >>>) will throw a compile-time error.
Example:
int x = 8;
While shifting, if the value overflows or underflows beyond the range of the data type, the
result can be unpredictable. Java’s shift operators do not raise errors for overflows but wrap
the result around based on the data type size.
Example:
int x = Integer.MAX_VALUE;
Introduction
It returns a boolean value: true if the object is an instance of the specified class or interface,
and false otherwise.
Syntax:
object instanceof ClassName
ClassName: The class or interface that you want to check the type of the object against.
Program:
class Animal
// some methods
// some methods
{
Animal animal = new Dog(); // Animal reference, but Dog object
else
Output:
Null Check:
The instanceof operator will always return false when the object being checked is null.
String str = null;
Inheritance Hierarchy: The operator works well with inheritance, checking if an object is an
instance of a superclass or subclass.
class Animal {}
Use in Interfaces:
The instanceof operator also works with interfaces. It checks if an object implements a
specific interface.
interface Playable {}
Performance:
Inheritance Hierarchy Traversal: It checks the class hierarchy, starting from the actual class
and moving up to the Object class. This is efficient but can cause slight overhead in complex
hierarchies.
Starting from Java 16, instanceof can be used in a switch statement with pattern matching.
switch (obj) {
case Dog d -> System.out.println("It's a dog!");
The instanceof operator is often used in conjunction with casting to safely cast objects.
System.out.println(str.length()); // Output: 5
The instanceof operator can be used with generics, but due to type erasure in Java, it can
only check the raw type of the generic class.
System.out.println("It's an ArrayList");
Keywords in Java
Introduction
Keywords are the predefined, reserved words used by the Java compiler for specific
operations.
There are total 50 keywords in Java, in which 48 keywords are actively used in
programming and 2 reserved words (goto and const) that are not currently used in java.
NOTE :
true, false and null are not keywords, they are literals (reserved words).
There are 5 Contextual keywords in Java, that act like keywords only in specific situations.
These keywords are var, yield, record, sealed and non-sealed. So total there are 57 reserved
words including 5 contextual keywords in Java.
Reserved Words: Keywords have specific meanings and are reserved for particular
functions in the Java language.
Case-Sensitive: All keywords in Java are case-sensitive (e.g., class is a keyword, but Class is
not).
Cannot be Identifiers: They cannot be used to name variables, methods, classes or other
user-defined identifiers.
Fixed Set: Java has a fixed list of keywords, and new ones are rarely added across versions
Identifiers in Java
Introduction
Just as "Priya" is a name used to identify the girl; in programming, identifiers are names
used to identify variables, classes, methods, interfaces or other elements in the code.
In simple words we can say, Ientifiers is any name, it can be variable, methods or class name
in our program.
They are unique names that help us recognize elements like variables, methods, and classes
in our program.
For example :
Valid Examples:
int myVariable;
String userName;
Invalid Examples:
Identifiers can include underscores (_) or dollar signs ($), but other special symbols
like @, # or ! are not allowed.
Valid Examples:
int _counter;
double $price;
String first_name;
Invalid Examples:
Identifiers cannot begin with a digit (0-9) but may include digits after the first character.
Valid Examples:
int variable1;
double _123value;
Invalid Examples:
Reserved keywords in Java (like class, public, if, etc.) cannot be used as identifiers.
Valid Examples:
int myClass;
String _if;
Invalid Examples:
Case Sensitivity.
Java identifiers are case-sensitive. For example, MyVariable and myVariable are treated as
distinct identifiers.
Valid Examples:
No Length Limit.
There is no specific limit on the length of an identifier, but it is recommended to keep names
concise and meaningful.
Valid Examples:
Avoid using names that conflict with commonly used built-in methods or library functions
to prevent confusion.
Valid Examples:
Choose names that describe the purpose of the variable or method to improve code
readability.
Valid Examples:
int x = 10; // Valid but not descriptive
Naming convention refers to a set of standardized rules and guidelines for naming classes,
methods, variables, and other identifiers to ensure code readability and maintainability.
Methods:
Variables:
Constants:
Packages:
Example: com.example.project.
Control Statements in Java
Introduction
Control statements in Java are the instructions that controls or manages the flow of
execution of a program based on specific conditions or loops.
Make decisions: Control program flow based on conditions (e.g., if, switch).
Loop through blocks of code: Repeat code execution multiple times (e.g., for, while).
Jump to a different part of the code: Change the natural flow of execution
(e.g., break, continue).
These statements allow the program to make decisions and execute a block of code based
on a condition.
These statements allow the execution of a block of code multiple times until a condition is
satisfied.
Jump Statements
These statements are used to alter the flow of control by jumping to a specific part of the
program.
Introduction
Just like in real life, in programming also, we face situations where we need to make
decisions based on certain conditions.
In Java, we use conditional statements to decide which part of the code should run
depending on the condition.
Decide which block of code should be executed when certain conditions are met.
if-else: Runs one block of code if true, and another block if false.
if-else if ladder: Checks multiple conditions one by one and runs the block of code for the
first true condition.
If the condition is true, the block of code inside the if statement is executed.
Syntax:
if(condition)
{
Program:
if (number > 0)
Output:
NOTE :
If there is only one statement in if block, then curly braces {} are optional.
Syntax :
if(condition)
statement;
Example :
if (number > 0)
If the condition is true, the block of code inside the if is executed; otherwise, the code inside
the else block runs.
Syntax:
if(condition)
else
Program:
if (number > 0)
else
Output:
NOTE :
If there is only one statement in if-else block, then curly braces {} are optional.
Syntax :
if(condition)
statement;
else
statement;
Syntax:
if (condition1)
else if (condition2)
else
Program:
System.out.println("Grade: A");
}
System.out.println("Grade: B");
System.out.println("Grade: C");
else
System.out.println("Grade: F");
Output:
Grade: B
The switch statement in Java runs one block of code based on matching a condition.
It checks multiple cases for a value and runs the matching case.
Syntax:
switch (expression)
case value1:
// Code to execute if expression equals value1
break;
case value2:
break;
default:
break;
NOTE : Instead of writing many if-else statements, we can use the switch statement for
simpler code.
Program:
int day = 3;
switch (day)
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("Invalid day");
Output:
Wednesday
Introduction
do-while: Executes a block of code once, then repeats it as long as the condition is true.
The for loop is used to repeat a block of code a specific number of times.
The for loop is useful when the number of iterations is known beforehand (i.e. we know
exactly how many times we need to repeat a task), like when working with arrays or
running a piece of code a specific number of times.
Syntax:
Initialization: Variable is initialized before the loop starts. This part runs only once at the
beginning.
Condition: Checks the condition before each iteration. If the condition is true, the loop
continues to execute the for block statements.
Increment/Decrement: Updates the loop variable, helping the loop move toward finishing.
Statements: Statements which are executed when the for loop condition is true.
Program:
Output:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
NOTE :
If there is only one statement in for loop, then curly braces {} are optional.
Syntax :
Example :
The while loop is used to repeat a block of code as long as a specific condition is true.
The while loop is useful when we don’t know how many times we need to repeat the task,
and the loop will continue as long as the condition holds true.
Syntax:
while (condition)
Condition: Checks the condition before each iteration. If the condition is true, the loop
continues to execute the while block statements.
Statements: The statements inside the loop are executed repeatedly as long as the condition
remains true.
NOTE :
If the condition is false, the loop will not run even once.
If the condition is always true, then the loop will run infinite times.
Program:
Solution : Since we don't know the exact number of even numbers within this range, we
should avoid using a for loop and instead use a while loop.
Output:
Even Number: 2
Even Number: 4
Even Number: 6
Even Number: 8
Even Number: 10
Even Number: 12
Even Number: 14
Even Number: 16
NOTE :
If there is only one statement in while loop, then curly braces {} are optional.
Syntax :
while(condition)
statement;
The do-while loop is used to repeat a block of code at least once and then repeatedly as long
as the condition is true.
The do-while loop is useful when we want the code to run at least once, even if the condition
is false initially.
Syntax:
do
} while (condition);
Statements: The block of code that will be executed at least once, regardless of the
condition.
Condition: After executing the statements, the condition is checked. If it evaluates to true,
the loop continues to execute the statements. If it's false, the loop terminates.
NOTE :
The do-while loop guarantees that the code inside the loop will run at least once.
The loop then checks the condition after the code execution, and if true, it continues to run.
If false, it exits.
Program:
Task : The user will provide an input, and we need to check whether it is a positive or
negative number.
Solution : Since the user will always provide input, we need to check the number. We have
to ensure that the code for taking input is always executed first, so we have to use do-
while loop.
import java.util.Scanner;
int number;
do
number = scanner.nextInt();
Here we have used Scanner class for User Input, to read Scanner Class deeply with
Program.
Output:
The for-each loop (also called Enhanced For Loop) in Java is used to iterate over elements in
an array or collection without needing an index variable.
It's commonly used when we don’t need to know the index of the element and simply want
to process each element in the collection.
Syntax:
dataType: Specifies the type of the elements in the collection (e.g. int, String).
collection: The array or collection (i.e. List, Set etc.) we want to iterate over.
NOTE : The for-each loop (enhanced for loop) in Java is primarily used with arrays and
collections, but it can also be used with any other Iterable objects also.
Program:
System.out.println(fruit);
Output:
Apple
Banana
Cherry
Advantages:
Simplifies code by removing the need to manually manage the loop index.
Introduction
Jump statements transfer the program's control from one part of the code to another,
skipping the lines in between.
By default, Java programs execute statements line by line from top to bottom, but jump
statements allows us to:
Break the usual execution order (e.g., exit a loop early using break).
Return control to the method caller (e.g., exit a method and optionally return a value
using return).
Examples of Jump Statements in Java:
continue: Skips the current loop step and moves to the next one
The break statement is used to exit a loop or a switch statement before it has completed its
normal execution.
Loops: The break statement can be used to terminate loops (for, while, do-while)
prematurely when a specific condition is met.
Switch Statements: It is commonly used in switch statements to exit a particular case and
prevent the execution of subsequent cases.
How it works:
The break statement stops the loop or case execution and moves the control to the first
statement outside the loop or switch block.
Syntax:
break;
if (i == 5)
Output:
Number: 1
Number: 2
Number: 3
Number: 4
int day = 3;
switch (day)
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thrusday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("Invalid day");
Output:
Wednesday
Important Notes:
If placed in nested loops, the break statement only terminates the innermost loop it is part
of.
We should use break wisely to avoid abrupt terminations that can make the program logic
harder to follow.
The continue statement is used to skip the current iteration of a loop and move to the next
iteration without completing the remaining code in the loop for that iteration.
It is useful when we want to skip specific conditions and proceed with the rest of the loop.
How it works:
In Loops:
When the continue statement is encountered, the loop immediately jumps to the next
iteration.
Syntax:
continue;
if (i == 3)
}
System.out.println("Number: " + i);
Output:
Number: 1
Number: 2
Skipping number: 3
Number: 4
Number: 5
int number = 1;
if (number == 3)
Output:
Number: 1
Number: 2
Skipping number: 3
Number: 4
Number: 5
Important Notes:
The continue statement works with for, while, and do-while loops.
It only skips the current iteration of the loop and does not terminate the loop entirely.
We should use continue carefully, as it can sometimes make the program harder to
understand.
The return statement is used to exit from a method and optionally send a value back to the
method's caller.
It is essential for returning a result from a method or terminating the execution of a method
before it reaches its end.
The usage of the return keyword in Java, categorized into two main cases:
Methods returning a value: The return keyword sends a value back to the caller.
How it works: You specify the type of value the method will return
(e.g. int, String, boolean etc), and the method sends this value back using
the return keyword.
Example:
These methods do not return anything to the caller, but they can still use return in two
ways:
How it works: The return statement is used without a value to stop the method's execution
and return control to the caller.
Example:
How it works: return is simply used to exit the method when no value needs to be returned.
Example:
System.out.println("Hello, World!");
Syntax:
return value; // For methods with return types, to send a value back.
int sum = a + b;
}
Output:
Result: 8
System.out.println("Voting Ended.");
Output:
Voting Ended.
NOTE : After the return statement, no other statements can be written in that method
because the control has already been returned to the caller.
Object Oriented Programming in Java
What is OOP's ?
OOPs in Java is a programming paradigm or approach that organizes code using objects and
classes to improve reusability, modularity, and maintainability
Polymorphism - Having multiple methods with the same name but different behavior
(method overloading/overriding).
Abstraction - Hiding complex details and showing only the essential features.
NOTE :
Java is strongly Object Oriented Language but not purely Object oriented because java as
primitive data types and static concept which is not related or tied to objects
A class is a template or blueprint used to categorize objects. For example, we can have
classes like Animal, Birds, Vehicles and Furniture. Each class can have multiple objects,
which represent real-world entities.
The Animal class can have objects such as elephant, tiger, dog etc.
The Birds class can have objects like sparrow, peacock etc.
Every class has its own methods, which define the actions that objects can perform:
The Animal class may have methods like eat(), run(), sleep() etc.
The Birds class may have methods like fly(), eat() etc.
Since objects represent real-world entities, they are used to call methods and perform
actions.
It is not a real-world entity, means it does not exist physically; it only defines how an object
should behave.
NOTE : Class metadata (such as the number of variables, variable names, method names,
constructors, etc.) is stored in the Method Area.
Syntax :
Example :
//fields
int eyes;
String color;
//method
void run()
//body
Advance Concept
If you want to read "Different types of classes in Java", then
There are different types of java classes which are listed below, these all classes are
explained in further tutorials...
Syntax :
// body
Example :
System.out.println(name+" is running");
Object is an instance of a class - Objects are created from a class blueprint and represent
real data.
Object is a real-world entity - It represents tangible things like a car, person, or book in
programming.
Object occupies memory - When an object is created (new ClassName()), it gets memory
allocated in the heap.
Syntax :
1. Creating Objects:
ClassName objectName = new ClassName();
new ClassName(); — Creates a new object of ClassName by allocating memory and calling
its constructor.
= — Assigns the reference (address) of the newly created object to the variable objectName.
objectName.methodName();
objectName.field_name;
Example :
System.out.println("Im running");
}
}
Program 1:
Below is the simple program in which we have created one Animal1 class, one run() method
and called the run() method using jambo object.
jumbo.run();
Output:
I'm running
Program 2:
Below is the simple program having one Animal2 class, two methods
i.e. run() and eat() method and jambo object is accessing both the methods.
jumbo.run();
jumbo.eat();
Output:
I'm running
I'm eating...!!
Program 3:
Below is the simple program having one Animal3 class, two methods
i.e. run() and eat() methods. Then two objects i.e. jambo and buzo objects are accessing both
the methods.
jumbo.run();
jumbo.eat();
buzo.eat();
buzo.run();
Output:
I'm running
I'm eating...!!
I'm eating...!!
I'm running
Program 4:
}
// Method to display that an animal is eating
Output:
Jumbo is running
Jumbo is eating...!!
Buzo is eating...!!
Buzo is running
Program 5:
jumbo.run("Jumbo", 5); // Call run method with name "Jumbo" and distance 5 km
jumbo.eat("Jumbo", "grass"); // Call eat method with name "Jumbo" and food "grass"
buzo.eat("Buzo", "meat"); // Call eat method with name "Buzo" and food "meat"
buzo.run("Buzo", 12); // Call run method with name "Buzo" and distance 12 km
Output:
Program 6:
Below is the another program with instance variables and method parameter.
// Define a class named Animal6
jumbo.no_of_eyes = 2;
jumbo.color = "Brown";
buzo.color = "Black";
Output:
------Details of Jumbo-------
Eyes : 2
Color : Brown
------Details of Buzo-------
Eyes : 2
Color : Black
In above programs we have created main method in Animal class which is not good
practice, we should always create main method in main class only, below is the program.
class Animal7
void run()
System.out.println("I'm running");
Output:
I'm running
Here we have created Animal8, Birds8 class with different methods and also created Main
class as separate class which is good practice.
class Animal8
void run()
System.out.println("I'm running");
void fly()
System.out.println("I'm flying");
buzo.run();
sparrow.fly();
Output:
I'm running
I'm flying
Constructors in Java
It is called when an instance of the class is created or say, when an object of a class is
created.
Whenever an object is created using the new keyword, at least one constructor is called.
Syntax :
//body
Example :
//constructor
public Test()
//body
}
}
Use of Constructor:
Constructors are used to initialize the object. It means that constructor assigns the values to
the instance variables when an object is created. This can be done manually by the
programmer or automatically by Java using a default constructor.
Note : Constructors are not used to create an object, they are only used to initialize an
object.
The constructor must have the same name as that of class name.
Constructors can have any access modifier (public, private, protected or default) but cannot
have non-access modifiers like static, final, abstract etc.
1. Default Constructor:
If programmer does'nt create any constructor, then Java compiler automatically creates one
constructor which is known as default constructor.
Syntax :
class ClassName
Example :
//here programmer didnt created any constructor, so Java compiler will create default
constructor automatically.
Test t = new Test(); //default constructor called automatically when we create object
The access modifier of Default Constructor is as that of class. If a class is public, the default
constructor is public and so on.
public Test()
super();
It is used to initialize objects with default values or perform some basic setup.
Syntax :
class ClassName
// No-Argument Constructor
ClassName()
Example :
String name;
// No-Argument Constructor
Student()
void display()
}
public static void main(String[] args)
3. Parameterized Constructor:
It is used to:
Syntax :
class ClassName
// Initialization code
Example :
class Student
String name;
int rollno;
// Parameterized Constructor
name = n;
rollno = rn;
void display()
Introduction
Relationship between classes describes that how multiple classes interact with or depend
on each other.
These relationships help structure and organize code in a logical and maintainable way.
Types of relationships between classes in Java:
Definition : Association is a relationship where one class interacts with another class.
Example :
Program :
class Address
void displayAddress()
class Student
{
String name = "Deepak";
Address address = new Address(); // Object created directly inside the class
void displayInfo()
address.displayAddress();
Output:
Definition :
Association is a relationship where one class uses or interacts with another class by holding
a reference to it. It represents a HAS-A relationship in object-oriented programming.
Example :
Constructor Injection
Setter Injection
class Address
void displayAddress()
class Student
Address address = new Address(); // Object created directly inside the class
void displayInfo()
address.displayAddress();
}
Output:
class Engine
void startEngine()
System.out.println("Engine starts.");
class Car
Car(Engine engine)
this.engine = engine;
void startCar()
myCar.startCar();
Output:
Engine starts.
Car starts.
class Processor
void startProcessor()
}
class Laptop
this.processor = processor;
void startLaptop()
processor.startProcessor();
System.out.println("Laptop starts.");
myLaptop.setProcessor(processor);
myLaptop.startLaptop();
Output:
Laptop starts.
Types of Association:
Aggregation
Example:
The Music Player can be removed, reused, or replaced — it can exist without the car.
Composition
Example:
Note : In both Aggregation and Composition, program logic remains the same, but the
relationship between the classes is different.
One-to-One
One-to-Many
Many-to-One
Many-to-Many
*These are also known as Cardinality of Associations. Cardinality is the count or the number
of connections.
Definition :
Dependency is a relationship where one class uses another class to perform a specific task.
It typically exists when one class depends on another temporarily, usually within a method.
Method parameters
Program :
class Printer
{
System.out.println("Printing document: " + doc);
class OfficeWorker
void doWork()
printer.printDocument("ProjectReport.pdf");
System.out.println("Work completed.");
Output:
Work completed.
Definition :
Dependency is a relationship where one class uses another class temporarily to perform a
specific task. This means the dependent object is often used within a method, rather than
being stored as an instance variable.
The dependency is typically short-lived, existing only during the execution of a method.
Example :
Method Parameter
// Dependent class
class Whiteboard
void writeOnBoard()
class Teacher
void teachLesson()
// Entry point
Output:
// Dependent class
class Printer
void printDocument()
System.out.println("Printing document...");
class OfficeWorker
// Entry point
worker.performTask(printer);
Output:
Printing document...
Dependency vs Association:
Definition : IS-A (Inheritance) is the process by which a child class (subclass) inherits fields
and methods from a parent class (superclass).
Program :
class Vehicle
void start()
{
System.out.println("Vehicle starts.");
void drive()
System.out.println("Car drives.");
Output:
Vehicle starts.
Car drives.
Inheritance in Java
Introduction
Inheritance means acquiring the properties and behaviors of a parent class in a child class.
It allows a subclass (child class) to inherit fields and methods from a superclass (parent
class), promoting code reuse and method overriding.
For example:
class Vehicle
void start()
System.out.println("Vehicle starts.");
{
void drive()
System.out.println("Car drives.");
interface Animal
void eat();
System.out.println("Dog eats.");
}
Advantages of Inheritance
Code Reusability: Inheritance allows a child class to reuse the code of its parent class.
Easy Maintenance: Changes made in the parent class automatically propagate to child
classes, making maintenance easier.
Disadvantages of Inheritance
Tight Coupling: Inheritance creates a tight coupling between parent and child classes, if we
change the parent class, it may affect all child classes.
Increased Complexity: Inheritance can lead to complex class hierarchies, making the code
harder to understand and maintain.
Note : Inheritance should be used carefully. It is not always the best solution for code reuse.
In some cases, composition (using objects of other classes) may be a better approach.
Types of Inheritance
Single Inheritance: One class inherits the properties and behaviors of one parent class.
Multilevel Inheritance: One class inherits the properties and behaviors of a parent class, and
that class is inherited by another class.
Hierarchical Inheritance: Multiple classes inherit the properties and behaviors of a single
parent class.
Multiple Inheritance: One class inherits the properties and behaviors of multiple classes.
(Not supported in Java directly, but can be achieved using interfaces.)
Introduction
in Java means one class can use the properties (like variables and methods) of another class.
It creates a parent-child relationship, where the parent is called the superclass and the child
is called the subclass.
Single Inheritance
Multilevel Inheritance
Hierarchical Inheritance
Single Inheritance:
Single level inheritance is a type of inheritance in which a child class inherits directly from a
single parent class.
It allows the child class to reuse the fields and methods of the parent class.
Syntax:
class ParentClass {
Program example:
// Parent class
class BankAccount
void accountType()
// Child class
void interestRate()
// Main class
Output:
Multilevel Inheritance:
Multilevel inheritance is a type of inheritance where a class inherits from a child class,
making a chain of inheritance.
Here, a class acts as a parent for another class, which in turn acts as a parent for a third
class.
Syntax:
class Grandparent
// code
}
// code
// code
Program example:
// Grandparent class
class Animal
void eat()
System.out.println("Animal is eating.");
// Parent class
void bark()
System.out.println("Dog is barking.");
}
// Child class
void weep()
System.out.println("Puppy is weeping.");
Output:
Animal is eating.
Dog is barking.
Puppy is weeping.
Important Points to Remember:
Multilevel inheritance represents a class hierarchy with more than two levels.
The child class inherits properties from its parent class and all ancestor classes.
Hierarchical Inheritance:
Hierarchical inheritance is a type of inheritance where multiple child classes inherit from a
single parent class.
It allows multiple subclasses to share the properties and behaviors of the same parent class.
This type of inheritance is useful for creating a common base class for multiple classes.
Syntax:
class Parent
Program example:
// Parent class
class Vehicle
void fuelType()
System.out.println("Uses fuel.");
void wheels()
void handleType()
}
public class MainApp
Output:
Uses fuel.
Uses fuel.
Each subclass gets its own copy of the parent class’s properties and methods.
It's useful when multiple classes share common behavior and properties.
Multiple Inheritance:
Note: Java does not support multiple inheritance with classes to avoid ambiguity problems
(commonly known as the "Diamond Problem"). However, it can be achieved
using interfaces.
Multiple inheritance refers to a feature where a class can inherit features (methods and
fields) from more than one parent class.
Java does not support multiple inheritance with classes directly, but it supports it
through interfaces.
interface A
void methodA();
interface B
void methodB();
class C implements A, B
{
System.out.println("Method from interface B");
// Interface A
interface A
void displayA();
// Interface B
interface B
void displayB();
class C implements A, B
obj.displayA();
obj.displayB();
Output:
Hybrid Inheritance:
Note: Java does not support hybrid inheritance with classes directly because it may lead to
ambiguity. However, it can be achieved using interfaces to simulate hybrid behavior.
Hybrid inheritance is a combination of two or more types of inheritance (e.g., single,
multiple, multilevel).
It represents a scenario where different inheritance types are combined to form a complex
hierarchy.
Java does not support hybrid inheritance with classes due to ambiguity issues but supports
it through interfaces.
interface A
void methodA();
interface B
void methodB();
class C
void methodC()
// Interface A
interface A
void showA();
// Interface B
interface B
void showB();
// Class C
class C
void showC()
// Main class
obj.showA();
obj.showB();
obj.showC();
Output:
Important Points
Java does not support multiple and hybrid inheritance with classes to avoid ambiguity, such
as the diamond problem.
A class can extend only one class, which is known as single inheritance.
Constructors and private members of the parent class are not inherited by the child class.
A class can implement multiple interfaces, which is Java's way of achieving multiple
inheritance.
The super keyword is used to refer to the parent class, such as accessing parent class
methods or constructors.
The this keyword is used to refer to the current class instance, commonly used to
differentiate between instance variables and parameters.
Polymorphism in Java
Introduction
It means the ability of a single entity (method, object, or operator) to behave in multiple
ways.
Real-world Examples :-
Advantage of Polymorphism :-
Compile-Time Polymorphism
In compile-time polymorphism, the Java compiler decides at compile time which overloaded
method or operator to invoke based on the method signature and reference type.
Program ():
class Calculator
System.out.println(a+b);
System.out.println(a+b);
Here:
Introduction
It is a feature in Java that allows a class to have more than one method with the same name,
but different parameters (number, type, or order of parameters).
The compiler determines which method to execute at compile time, based on the method
signature.
Number of parameters
Type of parameters
Order of parameters
Example :-
class Calculator
return a + b;
return a + b;
return a + b + c;
{
public static void main(String[] args)
Output:
Note :
Method Overloading is used to perform similar operations with different types or numbers
of inputs using the same method name.
Java chooses the best matching method based on the arguments passed.
Increased Readability:
Using the same method name for similar actions makes the code easier to understand.
Easy Maintenance:
Having logically grouped methods under one name makes code more organized and easier
to maintain.
Avoids writing similar code in different method names for similar logic.
Helps in Testing:
Easier to write unit tests for overloaded methods as they often represent the same action
with varied input.
When designing libraries or APIs, overloading allows a consistent interface for different
data inputs.
Important Points
Method overloading does not depend on return type, it depends only on the parameter list.
}
Constructors can also be overloaded.
class Student
Student() {}
Student(String name) {}
Runtime Polymorphism
Program ():
class Animal
void makeSound()
}
class Dog extends Animal
void makeSound()
System.out.println("Dog barks");
Here:
Animal obj = new Dog(); // Reference type = Animal, Object type = Dog
Introduction
It is a feature in Java that allows the child class to write its own implementation of a method
that is already present in the parent class.
The JVM determines which method to execute at runtime, based on the object type (not the
reference type).
Number of parameters
Type of parameters
Order of parameters
Should follow IS-A relationship (Inheritance).
Example :-
class Bank
double getInterestRate()
return 0.0;
@Override
double getInterestRate()
return 6.5;
@Override
double getInterestRate()
return 7.0;
}
}
@Override
double getInterestRate()
return 6.8;
Output:
Runtime Polymorphism::
Allows Java to decide at runtime which method to execute, enabling flexible and dynamic
behavior.
Reuses method names from the parent class while allowing customized behavior in the
child class.
Supports Inheritance:
Makes the code more logical and organized when different classes handle behavior in their
own way.
Encourages Consistency::
Keeps method names the same across class hierarchies, promoting consistency in design.
Commonly used in Java frameworks (like Spring, Hibernate) where parent classes define
default behavior and subclasses override as needed.
Important Points
Method overriding requires the subclass method to have the same name, return type, and
parameter list as the superclass method.
// Valid override
The overriding method can throw only the same or narrower checked exceptions than the
overridden method.
@Override
void methodName() {
// implementation
Important Points
Polymorphism helps reduce code duplication by reusing the same interface or method
name across different types.
Example:
Abstraction in Java
Introduction
Abstraction is a concept of :
hiding internal implementation details and showing only the essential features to the user.
When you drive a car, you only need to know how to operate the steering wheel, pedals and
gear shift. You don't need to understand how the engine works or how the brakes are
designed.
Using Interfaces
Abstract Methods :-
Introduction
Abstract methods must be overridden by subclasses, unless the subclass is also abstract.
Abstract Class :-
Introduction
An abstract class in Java is a class that is declared using the abstract keyword.
It can contain a mix of abstract methods (without body) and concrete methods (with body).
Syntax:
// abstract method
// concrete method
void sleep()
{
System.out.println("Sleeping...");
Example:
// Concrete method
void fuelType()
@Override
void startEngine()
class Car
int no_of_tyres = 4;
void displayTyres()
void start()
class Scooter
int no_of_tyres = 2;
void displayTyres()
void start()
myCar.displayTyres();
myCar.start();
System.out.println();
myScooter.displayTyres();
myScooter.start();
}
}
Output:
No Polymorphism:
Example:
Vehicle vehicle = new Car(); // Not possible, because there is no common Vehicle type
This limits flexibility and makes it hard to treat Car and Scooter uniformly.
Code Duplication:
Common logic like displayTyres() is repeated in every class (Car, Scooter, etc.).
In a larger system, this leads to duplicate code, harder maintenance, and higher chances of
bugs.
No Method Enforcement:
There is no guarantee that all vehicle-related classes will implement essential methods like
start().
A developer might forget to add a critical method in a new class like Bike, leading to
incomplete functionality.
Poor Scalability:
As the project grows and more vehicle types are added, maintaining consistency becomes
harder.
Any change in shared logic (e.g., tyre display format) needs to be updated in every
individual class, increasing maintenance overhead.
This leads to inconsistent design and makes collaboration or team development harder.
// Abstract class used to remove code duplication and enforce method structure
int no_of_tyres;
void displayTyres()
// Car class extends abstract class and provides its own implementation
Car()
no_of_tyres = 4;
}
// Required by abstract class - enforces structure (removes disadvantage #3)
@Override
void start()
Scooter()
no_of_tyres = 2;
@Override
void start()
{
public static void main(String[] args)
myVehicle1.displayTyres();
myVehicle1.start();
System.out.println();
myVehicle2.displayTyres();
myVehicle2.start();
// Easier to scale and add new vehicle types consistently (removes disadvantage #4)
Output:
Interface in Java
Introduction
Interfaces are similar to abstract class but having all the methods of abstract type.
Note :
Till Java 7, interfaces can contain only abstract methods and constants.
In Java 8, we can provide the implementation of methods using default methods and static
methods.
Syntax :-
interface InterfaceName
Use of Interfaces :-
Used extensively in frameworks, APIs, and design patterns (e.g., DAO, Service Layer).
Example:
interface Vehicle
{
void start();
void stop();
System.out.println("Car is starting...");
System.out.println("Car is stopping...");
v.start();
v.stop();
}
Output:
Car is starting...
Car is stopping...
Example:
interface Printable
void print();
// Unrelated class 1
System.out.println("Printing document...");
// Unrelated class 2
System.out.println("Printing image...");
// Main class
p1.print();
p2.print();
Output:
Printing document...
Printing image...
Example:
interface I1
void m1();
}
interface I2
void m2();
// Main class
obj.m2();
Output:
Example:
import java.util.Scanner;
interface Payment
void pay();
}
// Net Banking Payment Implementation
// Checkout class using interface (not tightly bound to any one payment method)
class PaymentCheckout
payment.pay(); // Loose coupling: works with any class that implements Payment
System.out.println("1. UPI");
switch (choice)
case 1:
checkout.payment(new UpiPayment());
break;
case 2:
checkout.payment(new NetBankingPayment());
break;
default:
System.out.println("Invalid choice");
Output:
If user enters 1:
1. UPI
2. Net Banking
Enter choice: 1
1. UPI
2. Net Banking
Enter choice: 2
Frameworks:
Java APIs:
Design Patterns:
Testing:
Encapsulation in Java
Introduction
Encapsulation is the mechanism of binding data (variables) and actions (methods) into a
single unit, called a class.
class Car
String brand;
int speed;
brand = b;
speed = s;
void printDetails()
// Creating object
// Calling method
c.setDetails("Tata", 100);
Output:
Brand : Tata
Speed : 100
Explanation:
Person class contains both data (name, age) and method (displayInfo()).
Note :
Above example is simple encapsulated class, but it does not provide any data hiding.
So, to create proper encapsulation, we have to follow some rules which are explained below.
1. Private Variables :
Declare variables as private so that they cannot be accessed directly from outside the class.
Provide public getter and setter methods to access and modify the private variables.
class Car
{
// Private data members (encapsulated)
this.brand = brand;
return brand;
if (speed >= 0)
this.speed = speed;
}
// Public getter for speed
return speed;
c.setBrand("Tata");
c.setSpeed(100);
c.printDetails();
}
Output:
Speed : Tata
Speed : 100
Use of Encapsulation :-
Protects data: Hides data from direct access using private variables.
Controls data access: Provides controlled access through public getters and setters.
Allows data validation: Enables validation before updating variables (e.g., checking valid
input).
Enhances flexibility: Internal logic can change without affecting external code.
Prevents unauthorized or accidental modifications: Limits who and how data can be
changed.
Example:
class Account
return accountHolder;
this.accountHolder = accountHolder;
return balance;
if (amount > 0)
}
else
else
// Creating object
account.setAccountHolder("Deepak");
Output: