Java Programming Basics and Concepts
Java Programming Basics and Concepts
Definition: A complete software development kit required for developing Java applications.
Includes:
o JRE (hence includes the JVM)
o Development tools such as javac, javadoc, jdb, and other utilities
Versions: Oracle provides standard and enterprise editions; open-source alternatives like
OpenJDK also exist.
Summary Table:
3. Wrapper Classes
Java is strictly object-oriented, and primitive types (e.g., int, double) are not objects. Wrapper
classes allow primitive types to be treated as objects.
a) Purpose:
c) Example:
Java supports classes defined within other classes or methods, primarily for better encapsulation and
logical grouping.
a) Nested Classes:
All classes defined within another class.
Two main types:
1. Static Nested Class
2. Non-static Inner Class
Type Description
Member Inner Class Non-static, defined at class level
Anonymous Inner Class Class without a name, often used for one-time-use implementations
Local Inner Class Defined within a method or block
Static Nested Class Declared with static keyword; doesn't require enclosing class instance
Example:
class Outer {
private int data = 30;
class Inner {
void msg() { [Link]("Data is " + data); }
}
Use Cases:
Arrays in Java
An array is a container object that holds a fixed number of values of a single type.
2. Initializing an Array
✨ Strings in Java
1. Creating Strings
2. String Methods
[Link]([Link]()); // 13
[Link]([Link]()); // "HELLO, WORLD!"
[Link]([Link](0)); // 'H'
[Link]([Link](0, 5)); // "Hello"
[Link]([Link]("World")); // true
3. String Concatenation
4. Comparing Strings
String a = "Java";
String b = "java";
� 1. String (Immutable)
🔹 Example:
String s = "Hello";
[Link](" World"); // This creates a new string but doesn't assign it
[Link](s); // Output: "Hello"
🔹 Example:
Access Modifiers
Java access modifiers are used to specify the scope of the variables, data members,
methods, classes, or constructors. These help to restrict and secure the access (or,
level of access) of the data.
There are four different types of access modifiers in Java, we have listed them as
follows:
🔐 1. private
class Example {
private int data = 10;
class Example {
int data = 20; // default access
void show() {
[Link]("Default access");
}
}
✅ Use when you want to allow access within the same package only.
👨👩👧 3. protected
Accessible within the same package and also in subclasses (even if they are in different
packages).
class Example {
protected int data = 30;
🌐 4. public
The class which inherits the properties of other is known as subclass (derived class, child class) and
the class whose properties are inherited is known as superclass (base class, parent class).
To implement (use) inheritance in Java, the extends keyword is used. It inherits the properties
(attributes or/and methods) of the base class to the derived class. The word "extends" means to extend
functionalities i.e., the extensibility of the features.
class Super {
.....
.....
.....
.....
Following is an example demonstrating Java inheritance. In this example, you can observe two
classes namely Calculation and My_Calculation.
Using extends keyword, the My_Calculation inherits the methods addition() and Subtraction() of
Calculation class.
Copy and paste the following program in a file with name My_Calculation.java
class Calculation {
int z;
z = x + y;
z = x - y;
z = x * y;
[Link](a, b);
[Link](a, b);
[Link](a, b);
javac My_Calculation.java
java My_Calculation
The sum of the given numbers:30
The difference between the given numbers:10
The product of the given numbers:200
In the given program, when an object to My_Calculation class is created, a copy of the contents of
the superclass is made within it. That is why, using the object of the subclass you can access the
members of a superclass.
The Superclass reference variable can hold the subclass object, but using that variable you can access
only the members of the superclass, so to access the members of both classes it is recommended to
always create reference variable to the subclass.
If you consider the above program, you can instantiate the class as given below. But using the
superclass reference variable ( cal in this case) you cannot call the method multiplication(), which
belongs to the subclass My_Calculation.
Note − A subclass inherits all the members (fields, methods, and nested classes) from its superclass.
Constructors are not members, so they are not inherited by subclasses, but the constructor of the
superclass can be invoked from the subclass.
Java Inheritance: The super Keyword
The super keyword is similar to this keyword. Following are the scenarios where the super keyword
is used.
It is used to differentiate the members of superclass from the members of subclass, if they have same
names.
It is used to invoke the superclass constructor from subclass.
[Link]
[Link]();
Sample Code
This section provides you a program that demonstrates the usage of the super keyword.
In the given program, you have two classes namely Sub_class and Super_class, both have a method
named display() with different implementations, and a variable named num with different values. We
are invoking display() method of both classes and printing the value of the variable num of both
classes. Here you can observe that we have used super keyword to differentiate the members of
superclass from subclass.
Example
Open Compiler
class Super_class {
}
public class Sub_class extends Super_class {
// Instantiating subclass
[Link]();
[Link]();
obj.my_method();
}
}
Compile and execute the above code using the following syntax.
javac Super_Demo
java Super
Output
If a class is inheriting the properties of another class, the subclass automatically acquires the default
constructor of the superclass. But if you want to call a parameterized constructor of the superclass,
you need to use the super keyword as shown below.
super(values);
Sample Code
The program given in this section demonstrates how to use the super keyword to invoke the
parametrized constructor of the superclass. This program contains a superclass and a subclass, where
the superclass contains a parameterized constructor which accepts a integer value, and we used the
super keyword to invoke the parameterized constructor of the superclass.
Copy and paste the following program in a file with the name [Link]
Example
Open Compiler
The List interface provides a listIterator() method that returns an instance of the ListIterator interface.
Methods of ListIterator
The ListIterator interface provides methods that can be used to perform various operations on the elements
of a list.
nextIndex() returns the index of the element that the next() method will return
previousIndex() - returns the index of the element that the previous() method will return
set() - replaces the element returned by either next() or previous() with the specified element
import [Link];
import [Link];
class Main {
// Creating an ArrayList
[Link](1);
[Link](3);
[Link](2);
Run Code
Output
ArrayList: [1, 3, 2]
Next Element: 1
Java LinkedList
The LinkedList class of the Java collections framework provides the functionality
of the linked list data structure (doubly linkedlist).
Next - stores an address of the next element in the list. It is null for the last element
import [Link];
class Main {
// create linkedlist
[Link]("Dog");
[Link]("Cat");
[Link]("Cow");
Run Code
Output
Java TreeSet
The TreeSet class of the Java collections framework provides the functionality of a
tree data structure.
It extends the NavigableSet interface.
Creating a TreeSet
In order to create a tree set, we must import the [Link] package first.
Once we import the package, here is how we can create a TreeSet in Java.
Here, we have created a TreeSet without any arguments. In this case, the elements in TreeSet are sorted
naturally (ascending order).
However, we can customize the sorting of elements by using the Comparator interface. We will learn about it
later in this tutorial.
Methods of TreeSet
The TreeSet class provides various methods that allow us to perform various operations on the set.
addAll() - inserts all the elements of the specified collection to the set
For example,
import [Link];
class Main {
[Link](2);
[Link](4);
[Link](6);
[Link](1);
[Link](evenNumbers);
Run Code
Output
TreeSet: [2, 4, 6]
lower(element) - Returns the greatest element among those elements that are
less than the specified element .
ceiling(element) - Returns the lowest element among those elements that are
greater than the specified element . If the element passed exists in a tree set, it
returns the element passed as an argument.
floor(element) - Returns the greatest element among those elements that are
less than the specified element . If the element passed exists in a tree set, it returns
the element passed as an argument.
3. pollfirst() and pollLast() Methods
pollFirst() - returns and removes the first element from the set
pollLast() - returns and removes the last element from the set
4. headSet(), tailSet() and subSet() Methods
headSet(element, booleanValue)
The headSet() method returns all the elements of a tree set before the
specified element (which is passed as an argument).
The booleanValue parameter is optional. Its default value is false .
If true is passed as a booleanValue , the method returns all the elements before the
specified element including the specified element.
contains() Searches the TreeSet for the specified element and returns a boolean result
Java PriorityQueue
The Java PriorityQueue class is an unbounded priority queue based on a priority heap.
Following are the important points about PriorityQueue −
The elements of the priority queue are ordered according to their natural ordering, or
by a Comparator provided at queue construction time, depending on which
constructor is used.
A priority queue does not permit null elements.
A priority queue relying on natural ordering also does not permit insertion of non-
comparable objects.
Class declaration
Parameters
Class constructors
[Link]. Constructor & Description
PriorityQueue()
1 This creates a PriorityQueue with the default initial capacity (11) that
orders its elements according to their natural ordering.
PriorityQueue(int initialCapacity)
3 This creates a PriorityQueue with the specified initial capacity that orders
its elements according to their natural ordering.
Class methods
[Link]. Method & Description
boolean add(E e)
1
This method inserts the specified element into this priority queue.
void clear()
2
This method removes all of the elements from this priority queue.
boolean contains(Object o)
4
This method returns true if this queue contains the specified element.
Iterator<E> iterator()
6
This method returns an iterator over the elements in this queue.
boolean offer(E e)
7
This method inserts the specified element into this priority queue.
boolean remove(Object o)
8
This method removes a single instance of the specified element from
this queue, if it is present.
boolean removeAll(Collection<?> c)
9
This method removes all of this collection's elements that are also
contained in the specified collection (optional operation).
boolean retainAll(Collection<?> c)
11
This method retains only the elements in this collection that are
contained in the specified collection (optional operation).
Spliterator<E> spliterator()
12
This method creates a late-binding and fail-fast Spliterator over the
elements in this queue.
Methods inherited
[Link]
[Link]
[Link]
[Link]
The following example shows the usage of Java PriorityQueue add(E) method to add
Integers. We're adding couple of Integers to the PriorityQueue object using add()
method calls per element and then print each element to show the elements added.
import [Link];
[Link](20);
[Link](30);
[Link](20);
[Link](30);
[Link](15);
[Link](22);
[Link](11);
Let us compile and run the above program, this will produce the following result −
Number = 11
Number = 20
Number = 15
Number = 30
Number = 30
Number = 22
Number = 20
✅ Comparable ([Link])
Example:
@Override
public int compareTo(Student other) {
return [Link] - [Link]; // sort by id
}
}
✅ Comparator ([Link])
Example:
Then:
[Link]=jdbc:mysql://localhost:3306/mydb
[Link]=root
[Link]=12345
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
lambda expressions
Lambda expression is, essentially, an anonymous or unnamed method. The
lambda expression does not execute on its own. Instead, it is used to implement a
method defined by a functional interface.
The new operator ( -> ) used is known as an arrow operator or a lambda operator.
The syntax might not be clear at the moment. Let's explore some examples,
Suppose, we have a method like this:
double getPiValue() {
return 3.1415;
}
() -> 3.1415
Here, the method does not have any parameters. Hence, the left side of the
operator includes an empty parameter. The right side is the lambda body that
specifies the action of the lambda expression. In this case, it returns the value
() -> {
double pi = 3.1415;
return pi;
};
This type of the lambda body is known as a block body. The block body allows the
lambda body to include multiple statements. These statements are enclosed
inside the braces and you have to add a semi-colon after the braces.
Note: For the block body, you can have a return statement if the body returns a
value. However, the expression body does not require a return statement.
// abstract method
double getPiValue();
}
// lambda expression
ref = () -> 3.1415;
Output:
Value of Pi = 3.1415
Inside the Main class, we have declared a reference to MyInterface . Note that we
can declare a reference of an interface but we cannot instantiate an interface.
That is,
MyInterface ref;
Finally, we call the method getPiValue() using the reference interface. When
The life cycle of a thread in Java refers to the various states of a thread goes
through. For example, a thread is born, started, runs, and then dies. Thread
class defines the life cycle and various states of a thread.
New − A new thread begins its life cycle in the new state. It remains in this state until
the program starts the thread. It is also referred to as a born thread.
Runnable − After a newly born thread is started, the thread becomes runnable. A
thread in this state is considered to be executing its task.
Waiting − Sometimes, a thread transitions to the waiting state while the thread waits
for another thread to perform a task. A thread transitions back to the runnable state
only when another thread signals the waiting thread to continue executing.
Timed Waiting − A runnable thread can enter the timed waiting state for a specified
interval of time. A thread in this state transitions back to the runnable state when
that time interval expires or when the event it is waiting for occurs.
Terminated (Dead) − A runnable thread enters the terminated state when it completes
its task or otherwise terminates.
In this example, we're creating two threads by extending the Thread class. We're
printing each state of the thread. When a thread object is created, its state is NEW;
when start() method is called, state is START; when run() method is called, state is
RUNNING; When a thread finished the processing the run() method, it went to
DEAD state.
threadName = name;
if (t == null) {
[Link] ();
[Link]();
[Link]();
}
Output
Java used to offer methods like [Link]() and [Link](), but they are now
deprecated because they could lead to deadlocks and thread starvation.
❗ These methods can leave locks held, and prevent other threads from making progress.
// Simulated task
[Link]("Thread is working...");
try {
[Link](1000);
} catch (InterruptedException e) {
[Link]("Thread interrupted during work.");
return;
}
}
}
✅ Usage:
public class Main {
public static void main(String[] args) throws InterruptedException {
ControlledThread t = new ControlledThread();
[Link]();
[Link](3000);
[Link]();
[Link]("Thread suspended.");
[Link](3000);
[Link]();
[Link]("Thread resumed.");
}
}
❌ 2. Stopping Threads in Java
❗ Stops the thread immediately, potentially leaving shared resources in an inconsistent state.
✅ Usage:
public class Main {
public static void main(String[] args) throws InterruptedException {
StoppableThread t = new StoppableThread();
[Link]();
[Link](2000);
[Link](); // Signal to stop
}
}
✅ Alternative Way: Using interrupt()
class InterruptExample extends Thread {
public void run() {
while (![Link]().isInterrupted()) {
[Link]("Working...");
try {
[Link](500);
} catch (InterruptedException e) {
[Link]("Thread was interrupted!");
break;
}
}
}
}
✅ Usage:
InterruptExample t = new InterruptExample();
[Link]();
[Link](2000);
[Link](); // Gracefully stop
🔒 3. Deadlock in Java
💥 What is Deadlock?
Deadlock happens when two or more threads are waiting for each other to release a resource, and
none of them can proceed.
class B {
synchronized void methodB(A a) {
[Link]("Thread-2: Holding lock on B...");
try { [Link](100); } catch (InterruptedException e) {}
[Link]("Thread-2: Waiting for lock on A...");
[Link](); // tries to get lock on A
}
🛑 Output (Typical):
✅ Preventing Deadlocks
🔐 1. Lock Ordering
class Safe {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
import [Link];
import [Link];
import [Link];
class SafeLock {
private final Lock lock1 = new ReentrantLock();
private final Lock lock2 = new ReentrantLock();
If an exception (like NullPointerException, IOException, etc.) is thrown inside a thread and not
caught, it will terminate that thread—but not the entire program (unless it’s the main thread or
you're relying on the thread to complete a critical task).
The simplest and safest way is to wrap your thread logic in a try-catch block.
2. Use UncaughtExceptionHandler
Java provides a way to catch exceptions that were not caught inside the thread itself using
[Link].
[Link]();
}
}
This is useful for logging or alerting when something goes wrong unexpectedly in background
threads.
try {
[Link](); // this will throw ExecutionException
} catch (ExecutionException e) {
[Link]("Caught: " + [Link]()); // [Link]() gives the
actual exception
} catch (InterruptedException e) {
[Link]().interrupt();
}
[Link](() -> {
throw new RuntimeException("Boom!");
});
🔹 Example:
import [Link].*;
[Link](button);
[Link](300, 200);
[Link](null);
[Link](100, 80, 100, 30);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
🔘 JRadioButton — Radio Button
🔹 Example:
import [Link].*;
[Link](rb1);
[Link](rb2);
[Link](300, 200);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
🔹 Example:
import [Link].*;
[Link](area);
[Link](300, 250);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
🔹 Example:
import [Link].*;
[Link](comboBox);
[Link](300, 200);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
🔹 Example:
import [Link].*;
String[][] data = {
{"101", "Alice", "90"},
{"102", "Bob", "85"},
{"103", "Charlie", "95"}
};
[Link](sp);
[Link](300, 200);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
🔹 Example:
import [Link].*;
import [Link].*;
import [Link].*;
[Link](button);
[Link](label);
[Link](300, 200);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
🔹 Example:
import [Link].*;
[Link](progressBar);
[Link](300, 150);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
// Simulate progress
for (int i = 0; i <= 100; i++) {
try {
[Link](50); // delay
[Link](i);
} catch (InterruptedException e) {
[Link]();
}
}
}
}
🔹 Example:
import [Link].*;
import [Link].*;
JSlider slider = new JSlider(0, 100, 50); // min, max, initial value
[Link](50, 50, 200, 40);
[Link](25);
[Link](true);
[Link](true);
[Link](slider);
[Link](label);
[Link](300, 200);
[Link](null);
[Link](JFrame.EXIT_ON_CLOSE);
[Link](true);
}
}
A layout manager is an object that determines the size and position of components within a
container. It automates the placement of UI components so you don’t have to manually set
setBounds().
[Link](new LayoutManagerType());
NORTH
SOUTH
EAST
WEST
CENTER
🔹 Example:
import [Link].*;
import [Link].*;
[Link](400, 300);
[Link](true);
[Link](JFrame.EXIT_ON_CLOSE);
}
}
🔲 2. GridLayout
Divides container into a grid of rows and columns, and all components get equal size.
🔹 Example:
import [Link].*;
import [Link].*;
[Link](400, 200);
[Link](true);
[Link](JFrame.EXIT_ON_CLOSE);
}
}
➡️ 3. FlowLayout
Places components left to right, like words in a sentence, wrapping to next line as needed. It's the
default for JPanel.
🔹 Example:
import [Link].*;
import [Link].*;
[Link](300, 200);
[Link](true);
[Link](JFrame.EXIT_ON_CLOSE);
}
}
📦 4. BoxLayout
[Link](panel);
[Link](200, 200);
[Link](true);
[Link](JFrame.EXIT_ON_CLOSE);
}
}
🃏 5. CardLayout
Like a deck of cards—only one component is visible at a time. Used in wizards, tabbed UIs, etc.
🔹 Example:
import [Link].*;
import [Link].*;
import [Link].*;
[Link](card1, "Card1");
[Link](card2, "Card2");
[Link](new BorderLayout());
[Link](cardPanel, [Link]);
[Link](switchBtn, [Link]);
[Link](300, 200);
[Link](true);
[Link](JFrame.EXIT_ON_CLOSE);
}
}
🔌 Introduction to JDBC
JDBC (Java Database Connectivity) is an API that enables Java applications to interact with
databases using SQL queries. It acts as a bridge between a Java program and a database.
// 2. Connect to DB
Connection con = [Link](
"jdbc:mysql://localhost:3306/testdb", "root", "yourpassword");
// 3. Create Statement
Statement stmt = [Link]();
// 4. Execute Query
ResultSet rs = [Link]("SELECT * FROM students");
// 5. Process Result
while ([Link]()) {
[Link]([Link](1) + " " + [Link](2));
}
// 6. Close connection
[Link]();
} catch (Exception e) {
[Link](e);
}
}
}
Make sure:
MySQL is running
You have a database named testdb
Table students exists
JDBC driver (mysql-connector-java) is in your classpath
Let’s look at how to do each using PreparedStatement (safer and prevents SQL injection):
3�⃣ Update
PreparedStatement ps = [Link]("UPDATE students SET name=? WHERE
id=?");
[Link](1, "Bob");
[Link](2, 101);
[Link]();
4�⃣ Delete
PreparedStatement ps = [Link]("DELETE FROM students WHERE id=?");
[Link](1, 101);
[Link]();
🔌 Connection Interface
The Connection interface represents a session with a specific database. It's part of [Link].
🔑 Key Methods:
Method Description
You're on a roll! Let's get into Java Networking, especially the key terminology, the Socket classes,
and how to create client-server communication using Socket and ServerSocket.
A logical channel between client and server for communication (e.g., port
Port
80 for HTTP)
Constructor:
Constructor:
🖥� Server Program:
import [Link].*;
import [Link].*;
[Link]();
} catch (Exception e) {
[Link](e);
}
}
}
💻 Client Program:
import [Link].*;
import [Link].*;
[Link]();
[Link]();
[Link]();
} catch (Exception e) {
[Link](e);
}
}
}
️ Pro Tip: Run the server first, then the client, or the client won’t find the server.
Method Description
Method Description
Great! You're covering all the key areas of Java Networking. Let’s break it down:
The URL class in [Link] is used to handle Uniform Resource Locators, like web addresses.
🔹 Example:
import [Link].*;
import [Link].*;
The URLConnection class helps open connections and read data from a URL.
String inputLine;
while ((inputLine = [Link]()) != null) {
[Link](inputLine);
}
[Link]();
}
}
Unlike TCP, UDP is faster but unreliable and uses DatagramSocket and DatagramPacket.
[Link]();
}
}
💻 Client:
import [Link].*;
[Link]();
}
}
💬 Client:
Socket s = new Socket("localhost", 6666);
A Comparator, when provided at the construction of a Java PriorityQueue, defines an explicit ordering rule beyond the natural ordering of elements. It affects the ordering of elements within the queue, allowing for custom priority criteria. If no Comparator is provided, elements are ordered according to their natural ordering.
In a multi-threaded Java application using ExecutorService, exceptions in tasks are not thrown immediately but are wrapped in a Future object. It requires explicitly calling the get() method, which may throw an ExecutionException. This encapsulates the actual cause of the exception, allowing proper handling by accessing e.getCause()
The Java PriorityQueue does not permit null elements as they cannot be compared to existing elements, leading to potential runtime errors. Similarly, objects that do not implement Comparable, or have incompatible comparators, cannot be inserted due to the exception thrown during ordering processes. This ensures the integrity of priority order.
A Layout Manager in Java Swing automates the size and positioning of components within containers, thus removing the need to manually define bounds. This allows for dynamic and flexible UI designs that can more easily adapt to different screen sizes and user interface requirements, improving overall user experience.
Using the deprecated methods Thread.suspend() and Thread.resume() in Java can lead to deadlocks and thread starvation due to leaving locks held, which prevents other threads from making progress. The safer alternative is to use a volatile flag combined with wait() and notify() methods to control thread suspension and resumption safely.
The Comparable interface defines the natural ordering of objects and requires the implementation of the compareTo() method within the object's class. It allows an object to compare itself with another of the same type. The Comparator interface, on the other hand, provides a mechanism for defining order external to the type being ordered, often useful for defining multiple sort sequences.
Deadlock in Java occurs when two or more threads are blocked forever, each holding a lock and waiting for the other to release a lock. It typically happens when threads acquire locks in different orders. An example is when Thread A holds a lock on resource 1 and waits for resource 2, while Thread B holds a lock on resource 2 and waits for resource 1. None of the threads can proceed, leading to a deadlock.
To safely terminate a running thread in Java, using a volatile boolean flag to signal the thread to stop is a recommended strategy. Alternatively, interrupting the thread using the interrupt() method allows a thread to handle graceful termination through checking its interrupted status or catching InterruptedException during blocking operations, avoiding abrupt termination with deprecated stop() method.
To establish a JDBC connection with a MySQL database, follow these steps: 1. Load the JDBC driver using Class.forName() method, 2. Establish a connection with DriverManager.getConnection() providing the database URL, username, and password, 3. Create a Statement object to execute queries, 4. Execute the query using executeQuery() for SELECT statements, 5. Process the ResultSet obtained from the query execution, and 6. Close the connection to free resources.
The TreeSet's floor() method returns the greatest element in the set that is less than or equal to the specified element. If the specified element exists in the set, it returns that element. Otherwise, it returns the greatest element that is less than the specified one.