0% found this document useful (0 votes)
6 views216 pages

Cleaned_Java_Notes

Java is a high-level, object-oriented programming language that allows developers to create a variety of applications, including desktop, web, and mobile applications. It has five main editions: Java SE for general-purpose programming, Java EE for enterprise applications, Java ME for resource-constrained devices, JavaFX for rich internet applications, and Java Card for secure environments. Key features of Java include platform independence, robustness, security, and a rich set of APIs, making it versatile for various development needs.

Uploaded by

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

Cleaned_Java_Notes

Java is a high-level, object-oriented programming language that allows developers to create a variety of applications, including desktop, web, and mobile applications. It has five main editions: Java SE for general-purpose programming, Java EE for enterprise applications, Java ME for resource-constrained devices, JavaFX for rich internet applications, and Java Card for secure environments. Key features of Java include platform independence, robustness, security, and a rich set of APIs, making it versatile for various development needs.

Uploaded by

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

Java Introduction

Java is a :-

Programming Language :

Java is a high-level, object-oriented programming language that enables developers to write


instructions for execution.

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.

It is designed to be simple, object-oriented, and user-friendly, similar to languages like C


and C++.

Types of Java Edition

There are total 5 editions in Java which are as below :-


1. Java Standard Edition (Java SE)
2. Java Enterprise Edition (Java EE)
3. Java Micro Edition (Java ME)
4. JavaFX
5. Java Card

These are explained deeply in below....

1. Java Standard Edition (Java SE)

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 :

Desktop Applications : Java SE is used to create standalone desktop applications, such as


productivity software, utilities, and games. Examples include IDEs like IntelliJ IDEA and
software like Eclipse.

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.

2. Java Enterprise Edition (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.

Enterprise Applications : Java EE is ideal for developing complex, scalable enterprise


systems like ERP (Enterprise Resource Planning) and CRM (Customer Relationship
Management) systems.

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.

3. Java Micro Edition (Java ME)

Introduction : Java ME is a subset of Java SE designed for developing applications on


resource-constrained devices like embedded systems, mobile phones, and IoT (Internet of
Things) devices.

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.

Multimedia Applications : JavaFX is suitable for developing applications that require


advanced graphics, media playback, and complex animations.

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.

Contactless Payment Systems: Java Card is commonly employed in contactless payment


systems such as NFC-based payment cards and mobile payment solutions. Its secure and
lightweight environment ensures the protection of financial transactions.

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.

JVM : The JVM is a crucial component of Java’s platform independence. It interprets or


compiles bytecode into native machine code specific to the underlying hardware and
operating system. By adhering to the JVM specification, Java applications can run
consistently on any platform that has a JVM implementation.

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 :

Encapsulation : Encapsulation involves bundling the data (attributes) and methods


(functions) that operate on the data into a single unit called a class. Access to the data is
controlled using access modifiers like private, protected, and public, which helps in
protecting the integrity of the data and exposing only what is necessary.

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.

Polymorphism : Polymorphism enables objects to be treated as instances of their parent


class rather than their actual class. It allows methods to be overridden in derived classes
and provides flexibility in method invocation. For example, a method makeSound() can be
defined in a parent class Animal and overridden in subclasses Dog and Cat to produce
different sounds.

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

Definition : Java is designed to be a reliable and error-resistant programming language.

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.

Automatic Garbage Collection : Java’s garbage collector automatically reclaims memory


used by objects that are no longer reachable, reducing the risk of memory leaks and
ensuring efficient memory management.

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

Definition : Java incorporates various security features to protect applications from


unauthorized access and malicious activities.

Detailed Explanation :

Bytecode Verification : Before execution, Java bytecode undergoes verification to ensure it


adheres to the Java language specification and does not contain illegal code that could
compromise the security of the JVM.

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.

No Recompilation : Unlike C/C++, Java doesn't require platform-specific recompilation.

Standard Libraries : Libraries handle system-specific differences, maintaining consistent


behavior.

Example : A Java app compiled on Windows runs seamlessly on Linux or macOS if JVM is
installed.

6. Simple

Definition : Java is designed to be a straightforward and accessible programming language.

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 :

Threading Support : Java provides a comprehensive threading model with the


java.lang.Thread class and the java.util.concurrent package. Threads allow Java applications
to perform multiple tasks concurrently, improving performance and responsiveness.

Synchronization : Java includes mechanisms to manage access to shared resources among


threads. The synchronized keyword and concurrency utilities like ReentrantLock ensure
that only one thread can access a critical section of code at a time, preventing race
conditions.

Concurrency Utilities : The java.util.concurrent package offers high-level concurrency


utilities such as thread pools (ExecutorService), concurrent collections
(ConcurrentHashMap), and atomic variables (AtomicInteger), which simplify the
development of multithreaded applications.

8. Distributed

Definition : Java facilitates the development of distributed applications, where components


can communicate over a network.

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

Definition : Java is an adaptable and flexible language, capable of accommodating changes


and extending its functionalities.

Detailed Explanation :

Runtime Polymorphism : Java supports runtime polymorphism, allowing methods to be


bound to their implementations at runtime rather than compile-time. This enables flexible
and dynamic behavior in Java applications.

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.

10. High Performance

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.

Efficient Memory Management : Java’s garbage collection mechanism is optimized to


manage memory efficiently. The JVM uses techniques like generational garbage collection
and concurrent garbage collectors to minimize pauses and improve application
responsiveness.

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.

11. Rich API

Definition : Java offers a comprehensive and extensive set of APIs (Application


Programming Interfaces) that simplify development and provide a wide range of
functionalities.

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.

13. Scalability and Performance

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.

Enterprise-Level Scalability : Java EE (now Jakarta EE) provides enterprise-level features


like clustering, caching, and session management that are essential for building large,
scalable applications. These features allow applications to handle increasing loads without
compromising performance.

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

Definition : Java’s interoperability features allow it to work seamlessly with other


programming languages and platforms, enhancing its flexibility in diverse environments.

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.

16. Community and Ecosystem

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

Server-Side Technologies : Java is extensively used in web development, particularly on the


server side. Frameworks like Spring, JavaServer Faces (JSF), and Apache Struts help build
robust, scalable web applications.

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.

5. Scientific and Research Applications

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.

6. Big Data Technologies

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.

JDK, JRE, JVM

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

a runtime environment (Java Runtime Environment or JRE).

Below is the diagram showing JDK architecture in Java.

Components of JDK :-

There are 2 main components in JDK which are as below :-

JDK (Java Development Kit) = 1 - Development Tools + 2 - JRE (Java Runtime


Environment)

Development Tools:

Other Development Tools (you can skip)

Java Runtime Environment (JRE):

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

Development : Used by developers to create and compile Java applications.

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.

Below is the diagram showing JRE architecture in JDK.

Components of JRE :-

There are 4 main components in JDK which are as below :-

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.

These are divided in 3 main categories :-

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.

Below is the diagram showing JVM architecture in JRE.

Components of JVM :-

There are 3 main components in 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.

Structure Of Java Program

Structure of Java Program

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.

This structure if explained below :-

1. Package Declaration Statement (Optional)

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;

2. Import Statements (If Necessary)

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 :

import packageName.ClassName; // Imports a specific class

import packageName.*; // Imports all classes in the package


Example :

import java.util.Scanner; // Imports Scanner class

import java.util.*; // Imports all classes in java.util package

3. Class Definition Statements

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 :

public class Car {

// Class members go here

We can create any number of classes in one program.

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

Variables : Also called fields or attributes, which hold data.

Constructors : Used to initialize objects.

Methods : Define behaviors or actions of the class.

etc...

3.1 Variables Declaration Statements (Optional) [Class Members]

Variables are used to store data and are declared within the class (as fields) or within
methods (local variables).

Syntax :

dataType variableName = value; // Field or local variable declaration


Example :

String model = "Tata Nexon" // Field

int year = 2020; // Field

3.2 Constructors Declaration Statements (Optional) [Class Members]

Constructor is a special method having same name as that of class name but should name
have any return type.

A constructor initializes objects of a class. If no constructor is provided, Java supplies a


default constructor.

Syntax :

ClassName() {

// Constructor body

Example :

public Car() {

System.out.println("Constructor called!");

3.3 Methods Declaration Statements [Class Members]

Methods are the set of codes which performs a particular task.

We can create any number of methods in one class.

Syntax :

accessModifier returnType methodName(parameters) {

// Method body

Example :

public void start() {

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 :

public static void main(String[] args) {

// Code to execute

Example :

public static void main(String[] args) {

System.out.println("Hello Deepak...!!");

Java Hello Program Deep Explanation

Simple Java Hello Program

In last tutorial, we have deeply explained the . Now, below is the simple Java Hello Program.

MainApp.java

public class MainApp

public static void main(String[] args)

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

1. public (Keyword - Access Modifier)

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 class can contain :-

Variables: Store data or attributes of the class.

Constructors: Initialize the object’s state.

Methods: Define the behavior or actions of the class.

3. MainApp (User-Defined Class Name)

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.

4. { (Class Opening Curly Brace)

Here "{" denotes the beginning of the class definition.

Every class body is enclosed in curly braces.

5. public (Keyword - Access Modifier)

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.

7. void (Keyword - Return Type)

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.

8. main (Pre-Defined Method)

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.

9. String[] (Parameter Type - Array of Strings)

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"

10. args (Parameter Name - Argunment Variable)

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 is used to hold the command-line arguments passed to the program.

11. { (Method Opening Curly Brace)

Here "{" denotes the beginning of the main method body.

12. System (Pre-Defined Class Name)

"System" is the built-in Java class from java.lang package.

It provides access to system-level functionality, such as input/output streams, properties,


and environment variables.

It contains:

in: Standard input stream (e.g., keyboard input).


out: Standard output stream (e.g., console output).

err: Standard error stream (e.g., error messages).

13. . (Member Access Operator)

"." 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:

in: Standard input stream (e.g., keyboard input).

out: Standard output stream (e.g., console output).

err: Standard error stream (e.g., error messages).

14. out (Pre-Defined Object)

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

15. println (Pre-Defined Method)

"println" is the pre-defined method of "PrintStream" class (referenced by System.out).

It prints the given text or data to the console and moves the cursor to a new line.

16. "Hello Deepak" (String Literal)

"Hello Deepak" is the sequence of characters enclosed in double quotes.

The text Hello Deepak is passed as an argument to the println method and will be displayed
in the console.

16. ; [Semicolon] (Statement Terminator)

";" marks the end of a statement in Java. Every executable statement must be terminated
with a semicolon.

17. } (Method Closing Curly Brace:)

Here "}" marks the end of the main method body.

18. } (Class Closing Curly Brace)

Here "}" marks the end of the class definition.


Deep Explanation of How Java Works Step by Step

Below diagram visually explains the steps involved when writing, compiling, and executing
a Java program using Notepad and CMD.

Below is detailed explanation:

Step 1: Writing the Java Program

We write our Java program in a plain text editor like Notepad.

The program is saved with a .java extension, e.g., MainApp.java.

MainApp.java

public class MainApp

public static void main(String[] args)

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

What happens in compilation phase:

The Java Compiler (javac) reads the .java file.

It checks the code for syntax errors.

If there are no errors, it compiles the code into bytecode, a platform-independent


intermediate representation.
The bytecode is saved in a .class file (e.g., MainApp.class).

Step 3: Bytecode (.class file)

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.

What happens during execution phase:

JVM (Java Virtual Machine):

The JVM reads the bytecode in the .class file.

It converts the bytecode into machine code that the operating system understands.

It executes the machine code line by line.

The main method is the entry point for execution.

Step 5: Output

If the program contains a print statement, such as:


System.out.println("Hello Deepak");

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

Purpose of Data Types :

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 Types & Variables :

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 :

int rollno = 101;

// "int" is "data type"

// "rollno" is "variable"

// "101" is "literal' or "data" (value assigned to the variable)

Diagram :

Types of Data Types

There are 2 types of Data Types in Java which are as below :-

Primitive Data Types

Non - Primitive Data Types

Below is the diagram representing the data types in java....

1. Primitive Data Types

Primitive data types are pre-defined data types.

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.

to read primitive data types more deeply.


2. Non-Primitive Data Types

Non-Primitive data types are user-defined or derived data types.

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.

to read non-primitive data types more deeply.

What are Data Types ?

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 :

int rollno = 101; // 'int' is a data type for integers

float marks = 91.4f; // 'float' is for decimal values

char grade = 'A'; // 'char' is for single characters

There are 2 types of data types in Java :-

Primitive Data Types

Non-Primitive Data Types

Primitive Data Types

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

a) Primitive Data Types are pre-defined data types

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.

For example : int rollno = 101;


In this case:

The compiler knows that int can only hold whole numbers (no decimals).

It allocates 4 bytes of memory to store this value directly.

Some Points to Note :

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.

Primitive Data Types are not objects but raw values.

b) Primitive Data Types are of 8 types

Java provides 8 pre-defined data types i.e.


boolean, char, byte, short, int, long, float and double.

Each type is suited for specific use cases:

boolean: Use for true/false values.

char: Use to store a single character (e.g., 'A').

byte: Use for small integers (-128 to 127).

short: Use for medium-sized integers (-32,768 to 32,767).

int: Use for whole numbers (default choice for integers).

long: Use for large integers beyond int range.

float: Use for small decimal numbers (less precision).

double: Use for large decimal numbers (high precision).

c) Primitive Data Types have fixed memory sizes

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.

char letter = 'A'; // Allocates 2 bytes for a Unicode character.

float price = 19.99f; // Allocates 4 bytes for a decimal value.

This fixed size ensures consistent behavior across different platforms, which is part of Java’s
"write once, run anywhere" philosophy.

Below is the memory size and range of each data type:

If we attempt to store a value outside the specified range, it results in a compilation or


runtime error.
For example:

byte smallNumber = 200; // Error: 200 exceeds the byte range of -128 to 127.

Non-Primitive Data Types

a) Non-Primitive Data Types are user-defined or derived data types

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.

For example : String name = "Deepak";


In this case:

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.

Some Points to Note :

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.

b) Non-Primitive Data Types include String, Arrays, classes, interfaces etc


Java does not have a fixed number of non-primitive data types like it does for primitive
types.

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.

Some common non-primitive data types categories in Java are as below :-

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.

Enums: Fixed sets of constants. Examples: enum Day { MONDAY, TUESDAY }.

c) Non-Primitive Data Types have variable memory sizes

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.

ArrayList numbers = new ArrayList<>();

numbers.add(10); // Memory adjusts 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.

String unused = new String("Garbage");

unused = null; // The memory for "Garbage" is now eligible for garbage collection

Variables in Java
Introduction

A variable is the name of memory location that can store data.

In simple words we can say, variables are the containers used to store the data values.

Real World Example :

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.

So we can say that every variable has its :-

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.

Value : The data assigned to the variable.

More Points about Varibales in Java :

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;

System.out.println("no : "+no); //output is no : 10

no = no + 20;

System.out.println("no : "+no); //output is no : 30


Types of Data Types

There are 3 types of variables in Java which are as below :-


1. Local Variable
2. Instance Variable
3. Static Variable

1. Local Variables

A variable defined within a block, method, or constructor is called a local variable.

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.

We have to initialize the local variables before using it.

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.

Program for Local, Instance & Static Variables

public class MainApp

{
int no = 100; //instance variable

static int sno = 200; //static variable

void m1()

int no1 = 10; //local variable

System.out.println("Result 1 : "+(no1 + no));

System.out.println("Result 2 : "+(no1 + no + sno));

//System.out.println("Result 3 : "+(no1 + no2)); //error as no2 is local variable which is


present in m2() method and thus cannot be used outside m2() method

void m2()

int no2 = 20; //local variable

System.out.println("Result 4 : "+(no2 + no));

System.out.println("Result 5 : "+(no2 + no + sno));

//System.out.println("Result 6 : "+(no2 + no1)); //error as no1 is local variable which is


present in m1() method and thus cannot be used outside m1() method

static void m3()

int no3 = 30; //local variable

//System.out.println("Result 7 : "+(no3 + no)); //error because no is instance variable


which cannot be used inside static method
System.out.println("Result 8 : "+(no3 + sno));

System.out.println("Result 9 : "+(no1 + no2 + no3)); //error because no1 and no2 are local
variables and cannot be used outside their method scope

public static void main(String[] args)

MainApp obj = new MainApp();

obj.m1();

obj.m2();

MainApp.m3(); //static method can be directly called by class name

Output:

Result 1 : 110

Result 2 : 310

Result 4 : 120

Result 5 : 320

Result 8 : 230

Literals in Java

Introduction

Literals are constants used in Java programs to represent fixed values.

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

There are many types of literals in Java which are as below :-


1. Integer Literal
2. Floating-Point Literal
3. Character Literal
4. String Literal
5. Boolean Literal
6. Null Literal

1. Integer Literals

Integer Literals represents the whole numbers and can be written in different number
systems.

Difference types of Integer Literals are :-

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;).

Rules for Integer Literals are:

By default, integer literals are of type int.

Use L or l to specify a long literal (e.g., long bigNum = 123456789L;).

Program for Integer Literal :

public class IntegerLiteralsExample

public static void main(String[] args)

// Decimal Literal (Base 10): Regular whole numbers

int decimal = 42;


System.out.println("Decimal Literal: " + decimal); // Output: 42

// Binary Literal (Base 2): Starts with 0b or 0B

int binary = 0b1010; // Binary for decimal 10

System.out.println("Binary Literal: " + binary); // Output: 10

// Octal Literal (Base 8): Starts with 0

int octal = 010; // Octal for decimal 8

System.out.println("Octal Literal: " + octal); // Output: 8

// Hexadecimal Literal (Base 16): Starts with 0x or 0X

int hexadecimal = 0x1F; // Hexadecimal for decimal 31

System.out.println("Hexadecimal Literal: " + hexadecimal); // Output: 31

// Long Literal: Specified with L or l at the end

long bigNum = 123456789L;

System.out.println("Long Literal: " + bigNum); // Output: 123456789

// Example of usage of all types together in calculations

int sum = decimal + binary + octal + hexadecimal;

System.out.println("Sum of all literals: " + sum); // Output: 91

Output:

Decimal Literal: 42

Binary Literal: 10
Octal Literal: 8

Hexadecimal Literal: 31

Long Literal: 123456789

Sum of all literals: 91

2. Floating-Point Literals

Floating-Point Literals represents the numbers with decimal points.

Difference types of Floating-Point Literals are :-

Float: These ends with F or f suffix (e.g., float pi = 3.14F;).

Double: These are the default type for decimal literals (e.g., double e = 2.718;).

Rules for Floating-Point Literals are:

Use scientific notation for very large or small numbers (e.g., double largeNum = 1.23e4;).

Program for Floating-Point Literal :

public class FloatingPointLiteralsExample

public static void main(String[] args)

// Float Literal: Ends with F or f

float pi = 3.14F; // The 'F' indicates it's a float literal

System.out.println("Float Literal (pi): " + pi); // Output: 3.14

// Double Literal: Default type for decimal numbers

double e = 2.718; // By default, this is considered a double

System.out.println("Double Literal (e): " + e); // Output: 2.718

// Scientific Notation: Large number in scientific format

double largeNum = 1.23e4; // Equivalent to 1.23 * 10^4 = 12300


System.out.println("Scientific Notation (largeNum): " + largeNum); // Output: 12300.0

// Another example of scientific notation: Very small number

double smallNum = 4.56e-3; // Equivalent to 4.56 * 10^-3 = 0.00456

System.out.println("Scientific Notation (smallNum): " + smallNum); // Output: 0.00456

// Demonstrating precision with double

double preciseNum = 3.14159265359; // Double can hold many decimal places

System.out.println("Double with precision (preciseNum): " + preciseNum); // Output:


3.14159265359

Output:

Float Literal (pi): 3.14

Double Literal (e): 2.718

Scientific Notation (largeNum): 12300.0

Scientific Notation (smallNum): 0.00456

Double with precision (preciseNum): 3.14159265359

3. Character Literals

Character Literals represent a single character enclosed in single quotes (').

Examples of Character Literals are :-

char letter = 'A';

char digit = '7';

char specialChar = '@';

Rules for Character Literals are:

Character Literals must represent a single Unicode character.

Escape sequences can be used for special characters:


\n (Newline), \t (Tab), \' (Single quote), \\ (Backslash), etc.

Program for Character Literal :

public class CharacterLiteralsExample

public static void main(String[] args)

// Character Literal: A single character enclosed in single quotes

char letter = 'A'; // Represents the character 'A'

System.out.println("Character Literal (letter): " + letter); // Output: A

// Character Literal: A digit as a character

char digit = '7'; // Represents the character '7'

System.out.println("Character Literal (digit): " + digit); // Output: 7

// Character Literal: A special character

char specialChar = '@'; // Represents the character '@'

System.out.println("Character Literal (specialChar): " + specialChar); // Output: @

// Using Escape Sequences for special characters

char newlineChar = '\n'; // Represents a newline

char tabChar = '\t'; // Represents a tab

char singleQuoteChar = '\''; // Represents a single quote

char backslashChar = '\\'; // Represents a backslash

// Output using escape sequences

System.out.println("Escape Sequence (newline):" + newlineChar + "This is after newline.");


System.out.println("Escape Sequence (tab):" + tabChar + "This is after tab.");

System.out.println("Escape Sequence (single quote): " + singleQuoteChar + "This is single


quote.");

System.out.println("Escape Sequence (backslash): " + backslashChar + "This is backslash.");

Output:

Character Literal (letter): A

Character Literal (digit): 7

Character Literal (specialChar): @

Escape Sequence (newline):

This is after newline.

Escape Sequence (tab): This is after tab.

Escape Sequence (single quote): 'This is single quote.

Escape Sequence (backslash): \This is backslash.

4. String Literals

String Literals represent a sequence of characters enclosed in double quotes (").

Examples of String Literals are :-

String greeting = "Hello, World!";

String empty = ""; (An empty string).

Rules for String Literals are:

Strings are immutable in Java. (explained in String chapter)

Can include escape sequences (e.g., "Line1\nLine2").

Program for String Literal :

public class StringLiteralsExample

public static void main(String[] args)


{

// String Literal: A sequence of characters enclosed in double quotes

String greeting = "Hello, World!"; // A simple string literal

System.out.println("String Literal (greeting): " + greeting); // Output: Hello, World!

// String Literal: An empty string

String empty = ""; // An empty string

System.out.println("String Literal (empty): '" + empty + "'"); // Output: ''

// String with Escape Sequences

String multiLineString = "Line1\nLine2"; // Using escape sequence \n for newline

System.out.println("String with Escape Sequences (multiLineString): " + multiLineString);

// Output:

// Line1

// Line2

String quotedString = "He said, \"Hello!\""; // Using escape sequence \" for double quote

System.out.println("String with Escape Sequences (quotedString): " + quotedString);

// Output: He said, "Hello!"

String tabbedString = "Item1\tItem2"; // Using escape sequence \t for tab

System.out.println("String with Escape Sequences (tabbedString): " + tabbedString);

// Output: Item1 Item2

Output:
String Literal (greeting): Hello, World!

String Literal (empty): ''

String with Escape Sequences (multiLineString): Line1

Line2

String with Escape Sequences (quotedString): He said, "Hello!"

String with Escape Sequences (tabbedString): Item1 Item2

5. Boolean Literals

Boolean Literals represent one of two values: true or false.

Examples of Boolean Literals are :-

boolean isJavaFun = true;

boolean isHot = false;

Rules for Boolean Literals are:

Boolean Literals are used for conditional expressions and control flow.

Program for Boolean Literal :

public class BooleanLiteralsExample

public static void main(String[] args)

// Boolean Literals: Represent either true or false

boolean isJavaFun = true; // The value of isJavaFun is true

boolean isHot = false; // The value of isHot is false

// Printing the Boolean literals

System.out.println("Is Java Fun? " + isJavaFun); // Output: true

System.out.println("Is it Hot? " + isHot); // Output: false


// Using Boolean literals in a conditional expression (if-else)

if (isJavaFun) {

System.out.println("Java is fun!"); // This will print as isJavaFun is true

} else {

System.out.println("Java is not fun!");

// Using Boolean literals for control flow (example with boolean flags)

if (!isHot) {

System.out.println("It is not hot today!"); // This will print as isHot is false

} else {

System.out.println("It is hot today!");

Output:

Is Java Fun? true

Is it Hot? false

Java is fun!

It is not hot today!

6. Null Literal

Null Literal represents the absence of a value for an object reference.

Examples of Null Literal is :-

String str = null;

Rules for Null Literals are:

null can only be assigned to reference types, not primitive data types.
Program for Null Literal :

public class NullLiteralExample

public static void main(String[] args)

// Null Literal: Represents the absence of a value for an object reference

String str = null; // Null literal assigned to a reference type

// Checking if the object reference is null

if (str == null)

System.out.println("The string is null, no value assigned.");

else

System.out.println("The string has a value: " + str);

Output:

The string is null, no value assigned.

Underscores in Numeric Literals (Java 7+)

We can use underscores in numeric literals to improve readability.

For example :-

int million = 1_000_000;


double pi = 3.141_592_653;

Rules to use Underscores in Numeric Literals :

Underscores cannot be used at the start or end of the literal, or next to a decimal point.

Program for Underscores in Numeric Literals :

public class NumericLiteralsWithUnderscore

public static void main(String[] args)

// Using underscores to improve readability in numeric literals

int million = 1_000_000; // Underscores to separate thousands

double pi = 3.141_592_653; // Underscores in a floating-point number

// Printing the values

System.out.println("Million: " + million); // Output: 1000000

System.out.println("Pi value: " + pi); // Output: 3.141592653

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

Arithmetic operators are explained as below :-

+ (Addition operator): Adds two operands.

(Subtraction operator): Subtracts the second operand from the first.

* (Multiplication operator): Multiplies two operands.


/ (Division operator): Divides the first operand by the second.

% (Modulus operator): Returns the remainder when the first operand is divided by the
second.

Program :

public class ArithmeticOperators

public static void main(String[] args)

int a = 10, b = 5;

double x = 10.5, y = 4.2;

// Addition

System.out.println("Addition (int): " + (a + b)); // Output: 15

System.out.println("Addition (double): " + (x + y)); // Output: 14.7

// Subtraction

System.out.println("Subtraction (int): " + (a - b)); // Output: 5

System.out.println("Subtraction (double): " + (x - y)); // Output: 6.3

// Multiplication

System.out.println("Multiplication (int): " + (a * b)); // Output: 50

System.out.println("Multiplication (double): " + (x * y)); // Output: 44.1

// Division

System.out.println("Division (int): " + (a / b)); // Output: 2 (integer division)

System.out.println("Division (double): " + (x / y)); // Output: 2.5


// Modulus

System.out.println("Modulus (int): " + (a % b)); // Output: 0

System.out.println("Modulus (double): " + (x % y)); // Output: 2.1

Output:

Addition (int): 15

Addition (double): 14.7

Subtraction (int): 5

Subtraction (double): 6.3

Multiplication (int): 50

Multiplication (double): 44.1

Division (int): 2

Division (double): 2.5

Modulus (int): 0

Modulus (double): 2.0999999999999996

Some Advance Important Points :-

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

Floating-Point Division: When at least one operand is a floating-point number (float or


double), division results in a floating-point value.

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 operators are used to perform an operation (like addition, subtraction,


multiplication, etc.) and assign the result to a variable in a single step.
Assignment operators are explained as below :-

= (Assignment Operator):

Purpose: Assigns the right-hand operand value to the left-hand operand (variable).

Example: a = b assigns the value of b to a.

+= (Addition Assignment Operator):

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.

= (Subtraction Assignment Operator):

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.

*= (Multiplication Assignment Operator):

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.

/= (Division Assignment Operator):

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.

%= (Modulus Assignment Operator):

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 :

public class AssignmentOperators

public static void main(String[] args)


{

// Initialize variables

int a = 10, b = 5;

double x = 10.5, y = 4.2;

// Simple Assignment (=)

a = b; // a is assigned the value of b (a = 5)

System.out.println("Simple Assignment: a = " + a); // Output: a = 5

// Addition Assignment (+=)

a += b; // a = a + b (5 + 5)

System.out.println("Addition Assignment: a = " + a); // Output: a = 10

// Subtraction Assignment (-=)

a -= b; // a = a - b (10 - 5)

System.out.println("Subtraction Assignment: a = " + a); // Output: a = 5

// Multiplication Assignment (*=)

a *= b; // a = a * b (5 * 5)

System.out.println("Multiplication Assignment: a = " + a); // Output: a = 25

// Division Assignment (/=)

a /= b; // a = a / b (25 / 5)

System.out.println("Division Assignment: a = " + a); // Output: a = 5

// Modulus Assignment (%=)


a %= b; // a = a % b (5 % 5)

System.out.println("Modulus Assignment: a = " + a); // Output: a = 0

// Using compound operators with double

x += y; // x = x + y (10.5 + 4.2)

System.out.println("Addition Assignment (double): x = " + x); // Output: x = 14.7

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

Addition Assignment (double): x = 14.7

Some Advance Important Points :-

Chained Assignment:

We can assign the same value to multiple variables in a single statement.

Example: a = b = c = 10; assigns 10 to a, b and c.

Implicit Casting with Compound Operators:

Compound operators (e.g., +=, *=) perform implicit type casting if needed.

Example: int a = 5; a += 2.5; results in a = 7 (2.5 is cast to an int).

String Concatenation:

The += operator concatenates strings instead of performing numeric addition.

Example: String s = "Java"; s += " Rocks"; results in "Java Rocks".


Final Variables:

Assignment operators cannot modify final variables.

Example: final int a = 10; a += 5; will cause a compilation error.

Overflow and Underflow:

For integer types, compound assignments can cause overflow or underflow.

Example: int a = Integer.MAX_VALUE; a += 1; wraps around to Integer.MIN_VALUE.

Precedence and Associativity:

Assignment operators have low precedence and are evaluated right-to-left.

Example: a = b = c = 10; evaluates as c = 10, then b = c, then a = b.

Side Effects:

Assignment operators modify the variable as part of the expression.

Example: int a = 5; int b = (a += 10) * 2; results in a = 15 and b = 30.

Not for Literals:

The left-hand operand of an assignment must be a variable, not a literal or constant.

Example: 5 += 3; is invalid.

Usage in Loops:

Compound assignment operators (+=, -=) are frequently used in loops to modify counters
efficiently.

Example: for (int i = 0; i < 10; i += 2) iterates by steps of 2.

Cannot Chain Compound Operators:

Compound assignments like += cannot be directly chained.

Example: a += b += c; is invalid.

Works with All Primitives:

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

Relational operators are explained as below :-

== (Equal to Operator):

Purpose: Checks if two values are equal.

Example:

int a = 5, b = 5;

System.out.println(a == b); // Output: true

!= (Not equal to operator):

Purpose: Checks if two values are not equal.

Example:

int a = 5, b = 10;

System.out.println(a != b); // Output: true

< (Less Than Operator):

Purpose: Checks if the left operand is less than the right operand.

Example:

int a = 5, b = 10;

System.out.println(a < b); // Output: true

> (Greater Than Operator):

Purpose: Checks if the left operand is greater than the right operand.

Example:

int a = 10, b = 5;

System.out.println(a > b); // Output: true


<= (Less than or equal to operator):

Purpose: Checks if the left operand is less than or equal to the right operand.

Example:

int a = 5, b = 10;

System.out.println(a <= b); // Output: true

>= (Greater than or equal to operator):

Purpose: Checks if the left operand is greater than or equal to the right operand.

Example:

int a = 10, b = 10;

System.out.println(a >= b); // Output: true

Program :

public class RelationalOperators

public static void main(String[] args)

// Initialize variables

int a = 10, b = 20;

double x = 15.5, y = 15.5;

// Equal To (==)

System.out.println("Equal To (a == b): " + (a == b)); // Output: false

System.out.println("Equal To (x == y): " + (x == y)); // Output: true

// Not Equal To (!=)

System.out.println("Not Equal To (a != b): " + (a != b)); // Output: true

System.out.println("Not Equal To (x != y): " + (x != y)); // Output: false


// Less Than (<)

System.out.println("Less Than (a < b): " + (a < b)); // Output: true

System.out.println("Less Than (x < y): " + (x < y)); // Output: false

// Greater Than (>)

System.out.println("Greater Than (a > b): " + (a > b)); // Output: false

System.out.println("Greater Than (x > y): " + (x > y)); // Output: false

// Less Than or 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

// Greater Than or Equal To (>=)

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:

Equal To (a == b): false

Equal To (x == y): true

Not Equal To (a != b): true

Not Equal To (x != y): false

Less Than (a < b): true

Less Than (x < y): false

Greater Than (a > b): false


Greater Than (x > y): false

Less Than or Equal To (a <= b): true

Less Than or Equal To (x <= y): true

Greater Than or Equal To (a >= b): false

Greater Than or Equal To (x >= y): true

Some Advance Important Points :-

Comparison of Primitives:

Relational operators can be used with all primitive data types except boolean.

Example: int a = 10, b = 20; boolean result = a < b; // true.

Boolean Result:

Relational operators always return a boolean value (true or false).

Example: 5 > 3 evaluates to true.

Floating-Point Precision Issues:

Comparing float or double values may lead to unexpected results due to precision issues.

Example: (0.1 + 0.2) == 0.3; // false due to floating-point representation errors.

String Comparison:

Relational operators (<, >, etc.) cannot be used with String objects; use compareTo for
lexicographical comparison.

Example: "abc".compareTo("def") < 0 // true.

Equality of Objects:

== checks reference equality (if two references point to the same object), not content
equality.

Use .equals() to compare the content of objects.

Example:

String s1 = "Java";

String s2 = "Java";

System.out.println(s1 == s2); // true (same reference in the string pool)


System.out.println(s1.equals(s2)); // true (content is the same)

Not Applicable to Arrays:

Relational operators cannot directly compare arrays. Use Arrays.equals() or iterate through
elements.

Example:

int[] arr1 = {1, 2, 3};

int[] arr2 = {1, 2, 3};

System.out.println(arr1 == arr2); // false (different references)

Operator Precedence:

Relational operators have higher precedence than logical operators (&&, ||) but lower
precedence than arithmetic operators (+, *).

Example: 3 + 5 > 7 && 2 < 4; // true.

Chaining Not Allowed:

You cannot directly chain relational operators like a < b < c.

Example: 10 < 20 < 30; // Compilation error.

Works with Mixed Types:

Relational operators can compare values of different numeric types (int, float, etc.). Implicit
casting applies to the smaller type.

Example: int a = 5; double b = 5.0; System.out.println(a == b); // true.

Cannot Use with null:

Relational operators other than == or != cannot be used with null.

Example:

String s = null;

System.out.println(s == null); // true

System.out.println(s < "Java"); // Compilation error

Comparison of Characters:

Relational operators can compare char values based on their Unicode values.
Example: 'a' < 'b' // true (Unicode 97 < 98).

Usage in Control Structures:

Frequently used in if, while, for and switch conditions to determine the flow of execution.

Example: if (a >= b) { /* logic */ }.

Equality with NaN:

For double and float, NaN (Not a Number) is not equal to any value, including itself.

Example:

double value = Double.NaN;

System.out.println(value == value); // false

Efficiency:

Relational operators are highly optimized in Java for performance.

Interplay with Auto-boxing:

Relational operators work on unboxed values when comparing wrapper classes


(Integer, Double, etc.).

Example:

Integer a = 100, b = 100;

System.out.println(a == b); // true (cached values)

Behavior with Booleans:

Only == and != are valid for boolean values; other relational operators cannot be applied.

Example:

boolean flag = true;

System.out.println(flag == true); // true

System.out.println(flag > true); // Compilation error

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

&& (Logical AND Operator):

Purpose: Returns true if both operands (expressions) are true, otherwise returns false.

Example:

boolean a = true, b = false;

System.out.println(a && b); // Output: false

|| (Logical OR Operator):

Purpose: Returns true if at least one of the operands (expressions) is true, otherwise
returns false.

Example:

boolean a = true, b = false;

System.out.println(a || b); // Output: true

! (Logical NOT Operator):

Purpose: Inverts the value of the boolean expression. If the expression is true, it becomes
false, and vice versa.

Example:

boolean a = true;

System.out.println(!a); // Output: false

Program :

public class LogicalOperators

public static void main(String[] args)

// Initialize boolean variables

boolean a = true, b = false, c = true;

// Logical AND (&&)


System.out.println("Logical AND (a && b): " + (a && b)); // Output: false

System.out.println("Logical AND (a && c): " + (a && c)); // Output: true

// Logical OR (||)

System.out.println("Logical OR (a || b): " + (a || b)); // Output: true

System.out.println("Logical OR (b || c): " + (b || c)); // Output: true

// Logical NOT (!)

System.out.println("Logical NOT (!a): " + !a); // Output: false

System.out.println("Logical NOT (!b): " + !b); // Output: true

// Using logical operators in a complex condition

if ((a && b) || (c && !b))

System.out.println("Condition is true");

else

System.out.println("Condition is false"); // Output: Condition is true

// Another example with short-circuit behavior

if (a && b && (c || !b))

System.out.println("All conditions met");

}
else

System.out.println("Not all conditions met"); // Output: Not all conditions met

Output:

Logical AND (a && b): false

Logical AND (a && c): true

Logical OR (a || b): true

Logical OR (b || c): true

Logical NOT (!a): false

Logical NOT (!b): true

Condition is true

Not all conditions met

Some Advance Important Points :-

Usage with Boolean Data Type:

Logical operators (&&, ||, !) are primarily used with boolean values (true or false).

Example: boolean a = true, b = false; boolean result = a && b; // false.

Short-circuit Behavior:

Logical && (AND) and || (OR) operators exhibit 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.

Combining Logical Operators:


Logical operators can be combined to form complex conditions, making them useful for
decision-making and flow control.

Example: if ((a && b) || (!a && c)) { // complex condition }.

Precedence of Logical Operators:

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.

Example: boolean result = a && (b || c);.

Can Be Used with Conditions:

Logical operators can combine multiple conditions to evaluate complex expressions.

Example: if (x > 10 && y < 20) { // execute code }.

Result is Always Boolean:

Logical operators always return a boolean result (true or false).

Example: boolean result = a || b; // result is boolean.

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.

Works Only with Boolean Expressions:

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.

Avoiding Boolean Confusion:

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.

NOT on Non-Boolean Data Types:


The ! (logical NOT) operator is only applicable to boolean values. Using ! on non-boolean
types will result in a compile-time error.

Example: int a = 5; // !a will cause a compilation error.

Use in Conditional Statements:

Logical operators are commonly used in if, while, and for conditions to evaluate multiple
expressions and determine the flow of control.

Example: if (a > 10 && b < 20) { // condition met }.

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

&& (Logical AND Operator):

Purpose: Returns true if both operands (expressions) are true, otherwise returns false.

Example:

boolean a = true, b = false;

System.out.println(a && b); // Output: false

|| (Logical OR Operator):

Purpose: Returns true if at least one of the operands (expressions) is true, otherwise
returns false.

Example:

boolean a = true, b = false;

System.out.println(a || b); // Output: true

! (Logical NOT Operator):

Purpose: Inverts the value of the boolean expression. If the expression is true, it becomes
false, and vice versa.
Example:

boolean a = true;

System.out.println(!a); // Output: false

Program :

public class LogicalOperators

public static void main(String[] args)

// Initialize boolean variables

boolean a = true, b = false, c = true;

// Logical AND (&&)

System.out.println("Logical AND (a && b): " + (a && b)); // Output: false

System.out.println("Logical AND (a && c): " + (a && c)); // Output: true

// Logical OR (||)

System.out.println("Logical OR (a || b): " + (a || b)); // Output: true

System.out.println("Logical OR (b || c): " + (b || c)); // Output: true

// Logical NOT (!)

System.out.println("Logical NOT (!a): " + !a); // Output: false

System.out.println("Logical NOT (!b): " + !b); // Output: true

// Using logical operators in a complex condition

if ((a && b) || (c && !b))

{
System.out.println("Condition is true");

else

System.out.println("Condition is false"); // Output: Condition is true

// Another example with short-circuit behavior

if (a && b && (c || !b))

System.out.println("All conditions met");

else

System.out.println("Not all conditions met"); // Output: Not all conditions met

Output:

Logical AND (a && b): false

Logical AND (a && c): true

Logical OR (a || b): true

Logical OR (b || c): true

Logical NOT (!a): false

Logical NOT (!b): true

Condition is true
Not all conditions met

Some Advance Important Points :-

Usage with Boolean Data Type:

Logical operators (&&, ||, !) are primarily used with boolean values (true or false).

Example: boolean a = true, b = false; boolean result = a && b; // false.

Short-circuit Behavior:

Logical && (AND) and || (OR) operators exhibit 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.

Combining Logical Operators:

Logical operators can be combined to form complex conditions, making them useful for
decision-making and flow control.

Example: if ((a && b) || (!a && c)) { // complex condition }.

Precedence of Logical Operators:

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.

Example: boolean result = a && (b || c);.

Can Be Used with Conditions:

Logical operators can combine multiple conditions to evaluate complex expressions.

Example: if (x > 10 && y < 20) { // execute code }.

Result is Always Boolean:

Logical operators always return a boolean result (true or false).

Example: boolean result = a || b; // result is boolean.


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.

Works Only with Boolean Expressions:

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.

Avoiding Boolean Confusion:

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.

NOT on Non-Boolean Data Types:

The ! (logical NOT) operator is only applicable to boolean values. Using ! on non-boolean
types will result in a compile-time error.

Example: int a = 5; // !a will cause a compilation error.

Use in Conditional Statements:

Logical operators are commonly used in if, while, and for conditions to evaluate multiple
expressions and determine the flow of control.

Example: if (a > 10 && b < 20) { // condition met }.

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

&& (Logical AND Operator):

Purpose: Returns true if both operands (expressions) are true, otherwise returns false.

Example:

boolean a = true, b = false;


System.out.println(a && b); // Output: false

|| (Logical OR Operator):

Purpose: Returns true if at least one of the operands (expressions) is true, otherwise
returns false.

Example:

boolean a = true, b = false;

System.out.println(a || b); // Output: true

! (Logical NOT Operator):

Purpose: Inverts the value of the boolean expression. If the expression is true, it becomes
false, and vice versa.

Example:

boolean a = true;

System.out.println(!a); // Output: false

Program :

public class LogicalOperators

public static void main(String[] args)

// Initialize boolean variables

boolean a = true, b = false, c = true;

// Logical AND (&&)

System.out.println("Logical AND (a && b): " + (a && b)); // Output: false

System.out.println("Logical AND (a && c): " + (a && c)); // Output: true

// Logical OR (||)

System.out.println("Logical OR (a || b): " + (a || b)); // Output: true


System.out.println("Logical OR (b || c): " + (b || c)); // Output: true

// Logical NOT (!)

System.out.println("Logical NOT (!a): " + !a); // Output: false

System.out.println("Logical NOT (!b): " + !b); // Output: true

// Using logical operators in a complex condition

if ((a && b) || (c && !b))

System.out.println("Condition is true");

else

System.out.println("Condition is false"); // Output: Condition is true

// Another example with short-circuit behavior

if (a && b && (c || !b))

System.out.println("All conditions met");

else

System.out.println("Not all conditions met"); // Output: Not all conditions met

}
}

Output:

Logical AND (a && b): false

Logical AND (a && c): true

Logical OR (a || b): true

Logical OR (b || c): true

Logical NOT (!a): false

Logical NOT (!b): true

Condition is true

Not all conditions met

Some Advance Important Points :-

Usage with Boolean Data Type:

Logical operators (&&, ||, !) are primarily used with boolean values (true or false).

Example: boolean a = true, b = false; boolean result = a && b; // false.

Short-circuit Behavior:

Logical && (AND) and || (OR) operators exhibit 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.

Combining Logical Operators:

Logical operators can be combined to form complex conditions, making them useful for
decision-making and flow control.

Example: if ((a && b) || (!a && c)) { // complex condition }.

Precedence of Logical Operators:

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.

Example: boolean result = a && (b || c);.

Can Be Used with Conditions:

Logical operators can combine multiple conditions to evaluate complex expressions.

Example: if (x > 10 && y < 20) { // execute code }.

Result is Always Boolean:

Logical operators always return a boolean result (true or false).

Example: boolean result = a || b; // result is boolean.

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.

Works Only with Boolean Expressions:

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.

Avoiding Boolean Confusion:

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.

NOT on Non-Boolean Data Types:

The ! (logical NOT) operator is only applicable to boolean values. Using ! on non-boolean
types will result in a compile-time error.

Example: int a = 5; // !a will cause a compilation error.

Use in Conditional Statements:

Logical operators are commonly used in if, while, and for conditions to evaluate multiple
expressions and determine the flow of control.

Example: if (a > 10 && b < 20) { // condition met }.


Ternary Operator in Java

Introduction

The ternary operator in Java is a shortcut for the if-else statement.

It evaluates a boolean expression and returns one of two values based on the result of the
evaluation.

The syntax of ternary operator is as below:


condition ? value1 : value2;

condition: The boolean expression that is evaluated.

value1: The value returned if the condition evaluates to true.

value2: The value returned if the condition evaluates to false.

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:

public class TernaryOperator

public static void main(String[] args)

int a = 10, b = 20;

// Using ternary operator to find the maximum of two numbers

int max = (a > b) ? a : b;

System.out.println("The maximum value is: " + max); // Output: The maximum value is: 20

// Using ternary operator to check if a number is even or odd

String result = (a % 2 == 0) ? "Even" : "Odd";


System.out.println("The number is: " + result); // Output: The number is: Even

// Nested ternary operator

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:

The maximum value is: 20

The number is: Even

The largest value is: 20

Program Explanation:

Finding Maximum Value:

int max = (a > b) ? a : b;

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:

String result = (a % 2 == 0) ? "Even" : "Odd";

This checks if a is divisible by 2 (i.e., whether it is even). Since a = 10 is even, the result is
"Even".

Nested Ternary Operator:

int largest = (a > b) ? ((a > 15) ? a : 15) : ((b > 15) ? b : 15);

This is an example of a nested ternary operator. First, it checks if a is greater than b. If a is


greater, it further checks if a is greater than 15; if so, it returns a, otherwise it returns 15. If
b is greater than a, it checks if b is greater than 15; if so, it returns b, otherwise it returns 15.

When to Use Ternary Operator :-

Assignments: For assigning values based on conditions.

Example: int result = (score > 50) ? 1 : 0;


Return Statements: For returning a value based on a condition.

Example: return (age >= 18) ? "Adult" : "Minor";

Simple Conditional Logic: For simple checks, the ternary operator provides a cleaner, more
compact alternative to if-else statements.

When Not to Use Ternary Operator :-

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

Some Advance Important Points :-

Concise Syntax:

The ternary operator is used to perform conditional logic in a single line, making the code
more compact.

Example: int max = (a > b) ? a : b;.

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.

Nested Ternary Operator:

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.

This is similar to the && and || operators.


Unary Operators in Java

Introduction

Unary operators in Java are used to perform operations on a single operand.

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 (!).

Incrementing/Decrementing: Done using ++ (increment) or -- (decrement).

Logical Negation: Achieved using !, which inverts a boolean value.

etc...

Unary operators are explained as below :-

+ (Unary plus operator):

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

(Unary Minus Operator):

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

Purpose: Increases the value of a variable by 1. Can be used in two forms:

Pre-Increment (++a): Increments the value first, then uses it.

Post-Increment (a++): Uses the value first, then increments it.

Example:
int a = 5;

System.out.println(++a); // Output: 6 (Pre-increment)

System.out.println(a++); // Output: 6 (Post-increment)

System.out.println(a); // Output: 7

- (Decrement Operator):

Purpose: Decreases the value of a variable by 1. Can also be used in two forms:

Pre-Decrement (--a): Decrements the value first, then uses it.

Post-Decrement (a--): Uses the value first, then decrements it.

Example:

int a = 5;

System.out.println(--a); // Output: 4 (Pre-decrement)

System.out.println(a--); // Output: 4 (Post-decrement)

System.out.println(a); // Output: 3

! (Logical NOT Operator):

Purpose: Inverts the value of a boolean expression. If the expression is true, it becomes
false, and vice versa.

Example:

boolean isTrue = true;

System.out.println(!isTrue); // Output: false

Program:

public class UnaryOperators

public static void main(String[] args)

// Initialize variables

int a = 5, b = -10;

boolean isTrue = true;


// Unary Plus (+)

System.out.println("Unary Plus (+a): " + (+a)); // Output: 5

// Unary Minus (-)

System.out.println("Unary Minus (-b): " + (-b)); // Output: 10

// Pre-Increment (++a)

System.out.println("Pre-Increment (++a): " + (++a)); // Output: 6

// Post-Increment (a++)

System.out.println("Post-Increment (a++): " + (a++)); // Output: 6

System.out.println("Value after Post-Increment: " + a); // Output: 7

// Pre-Decrement (--a)

System.out.println("Pre-Decrement (--a): " + (--a)); // Output: 6

// Post-Decrement (a--)

System.out.println("Post-Decrement (a--): " + (a--)); // Output: 6

System.out.println("Value after Post-Decrement: " + a); // Output: 5

// Logical NOT (!)

System.out.println("Logical NOT (!isTrue): " + (!isTrue)); // Output: false

// Bitwise Complement (~)

System.out.println("Bitwise Complement (~a): " + (~a)); // Output: -6


}

Output:

Unary Plus (+a): 5

Unary Minus (-b): 10

Pre-Increment (++a): 6

Post-Increment (a++): 6

Value after Post-Increment: 7

Pre-Decrement (--a): 6

Post-Decrement (a--): 6

Value after Post-Decrement: 5

Logical NOT (!isTrue): false

Bitwise Complement (~a): -6

Some Advance Important Points :-

Unary Operators with Literals:

Unary operators can be directly applied to literals or variables.

Example: System.out.println(-5); outputs -5.

Unary Plus with Non-Numeric Types:

The unary plus (+) operator is valid only for numeric types.

Example: +true; will result in a compilation error because true is a boolean.

Increment/Decrement Operators in Expressions:

When used in complex expressions, the result depends on whether the operator is pre or
post.

Example:

int a = 5;

int result = a++ + 10; // Post-increment: result = 15, a = 6

Increment/Decrement on Non-Variables:
Increment (++) and decrement (--) operators must be applied to variables, not constants or
expressions.

Example: 5++; or (a + b)++; is invalid.

Logical NOT (!) with Non-Boolean Types:

The ! operator only works with boolean expressions.

Example: !5; results in a compilation error, but !true; is valid.

Unary Operators and Precedence:

Unary operators have higher precedence than binary operators but lower than parentheses.

Example:

int a = 5, b = 10;

System.out.println(-a + b); // Output: 5 (evaluates as (-a) + b)

Chained Increment/Decrement:

Multiple increments or decrements can be chained, but their evaluation follows left-to-right
associativity.

Example:

int a = 5;

System.out.println(++a + ++a); // Output: 13 (evaluates as (++6) + (++7))

Unary Operators with Final Variables:

Increment and decrement operators cannot modify final variables.

Example:

final int a = 5;

a++; // Compilation error

Unary Operators with Char:

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

Efficiency in Loop Counters:

Pre-increment (++i) is slightly more efficient than post-increment (i++) in loops due to
avoiding a temporary variable.

Example:

for (int i = 0; i < 10; ++i)

System.out.println(i);

Overflow/Underflow with Increment/Decrement:

Incrementing or decrementing numeric types can lead to overflow or underflow.

Example:

int a = Integer.MAX_VALUE;

System.out.println(++a); // Output: Integer.MIN_VALUE (overflow)

Unary Operators with Compound Expressions:

Unary operators can modify variables directly used in complex expressions.

Example:

int a = 5;

int b = (++a * 2) + (--a); // a becomes 6, then 5 again; result = 17

Unary Operators on Boolean Literals:

The ! operator can invert boolean literals directly.

Example: System.out.println(!true); // Output: false

Usage with Arrays:

Increment and decrement operators can modify array elements directly.

Example:

int[] arr = {1, 2, 3};

arr[0]++;
System.out.println(arr[0]); // Output: 2

Chained Logical NOT:

Multiple ! operators can be chained, effectively toggling the boolean value multiple times.

Example:

boolean flag = true;

System.out.println(!!!flag); // Output: false

Bitwise Operators in Java

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:

Low-level programming: Directly manipulating bits for hardware interaction.

Flags: Managing multiple boolean conditions compactly using a single integer.

Efficient calculations: Performing tasks like checking even/odd numbers or swapping


values without additional memory.

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:

Masks: Using bit masks to extract, modify, or toggle specific bits.


Encryption: XOR (^) is often used in simple encryption schemes.

Shift Operations: Combine with shift operators (<<, >>, >>>) for tasks like scaling numbers
or accessing specific bits.

Bitwise operators are explained as below :-

& (Bitwise AND Operator):

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:

int a = 5; // Binary: 0101

int b = 3; // Binary: 0011

System.out.println(a & b); // Output: 1 (Binary: 0001)

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

int a = 5; // Binary: 0101

int b = 3; // Binary: 0011

System.out.println(a | b); // Output: 7 (Binary: 0111)

^ (Bitwise XOR Operator):

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:

int a = 5; // Binary: 0101

int b = 3; // Binary: 0011

System.out.println(a ^ b); // Output: 6 (Binary: 0110)

~ (Bitwise NOT Operator)

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:

int a = 5; // Binary: 0101

System.out.println(~a); // Output: -6 (Binary: 1010 in two's complement form)

Program:

public class BitwiseOperators

public static void main(String[] args)

// Initialize variables

int a = 5; // Binary: 0101

int b = 3; // Binary: 0011

// Bitwise AND (&)

System.out.println("Bitwise AND (a & b): " + (a & b)); // Output: 1 (Binary: 0001)

// Bitwise OR (|)

System.out.println("Bitwise OR (a | b): " + (a | b)); // Output: 7 (Binary: 0111)

// Bitwise XOR (^)

System.out.println("Bitwise XOR (a ^ b): " + (a ^ b)); // Output: 6 (Binary: 0110)

// Bitwise Complement (~)

System.out.println("Bitwise Complement (~a): " + (~a)); // Output: -6 (Binary: 1010 in


two's complement)

// Demonstrating with larger numbers

int x = 12; // Binary: 1100


int y = 10; // Binary: 1010

System.out.println("\nWith larger numbers:");

System.out.println("Bitwise AND (x & y): " + (x & y)); // Output: 8 (Binary: 1000)

System.out.println("Bitwise OR (x | y): " + (x | y)); // Output: 14 (Binary: 1110)

System.out.println("Bitwise XOR (x ^ y): " + (x ^ y)); // Output: 6 (Binary: 0110)

System.out.println("Bitwise Complement (~x): " + (~x)); // Output: -13 (Binary: 0011 in


two's complement)

Output:

Bitwise AND (a & b): 1

Bitwise OR (a | b): 7

Bitwise XOR (a ^ b): 6

Bitwise Complement (~a): -6

With larger numbers:

Bitwise AND (x & y): 8

Bitwise OR (x | y): 14

Bitwise XOR (x ^ y): 6

Bitwise Complement (~x): -13

Some Advance Important Points :-

Bitwise Operators with Literals:

Bitwise operators can be directly applied to literals or variables.

Example:

System.out.println(5 & 3); // Output: 1

System.out.println(8 | 2); // Output: 10


Supported Data Types:

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.

Bitwise NOT with Non-Integer Types:

The ~ operator is valid only for integer types.

Example: System.out.println(~5); // Output: -6

Using it on non-integer types like boolean or String will result in a compilation error.

Precedence of Bitwise Operators:

Bitwise operators have lower precedence than arithmetic operators but higher precedence
than comparison and logical operators.

Example: int result = 5 + 3 & 2; // Evaluates as (5 + 3) & 2 = 8 & 2 = 0

Evaluation in Complex Expressions:

In complex expressions, bitwise operators operate on the binary representation of their


operands.

Example: int result = (5 | 3) & 2; // Binary: (0101 | 0011) & 0010 = 0111 & 0010 = 0010 = 2

Impact of Data Type Size:

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.

Sign Extension with ~:

The ~ operator flips all bits, including the sign bit in two's complement representation.

This can produce unexpected results for signed integers.

Example:

int a = 5; // Binary: 00000000 00000000 00000000 00000101

System.out.println(~a); // Binary: 11111111 11111111 11111111 11111010 = -6

Mixing Data Types:


When using bitwise operators with mixed data types, operands are promoted
to int (or long if one operand is long) before the operation is performed.

Example:

byte a = 5, b = 3;

System.out.println(a & b); // Implicitly promoted to int during operation

Usage with Boolean Logic:

Bitwise operators (&, |, ^) are not interchangeable with logical operators (&&, ||).

Using bitwise operators with boolean values performs bitwise evaluation.

Example: System.out.println(true & false); // Output: false

Shift Operators in Java

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.

Efficient calculations: Scale numbers by powers of two, faster than multiplication/division.

Optimizing performance: Faster than arithmetic/logical operations in performance-critical


tasks.

Data encoding/decoding: Important in bit-packing and handling bits in data.

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.

Flag manipulation: Combined with bitwise operators for flag management.

Memory optimization: Efficiently uses memory, especially with bitmasks.

Efficient arithmetic operations: Fast for low-level calculations and cryptography.

Shift operators are explained as below :-

<< (Left shift operator):

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;

System.out.println(a << 1); // Output: 10 (binary 101 << 1 becomes 1010)

>> (Right shift operator):

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;

System.out.println(a >> 2); // Output: 5 (binary 10100 >> 2 becomes 101)

>>> (Unsigned right shift operator):

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:

public class ShiftOperators

public static void main(String[] args)

// Initialize variables

int a = 5; // Binary: 0101

int b = -10; // Binary: 11111111111111111111111111110110 (in 32-bit two's


complement)

// Left shift (<<)

System.out.println("Left Shift (a << 1): " + (a << 1)); // Output: 10 (Binary: 1010)

// Right shift (>>)

System.out.println("Right Shift (a >> 1): " + (a >> 1)); // Output: 2 (Binary: 0010)

// Unsigned right shift (>>>)

System.out.println("Unsigned Right Shift (a >>> 1): " + (a >>> 1)); // Output: 2 (Binary:
0010)

// Left shift with negative number

System.out.println("Left Shift (b << 1): " + (b << 1)); // Output: -20 (Binary:
11111111111111111111111111101100)

// Right shift with negative number


System.out.println("Right Shift (b >> 1): " + (b >> 1)); // Output: -5 (Binary:
11111111111111111111111111111011)

// Unsigned right shift with negative number

System.out.println("Unsigned Right Shift (b >>> 1): " + (b >>> 1)); // Output: 2147483643
(Binary: 01111111111111111111111111111011)

Output:

Left Shift (a << 1): 10

Right Shift (a >> 1): 2

Unsigned Right Shift (a >>> 1): 2

Left Shift (b << 1): -20

Right Shift (b >> 1): -5

Unsigned Right Shift (b >>> 1): 2147483643

Some Advance Important Points :-

Shift Operators with Literals:

Shift operators can be directly applied to literals or variables.

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)

Supported Data Types:

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

Left Shift (<<) for Multiplication:


The left shift operator (<<) is used for efficient multiplication by powers of two.

Example :

int x = 3;

System.out.println(x << 2); // Output: 12 (Equivalent to 3 * 2^2)

This is computationally faster than using multiplication (x * 4).

Right Shift (>>) for Division:

The right shift operator (>>) is used for efficient division by powers of two.

Example :

int x = 16;

System.out.println(x >> 2); // Output: 4 (Equivalent to 16 / 2^2)

This is faster than using division (x / 4).

Unsigned Right Shift (>>>) and Negative Numbers:

The unsigned right shift operator (>>>) behaves differently for negative numbers by filling
with zeros instead of extending the sign bit.

Example :

int x = -8;

System.out.println(x >>> 1); // Output: 2147483640 (In binary:


11111111111111111111111111111000 >> 1 results in
01111111111111111111111111111100)

Shift Operators with Negative Numbers:

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;

System.out.println(x << 1); // Output: -10 (Binary:


11111111111111111111111111111011 << 1 results in
11111111111111111111111111110110)
Zero-Fill Right Shift (>>>) with Negative Numbers:

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;

System.out.println(x >>> 1); // Output: 2147483643 (Binary:


11111111111111111111111111111100 >>> 1 results in
01111111111111111111111111111110)

Shifting on Larger Numbers (long):

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;

System.out.println(x << 3); // Output: 800 (Equivalent to 100 * 2^3)

Shift Operations with Negative Powers:

Negative values in the right shift operator (>> and >>>) will throw a compile-time error.

Example:

int x = 8;

System.out.println(x >> -2); // Compile-time error: shift count must be non-negative

Overflow and Underflow in Shift Operations:

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;

System.out.println(x << 1); // Output: -2 (Overflow: 2147483647 << 1 results in a negative


value)
Instanceof Operator in Java

Introduction

The instanceof operator is used to check if an object is an instance of a specific class or


implements a given interface.

It returns a boolean value: true if the object is an instance of the specified class or interface,
and false otherwise.

It is commonly used for type checking in Java.

Syntax:
object instanceof ClassName

object: The reference variable pointing to the object being tested.

ClassName: The class or interface that you want to check the type of the object against.

Program:

class Animal

// some methods

class Dog extends Animal

// some methods

public class InstanceOfExample

public static void main(String[] args)

{
Animal animal = new Dog(); // Animal reference, but Dog object

// Using instanceof to check the type

if (animal instanceof Dog)

System.out.println("The animal is a Dog");

else

System.out.println("The animal is not a Dog");

Output:

The animal is a Dog

Some Advance Important Points :-

Usage of instanceof Operator:

Type Checking: It checks if an object is an instance of a particular class or interface.


For example :-

String str = "Hello";

System.out.println(str instanceof String); // Output: true

Interface Type Checking: Checks if an object implements a particular interface.


For example :-

List<String> list = new ArrayList<>();

System.out.println(list instanceof List); // Output: true

Null Check:

The instanceof operator will always return false when the object being checked is null.
String str = null;

System.out.println(str instanceof String); // Output: false

Inheritance with instanceof:

Inheritance Hierarchy: The operator works well with inheritance, checking if an object is an
instance of a superclass or subclass.

class Animal {}

class Dog extends Animal {}

Animal a = new Dog();

System.out.println(a instanceof Dog); // Output: true

System.out.println(a instanceof Animal); // Output: true

Use in Interfaces:

The instanceof operator also works with interfaces. It checks if an object implements a
specific interface.

interface Playable {}

class Football implements Playable {}

Playable game = new Football();

System.out.println(game instanceof Playable); // Output: true

Performance:

The instanceof operator is generally fast as it is a runtime check.

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.

instanceof with switch (Java 16+):

Starting from Java 16, instanceof can be used in a switch statement with pattern matching.

Object obj = new Dog();

switch (obj) {
case Dog d -> System.out.println("It's a dog!");

case Cat c -> System.out.println("It's a cat!");

default -> System.out.println("Unknown animal");

instanceof with Type Casting:

The instanceof operator is often used in conjunction with casting to safely cast objects.

Object obj = "Hello";

if (obj instanceof String) {

String str = (String) obj; // Safe cast

System.out.println(str.length()); // Output: 5

instanceof with Generics:

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.

List list = new ArrayList<>();

if (list instanceof ArrayList) {

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.

Below is the list of all reserved words 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.

Characteristics of 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.

Enhance Readability: Keywords make the code easier to understand by providing a


common vocabulary for developers.

Fixed Set: Java has a fixed list of keywords, and new ones are rarely added across versions

Identifiers in Java

Introduction

Boy : How can i identify you ?


Girl : My name is "Priya", you can identify by my name.

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 :

String name = "Deepak"; // here name is identifier

int rollno = 101; // here rollno is identifier

class Test {-} // here Test is identifier


Rules for Identifiers:

Spaces cannot be used in an identifier.

Identifiers must not contain any whitespace.

Valid Examples:

int myVariable;

String userName;

Invalid Examples:

int my Variable; // Error: Spaces are not allowed

String user Name; // Error: Spaces are not allowed

Only two symbols (_ and $) can be used in an identifier.

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:

int user#name; // Error: '#' is not allowed

double total@; // Error: '@' is not allowed

Integer values cannot be used at the first position.

Identifiers cannot begin with a digit (0-9) but may include digits after the first character.

Valid Examples:

int variable1;

double _123value;

Invalid Examples:

int 1variable; // Error: Cannot start with a digit

double 3value; // Error: Cannot start with a digit


Reserved words cannot be used as an identifier.

Reserved keywords in Java (like class, public, if, etc.) cannot be used as identifiers.

Valid Examples:

int myClass;

String _if;

Invalid Examples:

int class; // Error: 'class' is a reserved keyword

String public; // Error: 'public' is a reserved keyword

Case Sensitivity.

Java identifiers are case-sensitive. For example, MyVariable and myVariable are treated as
distinct identifiers.

Valid Examples:

int MyVariable = 10;

int myVariable = 20; // Different from 'MyVariable'

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:

int thisIsAnExtremelyLongVariableName = 100; // Valid but not recommended

Must Not Conflict with Built-in Methods.

Avoid using names that conflict with commonly used built-in methods or library functions
to prevent confusion.

Valid Examples:

int println = 5; // Valid but confusing, as 'println' is used in System.out.println()

Use Meaningful Names.

Choose names that describe the purpose of the variable or method to improve code
readability.

Valid Examples:
int x = 10; // Valid but not descriptive

int age = 10; // Better: Descriptive and meaningful

Java Naming Conventions:

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.

Below table shows an example of naming convention in java :

Key Notes for Each Category:

Classes and Interfaces:

Use PascalCase (capitalize the first letter of each word).

Example: MyClass, UserAccount.

Methods:

Use camelCase (first word lowercase, subsequent words capitalized).

Always name methods as actions or verbs.

Example: getDetails(), calculateTotal().

Variables:

Use camelCase for instance variables and local variables.

Separate words with an underscore (_) only when necessary.

Example: user_age, total_price.

Constants:

Use UPPER_SNAKE_CASE (all uppercase, words separated by underscores).

Example: MAX_VALUE, DEFAULT_TIMEOUT.

Packages:

Use lowercase letters with dots separating levels of hierarchy.

Reflect the project's domain or structure.

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.

Control Statements are used to:

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

Types of Control Statements:

Control Statements in Java are divided in 3 main categories:

Decision-Making Statements or Conditional Statements

These statements allow the program to make decisions and execute a block of code based
on a condition.

Examples are: if, if-else, if-else if ladder, switch.

to read Conditional Statements more deeply.

Iteration or Looping Statements

These statements allow the execution of a block of code multiple times until a condition is
satisfied.

Examples are: for, while, do-while.

to read Looping Statements more deeply.

Jump Statements

These statements are used to alter the flow of control by jumping to a specific part of the
program.

Examples are: break, continue, return.

to read Jump Statements more deeply.


Java Conditional Statements with Examples

Introduction

"Is it raining ?"

"No" - Then lets play cricket.

"Yes" - Ohh, we cant play cricket.

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.

Conditional Statments helps us to:

Control the flow of the program.

Decide which block of code should be executed when certain conditions are met.

Examples of Conditional Statements in Java:

if: Runs code if a condition is true.

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.

switch: Chooses a block of code to run based on specific cases.

These are explained deeply as below:

"if" Statement in Java

The if statement in Java evaluates a boolean condition.

If the condition is true, the block of code inside the if statement is executed.

Syntax:

if(condition)
{

// this block will be executed if the condition is true

Program:

public class IfExample

public static void main(String[] args)

int number = 10;

// Check if the number is positive

if (number > 0)

System.out.println("The number is positive.");

Output:

The number is positive.

NOTE :

If there is only one statement in if block, then curly braces {} are optional.

Syntax :

if(condition)

statement;

Example :

public class IfExample


{

public static void main(String[] args)

int number = 10;

if (number > 0)

System.out.println("The number is positive.");

"if-else" Statement in Java

The if-else statement in Java evaluates a boolean condition.

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)

// this block will be executed if the condition is true

else

// this block will be executed if condition is false

Program:

public class IfElseExample

public static void main(String[] args)


{

int number = -5;

// Check if the number is positive or negative

if (number > 0)

System.out.println("The number is positive.");

else

System.out.println("The number is negative.");

Output:

The number is negative.

NOTE :

If there is only one statement in if-else block, then curly braces {} are optional.

Syntax :

if(condition)

statement;

else

statement;

"if-else if" Ladder Statement in Java

The if-else if ladder in Java evaluates multiple boolean conditions in sequence.


If any of the condition is true, the block of code associated with that condition is executed; if
none of the conditions are true, the optional else block runs.

Syntax:

if (condition1)

// Code to execute if condition1 is true

else if (condition2)

// Code to execute if condition2 is true

// ---- more else-if blocks as needed ----

else

// Code to execute if none of the above conditions are true

Program:

public class IfElseIfLadderExample

public static void main(String[] args)

int marks = 75;

// Determine the grade based on marks

if (marks >= 90)

System.out.println("Grade: A");
}

else if (marks >= 75)

System.out.println("Grade: B");

else if (marks >= 50)

System.out.println("Grade: C");

else

System.out.println("Grade: F");

Output:

Grade: B

"switch" Statement in Java

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.

If no case matches, the optional default block runs.

Syntax:

switch (expression)

case value1:
// Code to execute if expression equals value1

break;

case value2:

// Code to execute if expression equals value2

break;

// ---- more cases as needed ----

default:

// Code to execute if no case matches (optional)

break;

NOTE : Instead of writing many if-else statements, we can use the switch statement for
simpler code.

Program:

public class SwitchExample

public static void main(String[] args)

int day = 3;

// Determine the day of the week

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

Java Looping Statements with Examples

Introduction

Looping Statements are also know as "Iteration Statements".


Looping Statements allow us to repeat a block of code multiple times, making our programs
more efficient and reducing redundancy.

Loops are essential for handling repetitive tasks like:

printing data multiple times

executing tasks until a specific condition is met

iterating through arrays

and many more....

Examples of Looping Statements in Java:

for: Repeats a block of code a specific number of times.

while: Executes a block of code as long as a specified condition is true.

do-while: Executes a block of code once, then repeats it as long as the condition is true.

for-each (Enhanced For Loop): Iterates over elements in an array or collection.

These are explained deeply as below:

"for" Loop in Java

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:

for (initialization; condition; increment/decrement)

// statements (code to execute)

Below is syntax explanation:

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:

public class ForLoopExample

public static void main(String[] args)

// Print numbers from 1 to 5 using a for loop

for (int i = 1; i <= 5; i++)

System.out.println("Number: " + i);

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 :

for(initialization; condition; increment/decrement)


statement;

Example :

public class ForLoopExample

public static void main(String[] args)

for (int i = 1; i <= 5; i++)

System.out.println("Number: " + i);

"while" Loop in Java

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)

// statements (code to execute)

Below is syntax explanation:

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:

Task : Print all the even numbers between 1 and 17

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.

public class WhileLoopExample

public static void main(String[] args)

int no = 2; // Start from the smallest even number

while (no <= 17)

System.out.println("Even Number: " + no);

no = no + 2; // Skip directly to the next even number

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;

"do-while" Loop in Java

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

// statements (code to execute)

} while (condition);

Below is syntax explanation:

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;

public class DoWhileExample

public static void main(String[] args)

Scanner scanner = new Scanner(System.in);

int number;

// Prompting user for a positive number

do

System.out.print("Enter a positive number: ");

number = scanner.nextInt();

} while (number <= 0);

System.out.println("You entered a valid positive number: " + number);

Here we have used Scanner class for User Input, to read Scanner Class deeply with
Program.

Output:

Enter a positive number: -20

Enter a positive number: 0


Enter a positive number: 5

You entered a valid positive number: 5

"for-each" Loop (Enhanced For Loop) in Java

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:

for (dataType variable : collection)

// statements (code to execute)

Below is syntax explanation:

dataType: Specifies the type of the elements in the collection (e.g. int, String).

variable: Represents each element in the collection during each iteration.

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:

public class EnhancedForLoopExample

public static void main(String[] args)

String[] fruits = {"Apple", "Banana", "Cherry"};

// Using Enhanced For Loop (For-each loop)


for (String fruit : fruits)

System.out.println(fruit);

Output:

Apple

Banana

Cherry

Advantages:

Simplifies code by removing the need to manually manage the loop index.

Suitable for iterating over arrays and collections.

Helps avoid ArrayIndexOutOfBoundsException by iterating directly over elements.

Java Jump Statements with Examples

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

Skip parts of the code (e.g., skip an iteration using continue).

Return control to the method caller (e.g., exit a method and optionally return a value
using return).
Examples of Jump Statements in Java:

break: Stops the loop completely when a condition is true.

continue: Skips the current loop step and moves to the next one

return: Ends the method and sends a result back, if needed.

These are explained deeply as below:

"break" Statement in Java

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;

Program 1 (Using break in a loop):

public class BreakExample

public static void main(String[] args)

for (int i = 1; i <= 10; i++)

if (i == 5)

System.out.println("Loop stopped at: " + i);


break; // Exit the loop when i equals 5

System.out.println("Number: " + i);

Output:

Number: 1

Number: 2

Number: 3

Number: 4

Loop stopped at: 5

Program 2 (Using break in a switch statement):

public class BreakSwitchExample

public static void main(String[] args)

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.

"continue" Statements in Java

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.

In a for loop, the increment/decrement step is executed next.

In a while or do-while loop, the condition is checked again.

Syntax:

continue;

Program 1 (Using continue in a Loop):

public class ContinueExample

public static void main(String[] args)

for (int i = 1; i <= 5; i++)

if (i == 3)

System.out.println("Skipping number: " + i);

continue; // Skip the rest of the code in this iteration

}
System.out.println("Number: " + i);

Output:

Number: 1

Number: 2

Skipping number: 3

Number: 4

Number: 5

Program 2 (Using continue in a while loop):

public class ContinueWhileExample

public static void main(String[] args)

int number = 1;

while (number <= 5)

if (number == 3)

System.out.println("Skipping number: " + number);

number++; // Increment the number to avoid an infinite loop

continue; // Skip the rest of the code in this iteration

System.out.println("Number: " + number);


number++;

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.

"return" Statements in Java

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.

Methods not returning a value (Void methods)

Without return: return stops the method early.

With void: return ends the method without returning a value.

Click Here to read deep explanation of above usage


The usage of the return keyword in Java, categorized into two main cases:

Methods Returning a Value

Purpose: These methods return a value 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:

public int addNumbers(int a, int b)

return a + b; // Returns the sum of a and b

Methods Not Returning a Value (Void Methods)

These methods do not return anything to the caller, but they can still use return in two
ways:

Method Without Return in a Void Function

Purpose: To exit the method early without returning anything.

How it works: The return statement is used without a value to stop the method's execution
and return control to the caller.

Example:

public void checkAge(int age)

if (age < 18)

return; // Exits the method early if age is less than 18

System.out.println("You are an adult.");

Methods With void Return Type


Purpose: These methods do not return any data to the caller.

How it works: return is simply used to exit the method when no value needs to be returned.

Example:

public void greet()

System.out.println("Hello, World!");

return; // Stops the method here, no value is returned

Syntax:

return value; // For methods with return types, to send a value back.

return; // For void methods, to exit the method.

Program 1 (Using return in a method):

public class ReturnExample

public static void main(String[] args)

System.out.println("Result: " + addNumbers(5, 3)); // Calling method

public static int addNumbers(int a, int b)

int sum = a + b;

return sum; // Return the sum to the caller

}
Output:

Result: 8

Program 2 (Using return in a void method):

public class ReturnVoidExample

public static void main(String[] args)

checkAge(16); // Testing with an age less than 18

// checkAge(20); // Testing with an age greater than or equal to 18

System.out.println("Voting Ended.");

public static void checkAge(int age)

if (age < 18)

return; // Exits the method early if age is less than 18

System.out.println("You can vote");

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 Programming Paradigm ?

A programming paradigm is a way or style of programming based on certain principles and


techniques.

It defines how code is written, structured, and executed.

Some main programming paradigms are:

What is OOP's ?

OOPS (Object-Oriented Programming System)

OOPs in Java is a programming paradigm or approach that organizes code using objects and
classes to improve reusability, modularity, and maintainability

6 main pillers of OOP's are :-

A blueprint for creating objects (e.g., Car, Person).

An instance of a class (e.g., myCar, john).

Inheritance - Allowing a class to inherit properties from another class.

Polymorphism - Having multiple methods with the same name but different behavior
(method overloading/overriding).

Abstraction - Hiding complex details and showing only the essential features.

Encapsulation - Hiding data using private variables and public methods.

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

Smalltalk, Ruby, Scala etc are purely object oriented languages

Class, Objects & Methods in Java

Real World Example of Class, Methods & Objects


First lefts understand what is Class, Methods & Objects in real world, below are some
classes

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.

Similarly, other classes will have their respective objects.

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.

What is Class in Java ?

Class is a blueprint or prototype or template for creating objects in Java.

It is not a real-world entity, means it does not exist physically; it only defines how an object
should behave.

Class does not occupy memory (but objects occupies memory).

NOTE : Class metadata (such as the number of variables, variable names, method names,
constructors, etc.) is stored in the Method Area.

Syntax :

access-modifiers class ClassName

Fields (Instance Variables) – Store object data.

Constructors – Initialize objects.

Methods – Define object behavior.


Static Members – Shared among all objects.

Nested Classes – Class inside another class.

Blocks – Static and instance blocks for initialization.

Example :

public class Animal

//fields

int eyes;

String color;

//method

void run()

//body

Advance Concept
If you want to read "Different types of classes in Java", then

Types of Java Classes

Types of Java Classes ?

There are different types of java classes which are listed below, these all classes are
explained in further tutorials...

What is Method in Java ?


A method in Java is a block of code that performs a specific task and can be reused multiple
times.

Syntax :

access-modifiers return-type methodName(List of Parameters)

// body

Example :

public void run(String name)

System.out.println(name+" is running");

We can write computations, data processing, input/output operations, object manipulation,


conditional logic etc inside methods to perform specific tasks efficiently.

What is Object in Java ?

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.

Objects has its own :

Identity - Unique memory reference assigned by JVM

State / Attribute - Data stored in instance variables

Behaviour - Actions (methods)

Syntax :

1. Creating Objects:
ClassName objectName = new ClassName();

ClassName objectName; — Declares a reference variable objectName of type 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.

So overall: objectName now holds a reference to a new ClassName object in memory.

2. Access Methods using Objects:

objectName.methodName();

3. Access Fields/Variables using Objects

objectName.field_name;

Example :

public class Animal

String color; //instance variable

void run() //method

System.out.println("Im running");

public static void main(String[] args)

Animal buzo = new Animal(); //creating object (buzo)

buzo.run(); //accessing run() method from buzo object

buzo.color = "Black"; //setting value in instance variable using . operator

System.out.println("Buzo color is "+buzo.color); //accessing instance variable

}
}

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.

// Define a class named Animal1

public class Animal1

// Method to display a running message

public void run()

System.out.println("I'm running"); // Print a message to the console

// Main method - entry point of the program

public static void main(String[] args)

// Create an instance (object) of the Animal1 class

Animal1 jumbo = new Animal1();

// Call the run method using the object 'jumbo'

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.

// Define a class named Animal2

public class Animal2

// Method to display a running message

public void run()

System.out.println("I'm running"); // Print a message to the console

// Main method - entry point of the program

public static void main(String[] args)

// Create an instance (object) of the Animal2 class

Animal2 jumbo = new Animal2();

// Call the run method using the object 'jumbo'

jumbo.run();

// Call the eat method using the object 'jumbo'

jumbo.eat();

// Method to display an eating message

public void eat()


{

System.out.println("I'm eating...!!"); // Print a message to the console

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.

// Define a class named Animal3

public class Animal3

// Method to display a running message

public void run()

System.out.println("I'm running"); // Print a message indicating the animal is running

// Main method - entry point of the program

public static void main(String[] args)

// Create an instance (object) of Animal3 named 'jumbo'

Animal3 jumbo = new Animal3();


// Call the run method using the 'jumbo' object

jumbo.run();

// Call the eat method using the 'jumbo' object

jumbo.eat();

// Create another instance (object) of Animal3 named 'buzo'

Animal3 buzo = new Animal3();

// Call the eat method using the 'buzo' object

buzo.eat();

// Call the run method using the 'buzo' object

buzo.run();

// Method to display an eating message

public void eat()

System.out.println("I'm eating...!!"); // Print a message indicating the animal is eating

Output:

I'm running

I'm eating...!!

I'm eating...!!
I'm running

Program 4:

Below is the another program with parameters in methods.

// Define a class named Animal4

public class Animal4

// Method to display that an animal is running

public void run(String name)

System.out.println(name + " is running");

// Main method - program entry point

public static void main(String[] args)

// Create an object 'jumbo' of Animal4

Animal4 jumbo = new Animal4();

jumbo.run("Jumbo"); // Call run method with "Jumbo"

jumbo.eat("Jumbo"); // Call eat method with "Jumbo"

// Create another object 'buzo' of Animal4

Animal4 buzo = new Animal4();

buzo.eat("Buzo"); // Call eat method with "Buzo"

buzo.run("Buzo"); // Call run method with "Buzo"

}
// Method to display that an animal is eating

public void eat(String name)

System.out.println(name + " is eating...!!");

Output:

Jumbo is running

Jumbo is eating...!!

Buzo is eating...!!

Buzo is running

Program 5:

Below is the another program with multiple parameters in methods.

// Define a class named Animal5

public class Animal5

// Method to display that an animal has run a certain distance

public void run(String name, int distance_km)

System.out.println(name + " has run " + distance_km + " km");

// Main method - program entry point

public static void main(String[] args)


{

// Create an object 'jumbo' of Animal5

Animal5 jumbo = new Animal5();

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"

// Create another object 'buzo' of Animal5

Animal5 buzo = new Animal5();

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

// Method to display that an animal is eating a specific dish

public void eat(String name, String dish)

System.out.println(name + " is eating " + dish);

Output:

Jumbo has run 5 km

Jumbo is eating grass

Buzo is eating meat

Buzo has run 12 km

Program 6:

Below is the another program with instance variables and method parameter.
// Define a class named Animal6

public class Animal6

// Declare instance variables

int no_of_eyes; // Variable to store the number of eyes

String color; // Variable to store the color of the animal

// Method to display the details of an animal

public void details(String name)

System.out.println("-------Details of " + name + "-------");

System.out.println("Eyes : " + no_of_eyes);

System.out.println("Color : " + color);

// Main method - program entry point

public static void main(String[] args)

// Create an object 'jumbo' of Animal6 and assign values

Animal6 jumbo = new Animal6();

jumbo.no_of_eyes = 2;

jumbo.color = "Brown";

jumbo.details("Jumbo"); // Call details method for 'jumbo'

// Create another object 'buzo' of Animal6 and assign values

Animal6 buzo = new Animal6();


buzo.no_of_eyes = 2;

buzo.color = "Black";

buzo.details("Buzo"); // Call details method for 'buzo'

Output:

------Details of Jumbo-------

Eyes : 2

Color : Brown

------Details of Buzo-------

Eyes : 2

Color : Black

Program 7: (Best Practice Program)

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.

// Define a class named Animal7

class Animal7

// Method to display a running message

void run()

System.out.println("I'm running");

// Define the main class MainApp7


public class MainApp7

// Main method - program entry point

public static void main(String[] args)

// Create an object 'buzo' of Animal7

Animal7 buzo = new Animal7();

buzo.run(); // Call the run method

Output:

I'm running

Program 8: (Best Practice Program)

Here we have created Animal8, Birds8 class with different methods and also created Main
class as separate class which is good practice.

// Define a class named Animal8

class Animal8

// Method to display a running message

void run()

System.out.println("I'm running");

// Define a class named Birds8


class Birds8

// Method to display a flying message

void fly()

System.out.println("I'm flying");

// Define the main class MainApp8

public class MainApp8

// Main method - program entry point

public static void main(String[] args)

// Create an object 'buzo' of Animal8 and call the run method

Animal8 buzo = new Animal8();

buzo.run();

// Create an object 'sparrow' of Birds8 and call the fly method

Birds8 sparrow = new Birds8();

sparrow.fly();

Output:

I'm running
I'm flying

Constructors in Java

What is Constructor in Java ?

A constructor in Java is a special type of method used to initialize objects.

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 :

access-modifiers ClassName(list of parameters)

//body

Example :

public class Test

//constructor

public Test()

//body

public static void main(String[] args)

Test t = new Test(); //constructor called automatically when we create object

}
}

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.

Rules for Constructors in Java

Below are rules for constructors in Java:

The constructor must have the same name as that of class name.

A constructor does not have a return type (not even void).

Constructors can have any access modifier (public, private, protected or default) but cannot
have non-access modifiers like static, final, abstract etc.

The constructor is called automatically when an object is created.

Types of Constructors in Java

There are 3 types of constructors in Java:-

Default Constructor (created by compiler)

No-Args (No Argument) Constructor (created by programmer)

Parameterized Constructor (created by programmer)

These are explained below one by one....

1. Default Constructor:

If programmer does'nt create any constructor, then Java compiler automatically creates one
constructor which is known as default constructor.

It initializes an object properties with default values (0, null, false).

Syntax :
class ClassName

// Default constructor is automatically provided by Java Compiler

Example :

public class Test

//here programmer didnt created any constructor, so Java compiler will create default
constructor automatically.

public static void main(String[] args)

Test t = new Test(); //default constructor called automatically when we create object

Some important points for Default Constructor:

The access modifier of Default Constructor is as that of class. If a class is public, the default
constructor is public and so on.

Default Constructor has no parameters.

Default Constructor calls the superclass constructor (super()).

public Test()

super();

2. No-Args (No Argument) Constructor:


If a programmer creates the constructor without any parameters, then it is known as No
Argument Constructor.

It is used to initialize objects with default values or perform some basic setup.

Syntax :

class ClassName

// No-Argument Constructor

ClassName()

// Initialization code (if needed)

Example :

public class Student

String name;

// No-Argument Constructor

Student()

name = "Deepak"; // Assigning default value

void display()

System.out.println("Student Name: " + name);

}
public static void main(String[] args)

Student s1 = new Student(); // Calls no-argument constructor

s1.display(); // Output: Student Name: Deepak

3. Parameterized Constructor:

If a programmer creates the constructor with parameters, then it is known as


Parameterized Constructor.

It is used to:

Initialize objects with specific values instead of default values.

Avoid the need for setter methods after object creation.

Improve code readability by directly assigning values through the constructor.

Syntax :

class ClassName

ClassName(dataType parameter1, dataType parameter2)

// Initialization code

Example :

class Student

String name;
int rollno;

// Parameterized Constructor

Student(String n, int rn)

name = n;

rollno = rn;

void display()

System.out.println("Name: " + name + ", Roll No.: " + rollno);

public static void main(String[] args)

Student s1 = new Student("Deepak", 101); // Passing values

s1.display(); // Output: Name: Deepak, Roll No.: 101

Relationship Between Classes in Java

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:

Association (HAS-A relationship)

Dependency (USES-A relationship)

Inheritance (IS-A relationship)

1. Association (HAS-A relationship)

Definition : Association is a relationship where one class interacts with another class.

Example :

Student HAS-A Address

Car HAS-A Engine.

How to achieve association ?

Association is achieved by declaring object references as instance variables inside a class.

Program :

class Address

String city = "Delhi";

String country = "India";

void displayAddress()

System.out.println("City: " + city + ", Country: " + country);

class Student

{
String name = "Deepak";

int rollno = 101;

// Direct reference to another class

Address address = new Address(); // Object created directly inside the class

void displayInfo()

System.out.println("Name: " + name + ", Roll No: " + rollno);

address.displayAddress();

public class MainApp

public static void main(String[] args)

Student student = new Student(); // No need to pass Address

student.displayInfo(); // Displays student info along with address

Output:

Name: Deepak, Roll No: 101

City: Delhi, Country: India

Association, Composition & Aggregation in Java


Association (HAS-A relationship)

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 :

Student HAS-A Address

Car HAS-A Engine.

Laptop HAS-A Processor.

How to achieve association ?

Association is achieved by declaring object references as instance variables inside a class.

We can inject dependent objects using:

Direct Reference Variables

Creating the object directly inside the class

Constructor Injection

Passing the dependent object through the constructor

Setter Injection

Injecting the dependent object using a public setter method

Program 1 (Association using Direct Reference Variables) :

class Address

String city = "Delhi";

String country = "India";

void displayAddress()

System.out.println("City: " + city + ", Country: " + country);


}

class Student

String name = "Deepak";

int rollno = 101;

// Direct reference to another class

Address address = new Address(); // Object created directly inside the class

void displayInfo()

System.out.println("Name: " + name + ", Roll No: " + rollno);

address.displayAddress();

public class MainApp

public static void main(String[] args)

Student student = new Student(); // No need to pass Address

student.displayInfo(); // Displays student info along with address

}
Output:

Name: Deepak, Roll No: 101

City: Delhi, Country: India

Program 2 (Association using Constructor Injection) :

class Engine

void startEngine()

System.out.println("Engine starts.");

class Car

// HAS-A relationship: Car has an Engine

private Engine engine;

// Constructor Injection: Engine is provided from outside

Car(Engine engine)

this.engine = engine;

void startCar()

engine.startEngine(); // Car uses Engine to start


System.out.println("Car starts.");

public class MainApp

public static void main(String[] args)

// create the dependency

Engine engine = new Engine();

// inject it into Car

Car myCar = new Car(engine);

myCar.startCar();

Output:

Engine starts.

Car starts.

Program 3 (Association using Setter Injection) :

class Processor

void startProcessor()

System.out.println("Processor starts processing.");

}
class Laptop

// HAS-A relationship: Laptop has a Processor

private Processor processor;

// Setter Injection: Injecting dependency through setter method

public void setProcessor(Processor processor)

this.processor = processor;

void startLaptop()

processor.startProcessor();

System.out.println("Laptop starts.");

public class MainApp

public static void main(String[] args)

// Create the dependency

Processor processor = new Processor();


// Create the dependent object

Laptop myLaptop = new Laptop();

// Inject the dependency using setter

myLaptop.setProcessor(processor);

// Use the dependent object

myLaptop.startLaptop();

Output:

Processor starts processing.

Laptop starts.

Types of Association:

Aggregation

Weak relationship between classes.

Objects can exist independently of each other.

Example:

A Car HAS-A Music Player.

The Music Player can be removed, reused, or replaced — it can exist without the car.

Composition

Strong relationship between classes.

One object is fully dependent on the other.

Example:

A Car HAS-A Engine.


The Engine is an essential part of the car — if the car is destroyed, the engine has no real
standalone meaning.

Note : In both Aggregation and Composition, program logic remains the same, but the
relationship between the classes is different.

Associations can be:

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.

2. Dependency (USES-A relationship)

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.

Example : Office Worker USES-A Printer.

How to achieve dependency ?

Dependency can be achieved through:

Local variables inside methods

Method parameters

Program :

class Printer

void printDocument(String doc)

{
System.out.println("Printing document: " + doc);

class OfficeWorker

void doWork()

Printer printer = new Printer(); // Dependency via local variable

printer.printDocument("ProjectReport.pdf");

System.out.println("Work completed.");

public class MainApp

public static void main(String[] args)

OfficeWorker worker = new OfficeWorker();

worker.doWork(); // OfficeWorker depends on Printer to print

Output:

Printing document: ProjectReport.pdf

Work completed.

Dependency (USES-A Relationship) in Java


Dependency (USES-A relationship)

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.

It represents a USES-A relationship.

The dependency is typically short-lived, existing only during the execution of a method.

Example :

Teacher USES-A Whiteboard

Office Worker USES-A Printer

How to achieve dependency ?

Dependency is achieved by creating or using objects of another class inside a method,


instead of holding them as instance variables.

We can inject dependent objects using:

Local Variable inside Method

The dependent object is created directly in a method

Method Parameter

The dependent object is passed as a method argument

It promotes more flexibility and testability

Program 1 (Dependency using Local Variable inside Method) :

// Dependent class

class Whiteboard

void writeOnBoard()

System.out.println("Writing on the whiteboard...");


}

// Main class that uses Whiteboard

class Teacher

void teachLesson()

// Local variable: Dependency created inside the method

Whiteboard board = new Whiteboard();

board.writeOnBoard(); // Temporary usage

System.out.println("Teacher is explaining the topic.");

// Entry point

public class MainApp

public static void main(String[] args)

Teacher teacher = new Teacher();

teacher.teachLesson(); // Trigger method that shows dependency

Output:

Writing on the whiteboard...


Teacher is explaining the topic.

Program 2 (Dependency using Method Parameter) :

// Dependent class

class Printer

void printDocument()

System.out.println("Printing document...");

// Main class that depends on Printer

class OfficeWorker

// Dependency injected via method parameter

void performTask(Printer printer)

printer.printDocument(); // Temporary usage

System.out.println("OfficeWorker has completed printing task.");

// Entry point

public class MainApp

public static void main(String[] args)


{

Printer printer = new Printer(); // Create dependency

OfficeWorker worker = new OfficeWorker(); // Create dependent

// Inject dependency via method parameter

worker.performTask(printer);

Output:

Printing document...

OfficeWorker has completed printing task.

Dependency vs Association:

3. Inheritance (IS-A relationship)

Definition : IS-A (Inheritance) is the process by which a child class (subclass) inherits fields
and methods from a parent class (superclass).

Example : A Car IS-A Vehicle.

How to achieve inheritance ?

Inheritance is achieved using:

extends keyword in case of classes.

implements keyword in case of interfaces.

Program :

class Vehicle

void start()
{

System.out.println("Vehicle starts.");

class Car extends Vehicle

void drive()

System.out.println("Car drives.");

public class MainApp

public static void main(String[] args)

Car myCar = new Car();

myCar.start(); // inherited from Vehicle

myCar.drive(); // specific to Car

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.

Inheritance represents an IS-A relationship, also known as a parent-child relationship. It


signifies that a subclass is a type of its superclass.

For example:

A Car IS-A Vehicle.

A Dog IS-A Animal.

A Surgeon IS-A Doctor.

How to achieve inheritance in Java?

By using the extends keyword for class inheritance.

By using the implements keyword for interface inheritance.

Program 1 (using extends keyword): :

class Vehicle

void start()

System.out.println("Vehicle starts.");

class Car extends Vehicle

{
void drive()

System.out.println("Car drives.");

public class MainApp

public static void main(String[] args)

Car myCar = new Car();

myCar.start(); // inherited from Vehicle

myCar.drive(); // specific to Car

Program 2 (using implements keyword): :

interface Animal

void eat();

class Dog implements Animal

public void eat()

System.out.println("Dog eats.");
}

public class MainApp

public static void main(String[] args)

Dog myDog = new Dog();

myDog.eat(); // inherited from Animal

//Animal myAnimal = new Animal(); // error because we cannot create an object of an


interface

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.

Method Overriding: Inheritance enables method overriding, allowing a child class to


provide a specific implementation of a method already defined in its parent class.

Polymorphism: Inheritance supports runtime polymorphism using method overriding.

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

There are 5 types of inheritance in Java:

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

Hybrid Inheritance: A combination of two or more types of inheritance. (Not supported in


Java directly, but can be achieved using interfaces.)

to learn more about the types of inheritance in Java.

Types of Inheritance in Java

Introduction

in Java means one class can use the properties (like variables and methods) of another class.

It is the fundamental concept of OOP's which helps to reuse code.

It creates a parent-child relationship, where the parent is called the superclass and the child
is called the subclass.

to read more about .

There are 5 types of Inheritance in Java:

Single Inheritance

Multilevel Inheritance

Hierarchical Inheritance

Multiple Inheritance (not supported directly)

Hybrid Inheritance (not supported directly)

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 {

// Parent class code

class ChildClass extends ParentClass {

// Child class code

Program example:

// Parent class

class BankAccount

void accountType()

System.out.println("This is a general bank account.");

// Child class

class SavingsAccount extends BankAccount

void interestRate()

System.out.println("Savings account offers 4% interest.");


}

// Main class

public class MainApp

public static void main(String[] args)

SavingsAccount sa = new SavingsAccount();

sa.accountType(); // Inherited method

sa.interestRate(); // Specific method

Output:

This is a general bank account.

Savings account offers 4% interest.

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.

This forms a hierarchy of classes connected through inheritance.

Syntax:

class Grandparent

// code
}

class Parent extends Grandparent

// code

class Child extends Parent

// code

Program example:

// Grandparent class

class Animal

void eat()

System.out.println("Animal is eating.");

// Parent class

class Dog extends Animal

void bark()

System.out.println("Dog is barking.");
}

// Child class

class Puppy extends Dog

void weep()

System.out.println("Puppy is weeping.");

public class MainApp

public static void main(String[] args)

Puppy p = new Puppy();

p.eat(); // From Animal

p.bark(); // From Dog

p.weep(); // Own method

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.

Supports code reuse across multiple levels.

Helps model real-world hierarchical relationships.

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

// Parent class code

class Child1 extends Parent

// Child1 specific code

class Child2 extends Parent

// Child2 specific code

Program example:

// Parent class
class Vehicle

void fuelType()

System.out.println("Uses fuel.");

// First child class

class Car extends Vehicle

void wheels()

System.out.println("Car has 4 wheels.");

// Second child class

class Bike extends Vehicle

void handleType()

System.out.println("Bike has a handlebar.");

}
public class MainApp

public static void main(String[] args)

Car c = new Car();

c.fuelType(); // Inherited from Vehicle

c.wheels(); // Car specific

Bike b = new Bike();

b.fuelType(); // Inherited from Vehicle

b.handleType(); // Bike specific

Output:

Uses fuel.

Car has 4 wheels.

Uses fuel.

Bike has a handlebar.

Important Points to Remember:

Hierarchical inheritance allows code reuse through a shared parent class.

Each subclass gets its own copy of the parent class’s properties and methods.

It promotes loose coupling by separating shared logic into a base class.

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.

This prevents conflicts and ambiguity caused by the Diamond Problem.

Syntax using interfaces:

interface A

void methodA();

interface B

void methodB();

class C implements A, B

public void methodA()

System.out.println("Method from interface A");

public void methodB()

{
System.out.println("Method from interface B");

Program example (using interfaces):

// Interface A

interface A

void displayA();

// Interface B

interface B

void displayB();

// Class C implementing both interfaces

class C implements A, B

public void displayA()

System.out.println("Display from interface A");

public void displayB()


{

System.out.println("Display from interface B");

public class MainApp

public static void main(String[] args)

C obj = new C();

obj.displayA();

obj.displayB();

Output:

Display from interface A

Display from interface B

Important Points to Remember:

Java classes cannot extend more than one class at a time.

Multiple inheritance is achieved using interfaces in Java.

This design avoids ambiguity and promotes clean architecture.

Interfaces define abstract behavior that multiple classes can implement.

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.

Syntax using interfaces and a class:

interface A

void methodA();

interface B

void methodB();

class C

void methodC()

System.out.println("Method from class C");

// Class D inherits class C and implements A and B

class D extends C implements A, B


{

public void methodA()

System.out.println("Method from interface A");

public void methodB()

System.out.println("Method from interface B");

Program example (using interfaces and class):

// Interface A

interface A

void showA();

// Interface B

interface B

void showB();

// Class C
class C

void showC()

System.out.println("Show from class C");

// Class D: extends C and implements A and B

class D extends C implements A, B

public void showA()

System.out.println("Show from interface A");

public void showB()

System.out.println("Show from interface B");

// Main class

public class MainApp

public static void main(String[] args)


{

D obj = new D();

obj.showA();

obj.showB();

obj.showC();

Output:

Show from interface A

Show from interface B

Show from class C

Important Points to Remember:

Hybrid inheritance combines multiple types of inheritance to represent more complex


relationships.

Java does not support hybrid inheritance with classes directly.

It can be implemented safely using interfaces to avoid ambiguity.

Helps in designing systems with multiple traits and layered behaviors.

Important Points

Some important points to remember about inheritance in Java:

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

Polymorphism is one of the main concepts of Object-Oriented Programming (OOP) in Java.

Poly → many, Morph → forms; so Polymorphism means "many forms".

It means the ability of a single entity (method, object, or operator) to behave in multiple
ways.

Java uses polymorphism to let us write flexible and reusable code.

Real-world Examples :-

A person: acts as a teacher, father, son — different roles.

Water: takes shape of the container it’s in.

Sound: same sound word used in different tones.

Advantage of Polymorphism :-

Increases flexibility and reusability.

Allows code extensibility without modifying existing code.

Supports single task, multiple implementations.

Enhances maintainability and scalability.

Types of Polymorphism in Java :-

Compile-Time Polymorphism

It is also known as Static Binding or Early Binding.

It is achieved by Method Overloading or Operator Overloading.

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

void add(int a, int b)

System.out.println(a+b);

void add(double a, double b)

System.out.println(a+b);

Here:

Calculator calc = new Calculator(); // Reference type = Calculator

calc.add(5, 10); // method signature = add(int, int) → decided at compile-time

to read more about

Method Overloading in Java

Introduction

Method Overloading is a way (or mechanism or form) to achieve compile-time


polymorphism

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.

Rules of Method Overloading :-


All overloaded methods must have the same name.

All the methods should be in same class or in subclass.

All the method parameters list must be different:

Number of parameters

Type of parameters

Order of parameters

Example :-

class Calculator

int add(int a, int b)

return a + b;

double add(double a, double b)

return a + b;

int add(int a, int b, int c)

return a + b + c;

public class MainApp

{
public static void main(String[] args)

Calculator calc = new Calculator();

// Calling overloaded methods

int result1 = calc.add(10, 20);

double result2 = calc.add(5.5, 4.5);

int result3 = calc.add(1, 2, 3);

// Printing the results

System.out.println("Result of add(int, int): " + result1);

System.out.println("Result of add(double, double): " + result2);

System.out.println("Result of add(int, int, int): " + result3);

Output:

Result of add(int, int): 30

Result of add(double, double): 10.0

Result of add(int, int, int): 6

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.

Advantages of Method Overloading :-

Increased Readability:

Using the same method name for similar actions makes the code easier to understand.

Faster Execution (at Compile Time):


Since the method to be called is determined at compile time, it improves performance over
runtime decisions (like in method overriding).

Easy Maintenance:

Having logically grouped methods under one name makes code more organized and easier
to maintain.

Encourages DRY Principle (Don't Repeat Yourself):

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.

Cleaner API Design:

When designing libraries or APIs, overloading allows a consistent interface for different
data inputs.

Important Points

Some important points to remember about method overloading in Java:

Method overloading does not depend on return type, it depends only on the parameter list.

int add(int a, int b) { return a + b; }

double add(double a, double b) { return a + b; } //Valid overload

Main method can also be overloaded in Java.

public static void main(String[] args)

System.out.println("Main method with String[]");

public static void main(int[] args)

System.out.println("Main method with int[]");

}
Constructors can also be overloaded.

class Student

Student() {}

Student(String name) {}

Student(String name, int age) {}

Access modifiers (e.g., public, private) can be different.

public void show() {}

private void show(int a) {} //Valid overload

Static methods can be overloaded.

static void display() {}

static void display(String msg) {} //Valid overload

Runtime Polymorphism

It is also known as Dynamic Binding or Late Binding.

It is achieved by Method Overriding.

In runtime polymorphism, the JVM (Java Virtual Machine) decides at runtime


which overridden method to invoke based on the actual object (not the reference type).

Program ():

class Animal

void makeSound()

System.out.println("Some generic sound");

}
class Dog extends Animal

void makeSound()

System.out.println("Dog barks");

Here:

Animal obj = new Dog(); // Reference type = Animal, Object type = Dog

obj.makeSound(); // Method decided at runtime → calls Dog's makeSound()

to read more about

Method Overriding in Java

Introduction

Method Overriding is a way (or mechanism or form) to achieve runtime polymorphism

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

Rules of Method Overriding :-

The methods must have the same name.

The method must be in different class or in subclass.

All the method parameters list must be same:

Number of parameters

Type of parameters

Order of parameters
Should follow IS-A relationship (Inheritance).

Example :-

class Bank

double getInterestRate()

return 0.0;

class SBI extends Bank

@Override

double getInterestRate()

return 6.5;

class HDFC extends Bank

@Override

double getInterestRate()

return 7.0;

}
}

class ICICI extends Bank

@Override

double getInterestRate()

return 6.8;

public class Main

public static void main(String[] args)

Bank b1 = new SBI();

Bank b2 = new HDFC();

Bank b3 = new ICICI();

System.out.println("SBI Interest Rate: " + b1.getInterestRate() + "%");

System.out.println("HDFC Interest Rate: " + b2.getInterestRate() + "%");

System.out.println("ICICI Interest Rate: " + b3.getInterestRate() + "%");

Output:

SBI Interest Rate: 6.5%


HDFC Interest Rate: 7.0%

ICICI Interest Rate: 6.8%

Advantages of Method Overriding :-

Runtime Polymorphism::

Allows Java to decide at runtime which method to execute, enabling flexible and dynamic
behavior.

Improves Code Reusability:

Reuses method names from the parent class while allowing customized behavior in the
child class.

Supports Inheritance:

Strengthens the use of inheritance by enabling subclasses to modify or enhance the


behavior of parent class methods.

Better Readability and Maintainability:

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.

Useful in Frameworks & Libraries::

Commonly used in Java frameworks (like Spring, Hibernate) where parent classes define
default behavior and subclasses override as needed.

Important Points

Some important points to remember about method overriding in Java:

Method overriding requires the subclass method to have the same name, return type, and
parameter list as the superclass method.

The overriding method must be in a subclass, not in the same class.


The access modifier of the overriding method cannot be more restrictive than that of the
overridden method.
(For example, if the parent method is public, the overriding method cannot be private.)

// Valid override

protected void display() {}

// Invalid override (if superclass method is public)

private void display() {}

Static methods, constructors, and the main method cannot be overridden.

Methods marked as final, static, or private cannot be overridden.

The overriding method can throw only the same or narrower checked exceptions than the
overridden method.

The @Override annotation is recommended to avoid mistakes and improve code


readability.

@Override

void methodName() {

// implementation

Method overriding is used to achieve runtime polymorphism or dynamic method dispatch.

Important Points

Some important points to remember about polymorphism in Java:

Polymorphism is mainly achieved through method overloading and method overriding.

Overloading → Compile-time polymorphism

Overriding → Runtime polymorphism


Polymorphism supports the Open/Closed Principle.

Code is open for extension but closed for modification.

Polymorphism helps reduce code duplication by reusing the same interface or method
name across different types.

Upcasting enables runtime polymorphism.

Parent class reference can hold a child class object.

Example:

Animal myDog = new Dog();

Abstraction in Java

Introduction

Abstraction is a concept of :

hiding internal implementation details and showing only the essential features to the user.

Real World Example

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.

How to achieve Abstraction :-

We can achieve Abstraction by two ways:

Using Abstract Classes

Using Interfaces

Abstract Methods :-

Introduction

An abstract method is a method that is declared without an implementation (no method


body).
It only provides the method signature and forces subclasses to provide the actual
implementation.

Declared using the abstract keyword.

Syntax & Example :

Syntax : abstract returnType methodName(parameters);

Example : abstract void makeSound(); // Abstract method – no body

Rules of Abstract Method :

No method body – ends with a semicolon (;).

Must be declared inside an abstract class or interface.

A class that contains an abstract method must be declared abstract.

Abstract methods must be overridden by subclasses, unless the subclass is also abstract.

Cannot be private, static or final — because it must be overridden.

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

It cannot be instantiated (you cannot create objects of it).

Syntax & Example :

Syntax:

abstract class ClassName

// abstract method

abstract void makeSound();

// concrete method

void sleep()

{
System.out.println("Sleeping...");

Example:

abstract class Car

// Abstract method (must be implemented by subclasses)

abstract void startEngine();

// Concrete method

void fuelType()

System.out.println("This car uses petrol or diesel.");

class Sedan extends Car

@Override

void startEngine()

System.out.println("Sedan engine started with key ignition.");

Rules of Abstract Class :

Must be declared using the abstract keyword.

Can contain both abstract and concrete methods.


Cannot be instantiated directly.

Subclass must override all abstract methods or be declared abstract itself.

Can have constructors, static methods and final methods.

Can extend another class and implement interfaces.

Program Without Abstraction

class Car

int no_of_tyres = 4;

void displayTyres()

System.out.println("Car has " + no_of_tyres + " tyres.");

void start()

System.out.println("Car starts with a key ignition.");

// Scooter class without abstraction

class Scooter

int no_of_tyres = 2;
void displayTyres()

System.out.println("Scooter has " + no_of_tyres + " tyres.");

void start()

System.out.println("Scooter starts with a kick or self-start.");

// Main class to run the program

public class MainApp

public static void main(String[] args)

Car myCar = new Car();

myCar.displayTyres();

myCar.start();

System.out.println();

Scooter myScooter = new Scooter();

myScooter.displayTyres();

myScooter.start();

}
}

Output:

Car has 4 tyres.

Car starts with a key ignition.

Scooter has 2 tyres.

Scooter starts with a kick or self-start.

Disadvantages of Not Using Abstraction

No Polymorphism:

We can’t use a common parent reference to refer to multiple types of vehicles.

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.

No Common Structure or Contract:


Without a common abstract class or interface, there’s no standard structure that all vehicle
classes must follow.

This leads to inconsistent design and makes collaboration or team development harder.

Program Using Abstraction

// Abstract class used to remove code duplication and enforce method structure

abstract class Vehicle

int no_of_tyres;

// Common method to avoid duplication (removes disadvantage #2)

void displayTyres()

System.out.println("This vehicle has " + no_of_tyres + " tyres.");

// Abstract method to enforce implementation in all subclasses (removes disadvantage #3)

abstract void start();

// Car class extends abstract class and provides its own implementation

class Car extends Vehicle

Car()

no_of_tyres = 4;

}
// Required by abstract class - enforces structure (removes disadvantage #3)

@Override

void start()

System.out.println("Car starts with key ignition.");

// Scooter class also extends abstract class

class Scooter extends Vehicle

Scooter()

no_of_tyres = 2;

@Override

void start()

System.out.println("Scooter starts with kick or self-start.");

// Main class to test polymorphism and abstraction

public class Main

{
public static void main(String[] args)

// Using polymorphism (removes disadvantage #1)

Vehicle myVehicle1 = new Car();

myVehicle1.displayTyres();

myVehicle1.start();

System.out.println();

Vehicle myVehicle2 = new Scooter();

myVehicle2.displayTyres();

myVehicle2.start();

// Easier to scale and add new vehicle types consistently (removes disadvantage #4)

Output:

This vehicle has 4 tyres.

Car starts with key ignition.

This vehicle has 2 tyres.

Scooter starts with kick or self-start.

Interface in Java
Introduction

An interface in Java is a blueprint of a class, containing only method signatures (no


implementations) and constants.

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.

In Java 9, we can provide the implementation of methods using private methods.

Syntax :-

interface InterfaceName

// public static final variables (constants)

// public abstract methods

Use of Interfaces :-

Used to achieve 100% abstraction in Java.

Used to define a common behaviour across unrelated classes.

Used to achieve multiple inheritance in Java.

Used to achieve loose coupling in our code.

Used extensively in frameworks, APIs, and design patterns (e.g., DAO, Service Layer).

1. Used to achieve 100% abstraction in Java.

Example:

// Interface with 100% abstraction

interface Vehicle

{
void start();

void stop();

// Car class implements the interface

class Car implements Vehicle

public void start()

System.out.println("Car is starting...");

public void stop()

System.out.println("Car is stopping...");

// Main class to test

public class Main

public static void main(String[] args)

Vehicle v = new Car(); // Interface reference (polymorphism)

v.start();

v.stop();
}

Output:

Car is starting...

Car is stopping...

2. Used to define a common behaviour across unrelated classes.

Example:

// Interface with a common method

interface Printable

void print();

// Unrelated class 1

class Document implements Printable

public void print()

System.out.println("Printing document...");

// Unrelated class 2

class Image implements Printable

public void print()


{

System.out.println("Printing image...");

// Main class

public class Main

public static void main(String[] args)

Printable p1 = new Document();

Printable p2 = new Image();

p1.print();

p2.print();

Output:

Printing document...

Printing image...

3. Used to achieve multiple inheritance in Java.

Example:

interface I1

void m1();

}
interface I2

void m2();

// Multiple Inheritance using interfaces

class A implements I1, I2

public void m1()

System.out.println("Method m1 from interface I1");

public void m2()

System.out.println("Method m2 from interface I2");

// Main class

public class Main

public static void main(String[] args)

A obj = new A();


obj.m1();

obj.m2();

Output:

Method m1 from interface I1

Method m2 from interface I2

4. Used to achieve loose coupling in our code.

Example:

import java.util.Scanner;

// Interface to achieve loose coupling

interface Payment

void pay();

// UPI Payment Implementation

class UpiPayment implements Payment

public void pay()

System.out.println("Payment done using UPI.");

}
// Net Banking Payment Implementation

class NetBankingPayment implements Payment

public void pay()

System.out.println("Payment done using Net Banking.");

// Checkout class using interface (not tightly bound to any one payment method)

class PaymentCheckout

void payment(Payment payment)

payment.pay(); // Loose coupling: works with any class that implements Payment

// Main class with switch-case

public class MainApp

public static void main(String[] args)

Scanner scanner = new Scanner(System.in);

PaymentCheckout checkout = new PaymentCheckout();


System.out.println("Choose payment method:");

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

System.out.println("2. Net Banking");

System.out.print("Enter choice: ");

int choice = scanner.nextInt();

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:

Choose payment method:

1. UPI

2. Net Banking

Enter choice: 1

Payment done using UPI.


If user enters 2:

Choose payment method:

1. UPI

2. Net Banking

Enter choice: 2

Payment done using Net Banking.

5. Used extensively in frameworks, APIs, and design patterns

Frameworks:

Spring uses interfaces like CrudRepository, ApplicationContext.

Helps in writing clean, loosely-coupled code.

Java APIs:

Collections use interfaces like List, Set, Map.

JDBC provides interfaces like Connection, Statement.

Design Patterns:

DAO Pattern: Interface defines data access methods.

Service Layer: Interface declares business logic methods.

Testing:

Interfaces are mocked in unit tests for flexibility and isolation.

Encapsulation in Java

Introduction

Encapsulation is the mechanism of binding data (variables) and actions (methods) into a
single unit, called a class.

Technically, every class is an example of encapsulation.

Real World Example:


A capsule in which main medicine is encapsulated.

A car is in which engine, wheels, and other parts are encapsulated.

Java Program Example:

class Car

// Data members (variables)

String brand;

int speed;

// Method to display person details

void setDetails(String b, int s)

brand = b;

speed = s;

void printDetails()

System.out.println("Brand : " + brand);

System.out.println("Speed : " + speed);

public class Main

public static void main(String[] args)


{

// Creating object

Car c = new Car();

// Calling method

c.setDetails("Tata", 100);

Output:

Brand : Tata

Speed : 100

Explanation:

Person class contains both data (name, age) and method (displayInfo()).

Everything is inside one unit (class) — this is the essence of encapsulation.

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.

Rules for Encapsulation :-

1. Private Variables :

Declare variables as private so that they cannot be accessed directly from outside the class.

2. Public Getter & Setter Methdos :

Provide public getter and setter methods to access and modify the private variables.

Actual/Proper Encapsulated Java Program Example :-

class Car

{
// Private data members (encapsulated)

private String brand;

private int speed;

// Public setter for brand

public void setBrand(String brand)

this.brand = brand;

// Public getter for brand

public String getBrand()

return brand;

// Public setter for speed

public void setSpeed(int speed)

// Optional: simple validation

if (speed >= 0)

this.speed = speed;

}
// Public getter for speed

public int getSpeed()

return speed;

// Method to print car details

public void printDetails()

System.out.println("Brand : " + brand);

System.out.println("Speed : " + speed);

public class MainApp

public static void main(String[] args)

Car c = new Car();

// Setting values using setters

c.setBrand("Tata");

c.setSpeed(100);

// Printing car details

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

Improves code maintainability: Keeps internal implementation hidden, making changes


easier.

Enhances flexibility: Internal logic can change without affecting external code.

Prevents unauthorized or accidental modifications: Limits who and how data can be
changed.

Below is the program elaborating above uses :

Example:

// Class demonstrating proper encapsulation

class Account

// 🔒 Protects data by hiding it from direct access

private String accountHolder;

private double balance;

// ✅ Public getter (controlled access to private data)

public String getAccountHolder()


{

return accountHolder;

// ✅ Public setter (controlled access with flexibility for future validation)

public void setAccountHolder(String accountHolder)

this.accountHolder = accountHolder;

// ✅ Getter for balance

public double getBalance()

return balance;

// 💰 Method to deposit money

public void deposit(double amount)

// Allows data validation before modifying balance

if (amount > 0)

balance = balance + amount;

System.out.println("You have deposited " + amount + " Rs.");

System.out.println("New balance is: " + getBalance() + " Rs.");

}
else

System.out.println("Invalid deposit amount");

// 💸 Method to withdraw money

public void withdraw(double amount)

// Data validation: prevents negative balance

if (amount > 0 && amount <= balance)

balance = balance - amount;

System.out.println("You have withdrawn " + amount + " Rs.");

System.out.println("New balance is: " + getBalance() + " Rs.");

else

System.out.println("Invalid or Insufficient balance for withdrawal");

public class BankApp

public static void main(String[] args)


{

// Creating object

Account account = new Account();

// 🚫 Cannot access private fields directly

// account.balance = 10000; // ❌ Not allowed (Encapsulation)

// ✅ Uses public setters and methods

account.setAccountHolder("Deepak");

// ✅ Proper access via methods ensures validation

account.deposit(10000); // Valid deposit

account.withdraw(3000); // Valid withdrawal

account.deposit(-20000); // Invalid deposit

account.withdraw(100000); // Invalid withdrawal (insufficient funds)

Output:

You have deposited 10000.0 Rs.

New balance is: 10000.0 Rs.

You have withdrawn 3000.0 Rs.

New balance is: 7000.0 Rs.

Invalid deposit amount

Invalid or Insufficient balance for withdrawal


Interview Questions :-

What is encapsulation & its use ?

What is Data – Hiding ?

Provide examples of encapsulation in Java.

Difference between Abstraction & Encapsulation ?

You might also like