Java
Java
INTRODUCTION TO JAVA
Java is a high-level, object-oriented programming language developed by Sun
Microsystems in 1995. It is platform-independent, which means we can write
code once and run it anywhere using the Java Virtual Machine (JVM). Java is
mostly used for building desktop applications, web applications, Android apps,
and enterprise systems.
Key Features of Java
Platform Independent: Java is famous for its Write Once, Run Anywhere
(WORA) feature. This means we can write our Java code once, and it will
run on any device or operating system without changing anything.
Object-Oriented: Java follows the object-oriented programming. This
makes code clean and reusable.
Security: Java does not support pointers, it includes built-in protections to
keep our programs secure from common problems like memory leakage.
Multithreading: Java programs can do many things at the same time using
multiple threads. This is useful for handling complex tasks like processing
transactions.
Just-In-Time (JIT) Compiler: Java uses a JIT compiler. It improves
performance by converting the bytecode into machine readable code at the
time of execution.
COMMENTS IN JAVA
The comments are the notes written inside the code to explain what we are
doing. The comment lines are not executed while we run the program.
Single-line comment:
// This is a comment
Multi-line comment:
/*
This is a multi-line comment.
This is useful for explaining larger sections of code.
*/
JAVA OOP(OBJECT ORIENTED PROGRAMMING) CONCEPTS
Java Object-Oriented Programming (OOPs) is a fundamental concept in Java
that every developer must understand. It allows developers to structure code
using classes and objects, making it more modular, reusable, and scalable.
The core idea of OOPs is to bind data and the functions that operate on it,
preventing unauthorized access from other parts of the code. Java strictly
follows the DRY (Don't Repeat Yourself) Principle, ensuring that common
logic is written once (e.g., in parent classes or utility methods) and reused
throughout the application. This makes the code:
Easier to maintain: Changes are made in one place.
More organized: Follows a structured approach.
Easier to debug and understand: Reduces redundancy and improves
readability.
In this article, we will explore how OOPs works in Java using classes and
objects. We will also dive into its four main pillars of OOPs that
are, Abstraction, Encapsulation, Inheritance, and Polymorphism with
examples.
class Numbers {
// Properties
private int a;
private int b;
// Setter methods
public void setA(int a) { this.a = a; }
public void setB(int b) { this.b = b; }
// Methods
public void sum() { System.out.println(a + b); }
public void sub() { System.out.println(a - b); }
obj.sum();
obj.sub();
}
}
Output
3
-1
It is a simple example showing a class Numbers containing two variables
which can be accessed and updated only by instance of the object created.
Java Class
A Class is a user-defined blueprint or prototype from which objects are
created. It represents the set of properties or methods that are common to all
objects of one type. Using classes, you can create multiple objects with the
same behavior instead of writing their code multiple times. This includes
classes for objects occurring more than once in your code. In general, class
declarations can include these components in order:
Modifiers: A class can be public or have default access (Refer to this for
details).
Class name: The class name should begin with the initial letter capitalized
by convention.
Body: The class body is surrounded by braces, { }.
Java Object
An Object is a basic unit of Object-Oriented Programming that represents real-
life entities. A typical Java program creates many objects, which as you know,
interact by invoking methods. The objects are what perform your code, they
are the part of your code visible to the viewer/user. An object mainly consists
of:
State: It is represented by the attributes of an object. It also reflects the
properties of an object.
Behavior: It is represented by the methods of an object. It also reflects the
response of an object to other objects.
Identity: It is a unique name given to an object that enables it to interact
with other objects.
Method: A method is a collection of statements that perform some specific
task and return the result to the caller. A method can perform some specific
task without returning anything. Methods allow us to reuse the code
without retyping it, which is why they are considered time savers. In Java,
every method must be part of some class, which is different from languages
like C, C++, and Python.
Example
// Java Program to demonstrate
// Use of Class and Objects
// Class Declared
public class Employee {
// Instance variables (non-static)
private String name;
private float salary;
// Constructor
public Employee(String name, float salary) {
this.name = name;
this.salary = salary;
}
// getters method
public String getName() { return name; }
public float getSalary() { return salary; }
// setters method
public void setName(String name) { this.name = name; }
public void setSalary(float salary) { this.salary = salary; }
// Instance method
public void displayDetails() {
System.out.println("Employee: " + name);
System.out.println("Salary: " + salary);
}
Output
Employee: Geek
Salary: 10000.0
Note: For more information, please refer to the article - Classes and Object.
class Main {
public static void main(String[] args) {
// Proper initialization
Student obj = new Student(28, "Geek");
// Method with parameter
obj.printStudent("Student Details:");
}
}
Output
Student Details:
ID: 28
Name: Geek
1. Abstraction
Data Abstraction is the property by virtue of which only the essential details
are displayed to the user. The trivial or non-essential units are not displayed to
the user. Data Abstraction may also be defined as the process of identifying
only the required characteristics of an object, ignoring the irrelevant details.
The properties and behaviors of an object differentiate it from other objects of
similar type and also help in classifying/grouping the object.
Real-life Example: Consider a real-life example of a man driving a car. The
man only knows that pressing the accelerators will increase the car speed or
applying brakes will stop the car, but he does not know how on pressing the
accelerator, the speed is actually increasing. He does not know about the inner
mechanism of the car or the implementation of the accelerators, brakes etc. in
the car. This is what abstraction is.
Note: In Java, abstraction is achieved by interfaces and abstract classes. We
can achieve 100% abstraction using interfaces.
Example:
// Abstract class representing a Vehicle (hiding implementation details)
abstract class Vehicle {
// Abstract methods (what it can do)
abstract void accelerate();
abstract void brake();
// Concrete method (common to all vehicles)
void startEngine() {
System.out.println("Engine started!");
}
}
class Employee {
// Private fields (encapsulated data)
private int id;
private String name;
// Setter methods
public void setId(int id) {
this.id = id;
}
// Getter methods
public int getId() {
return id;
}
// Using getters
System.out.println("Employee ID: " + emp.getId());
System.out.println("Employee Name: " + emp.getName());
}
}
Output
Employee ID: 101
Employee Name: Geek
Note: To learn more about topic refer to Encapsulation in Java article.
3. Inheritance
Inheritance is an important pillar of OOP (Object Oriented Programming). It is
the mechanism in Java by which one class is allowed to inherit the features
(fields and methods) of another class. We are achieving inheritance by
using extends keyword. Inheritance is also known as "is-a" relationship.
Let us discuss some frequently used important terminologies:
Superclass: The class whose features are inherited is known as superclass
(also known as base or parent class).
Subclass: The class that inherits the other class is known as subclass (also
known as derived or extended or child class). The subclass can add its own
fields and methods in addition to the superclass fields and methods.
Reusability: Inheritance supports the concept of "reusability", i.e. when we
want to create a new class and there is already a class that includes some of
the code that we want, we can derive our new class from the existing class.
By doing this, we are reusing the fields and methods of the existing class.
Example:
// Superclass (Parent)
class Animal {
void eat() {
System.out.println("Animal is eating...");
}
void sleep() {
System.out.println("Animal is sleeping...");
}
}
Output
Animal is eating...
Animal is sleeping...
Dog is barking!
Note: To learn more about topic refer to Inheritance in Java article.
4. Polymorphism
It refers to the ability of object-oriented programming languages to
differentiate between entities with the same name efficiently. This is done by
Java with the help of the signature and declaration of these entities. The ability
to appear in many forms is called polymorphism.
Example:
sleep(1000) //millis
sleep(1000,2000) //millis,nanos
Types of Polymorphism
Polymorphism in Java is mainly of 2 types as mentioned below:
1. Method Overloading
2. Method Overriding
Method Overloading and Method Overriding
1. Method Overloading: Also, known as compile-time polymorphism, is the
concept of Polymorphism where more than one method share the same name
with different signature(Parameters) in a class. The return type of these
methods can or cannot be same.
2. Method Overriding: Also, known as run-time polymorphism, is the concept
of Polymorphism where method in the child class has the same name, return-
type and parameters as in parent class. The child class provides the
implementation in the method already written.
Below is the implementation of both the concepts:
// Java Program to Demonstrate
// Method Overloading and Overriding
// Parent Class
class Parent {
// Overloaded method (compile-time polymorphism)
public void func() {
System.out.println("Parent.func()");
}
// Child Class
class Child extends Parent {
// Overrides Parent.func(int) (runtime polymorphism)
@Override
public void func(int a) {
System.out.println("Child.func(int): " + a);
}
}
// Polymorphism in action
polymorphicObj.func(30);
}
}
Output
Parent.func()
Parent.func(int): 10
Child.func(int): 20
Child.func(int): 30
1. Simple
2. Object-Oriented
3. Distributed
4. Compiled and Interpreted
5. Robust
6. Secure
7. Architecture-Neutral
8. Portable
9. High Performance
10.Multithreaded
11.Dynamic
1. Simple
2. Object-Oriented
Everything in Java revolves around objects and classes.
Java allows you to model real-world entities (like a car or a bank account)
as objects in your program, making it easier to manage and build complex
applications.
Key Object-Oriented Programming (OOP) concepts include:
o Object: An instance of a class.
o Class: A blueprint for creating objects.
o Inheritance: Allows one class to inherit the properties of another.
o Polymorphism: The ability of objects to take on multiple forms.
o Abstraction: Hides the complex details and shows only the
essentials.
o Encapsulation: Keeps the data safe by restricting access to it.
3. Distributed
5. Robust
6. Secure
Java does not use pointers, which helps prevent unauthorized memory
access.
The JVM verifies Java bytecode before execution, ensuring that it adheres
to Java’s security constraints.
Java applications run in a restricted environment (sandbox) that limits
their access to system resources and user data, enhancing security.
7. Architecture-Neutral
Java language and JVM help achieve the goal of “write once; run
anywhere, any time, forever.”
Changes and upgrades in operating systems, processors, and system
resources do not force any changes in Java programs.
8. Portable
9. High Performance
10. Multithreaded
Java can link in new class libraries, methods, and objects dynamically.
Java programs carry substantial amounts of run-time type information,
enabling dynamic linking in a safe and expedient manner.
JVM architecture
JVM (Java Virtual Machine) runs Java applications as a run-time
engine. JVM is the one that calls the main method present in a Java
code. JVM is a part of JRE (Java Runtime Environment). Java
applications are called WORA (Write Once Run Anywhere). This means
a programmer can develop Java code on one system and expect it to run
on any other Java-enabled system without any adjustments. This is all
possible because of the JVM. When we compile a .java file, .class
files (containing byte-code) with the same class names present in
the .java file are generated by the Java compiler. This .class file goes
through various steps when we run it. These steps together describe the
whole JVM.
Architecture of JVM
The image below demonstrates the architecture and key components of
JVM.
Output
Student
getName
setName
getRoll_no
setRoll_no
name
roll_No
Note: For every loaded “.class” file, only one object of the class is
created.
Student s2 = new Student();
// c2 will point to same object where
// c1 is pointing
Class c2 = s2.getClass();
System.out.println(c1==c2); // true
2. Linking: Performs verification, preparation, and (optionally) resolution.
Verification: It ensures the correctness of the .class file i.e. it checks
whether this file is properly formatted and generated by a valid
compiler or not. If verification fails, we get run-time
exception java.lang.VerifyError. This activity is done by the component
ByteCodeVerifier. Once this activity is completed then the class file is
ready for compilation.
Preparation: JVM allocates memory for class static variables and
initializing the memory to default values.
Resolution: It is the process of replacing symbolic references from the
type with direct references. It is done by searching into the method
area to locate the referenced entity.
3. Initialization: In this phase, all static variables are assigned with their
values defined in the code and static block(if any). This is executed from
top to bottom in a class and from parent to child in the class hierarchy. In
general, there are three class loaders:
Bootstrap class loader: Every JVM implementation must have a
bootstrap class loader, capable of loading trusted classes. It loads core
java API classes present in the “JAVA_HOME/lib” directory. This path
is popularly known as the bootstrap path. It is implemented in native
languages like C, C++.
Extension class loader: It is a child of the bootstrap class loader. It
loads the classes present in the extensions directories
“JAVA_HOME/jre/lib/ext”(Extension path) or any other directory
specified by the java.ext.dirs system property. It is implemented in java
by the sun.misc.Launcher$ExtClassLoader class.
System/Application class loader: It is a child of the extension class
loader. It is responsible to load classes from the application classpath.
It internally uses Environment Variable which mapped to
java.class.path. It is also implemented in Java by the
sun.misc.Launcher$AppClassLoader class.
Example:
// Java code to demonstrate Class Loader subsystem
Output
null
jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f
Note: JVM follows the Delegation-Hierarchy principle to load classes.
System class loader delegate load request to extension class loader and
extension class loader delegate request to the bootstrap class loader. If a
class found in the boot-strap path, the class is loaded otherwise request
again transfers to the extension class loader and then to the system class
loader. At last, if the system class loader fails to load class, then we get
run-time exception java.lang.ClassNotFoundException.
2. Class Loaders
There are three primary types of class loaders:
Bootstrap Class Loader: Loads core Java API classes from
the JAVA_HOME/lib directory. It is implemented in native code and is not
a Java object.
Extension Class Loader: Loads classes from
the JAVA_HOME/jre/lib/ext directory or any directory specified by
the java.ext.dirs system property. It is implemented in Java.
System/Application Class Loader: Loads classes from the
application classpath, which is specified by
the java.class.path environment variable. It is also implemented in
Java.
Example:
public class Test {
public static void main(String[] args) {
System.out.println(String.class.getClassLoader());
System.out.println(Test.class.getClassLoader());
}
}
3. JVM Memory Areas
Method area: In the method area, all class level information like class
name, immediate parent class name, methods and variables
information etc. are stored, including static variables. There is only one
method area per JVM, and it is a shared resource.
Heap area: Information of all objects is stored in the heap area. There
is also one Heap Area per JVM. It is also a shared resource.
Stack area: For every thread, JVM creates one run-time stack which is
stored here. Every block of this stack is called activation record/stack
frame which stores methods calls. All local variables of that method are
stored in their corresponding frame. After a thread terminates, its run-
time stack will be destroyed by JVM. It is not a shared resource.
PC Registers: Store address of current execution instruction of a
thread. Obviously, each thread has separate PC Registers.
Native method stacks: For every thread, a separate native stack is
created. It stores native method information.
4. Execution Engine
Execution engine executes the “.class” (bytecode). It reads the byte-code
line by line, uses data and information present in various memory area
and executes instructions. It can be classified into three parts:
Interpreter: It interprets the bytecode line by line and then executes.
The disadvantage here is that when one method is called multiple
times, every time interpretation is required.
Just-In-Time Compiler(JIT): It is used to increase the efficiency of an
interpreter. It compiles the entire bytecode and changes it to native
code so whenever the interpreter sees repeated method calls, JIT
provides direct native code for that part so re-interpretation is not
required, thus efficiency is improved.
Garbage Collector: It destroys un-referenced objects. For more on
Garbage Collector, refer Garbage Collector.
5. Java Native Interface (JNI)
It is an interface that interacts with the Native Method Libraries and
provides the native libraries(C, C++) required for the execution. It enables
JVM to call C/C++ libraries and to be called by C/C++ libraries which may
be specific to hardware.