Java Programming
Java Programming
Example:
class Student {
int roll;
String name;
}
1.2 Encapsulation
1.3 Inheritance
1.4 Polymorphism
1.5 Abstraction
• 1994-1995: Renamed "Java", the focus shifts to the growing World Wide Web.
• May 23, 1995: Java is officially announced at SunWorld, highlighting its "Write Once, Run
Anywhere" (WORA) capability.
• 1996: The first public release, Java Development Kit (JDK) 1.0, is launched, alongside the
HotJava browser.
• Post-1995: Integration into Netscape Navigator boosts its popularity; it expands into applets,
enterprise software, and later mobile (Android).
• Secure: Java runs in a "sandbox" (JVM) and provides strict access control, preventing
malicious code from damaging the host system.
• Portable: The output of the Java compiler is Bytecode, which is not tied to any specific
machine.
• Platform Independent –(WORA): Compiles to bytecode, run on any system with a JVM (Java
Virtual Machine)
• Robust: Emphasizes early error checking (strong typing) and runtime exception handling to
prevent crashes.
• Architecture-Neutral: The code runs on any processor provided a Java Runtime is present.
• Interpreted: The JVM interprets bytecode into native machine code.
• High Performance: Achieved via the JIT (Just-In-Time) compiler, which compiles
frequently used bytecode to native code.
• Dynamic: Java programs carry runtime type information to verify and resolve object access at
runtime.
BYTE CODE:
4. JVM Architecture
The Java Virtual Machine (JVM) is an abstract machine that enables Java bytecode to be
executed.
Components of JVM
The following are the main components of JVM (Java Virtual Machine) architecture:
• Loading: Reads the .class files from the file system, network, or JARs and converts the bytecode into
binary data, storing it in the Method Area. For each loaded file, it creates a Class object in the heap.
o Verification: Ensures the bytecode follows the JVM's rules and security constraints.
o Preparation: Allocates memory for static variables and assigns them default values.
o Resolution: Replaces symbolic references in the bytecode with direct references (actual memory
addresses) in the Method Area.
• Initialization: Assigns the actual values to static variables as defined in the code and executes static
blocks (if any).
There are three built-in class loaders following a delegation hierarchy principle:
• Bootstrap ClassLoader: Loads core Java API classes (e.g., [Link] package) from the [Link] file.
• Extension ClassLoader: Loads classes from the JRE's lib/ext directory.
• Application/System ClassLoader: Loads application-specific classes from the classpath defined by the
user.
These are the memory areas created by the JVM to store data during program execution. Some are
shared across all threads, while others are thread-specific.
• Method Area: Stores class-level data such as class names, parent class information, method data, field
data, and static variables. It is a shared resource. In Java 8 and later, the concept of a permanent
generation (PermGen) was replaced by Metaspace, which is part of non-heap memory.
• Heap Area: This is where all objects and their corresponding instance variables and arrays are stored. It
is shared among all threads and is managed by the Garbage Collector.
• Stack Area: Each thread has a separate runtime stack. For every method call, a new stack frame is
created in the stack, which stores local variables, operand stacks (for intermediate operations), and frame
data (e.g., exception handling information). It is inherently thread-safe.
• PC (Program Counter) Registers: Each thread has a separate PC register that holds the memory
address of the currently executing JVM instruction.
• Native Method Stacks: For every thread, a separate native stack is created to hold information related to
native methods (non-Java code like C/C++) used in the application.
The execution engine is responsible for executing the bytecode, it has three different
components:
• Interpreter: Reads and executes the bytecode instruction by instruction. It is fast at interpreting but slow
in overall execution for repeatedly called methods.
• Just-In-Time (JIT) Compiler: Used to improve performance. It identifies "hotspots" (frequently used
code) and compiles the entire bytecode of those parts into highly optimized, native machine code, which
is then used directly for subsequent calls.
• Garbage Collector (GC): Automatically manages the heap memory by destroying unreferenced objects
and freeing up memory, which helps prevent memory leaks.
Interfaces
• Java Native Interface (JNI): A framework that acts as a bridge to interact with Native Method Libraries. It
enables the JVM to call C/C++ libraries and vice-versa.
• Native Method Libraries: A collection of platform-specific native libraries (written in C, C++) required for
the execution engine.
Primitive data types are predefined in the Java language and represent raw values that are stored directly
in memory.
• boolean:Stores boolean values, either true or false. It's typically used for conditional
logic and is machine-dependent in size, but represents one bit of information.
• byte: An 8-bit signed integer for small numbers, with a range from -128 to 127.
• short: A 16-bit signed integer with a range from -32,768 to 32,767.
• int:A 32-bit signed integer, the most commonly used integer type, with a range from
approximately -2 billion to +2 billion.
• long: A 64-bit signed integer used when the range of int is insufficient.
• float:
A single-precision 32-bit floating-point type for fractional numbers, used for saving
memory in large arrays of floating-point numbers.
• double:
A double-precision 64-bit floating-point type, generally the default choice for
decimal values due to its high precision (up to 15-16 decimal digits).
• char: A single 16-bit Unicode character, with a range from '\u0000' to '\uffff'.
Type Size Description
byte 1 byte Small integer
short 2 bytes Integer
int 4 bytes Default integer
long 8 bytes Large integer
float 4 bytes Decimal
double 8 bytes Precision decimal
char 2 bytes Unicode character
boolean 1 bit true / false
Non-Primitive (Reference) Data Types
Non-primitive data types, also known as reference types, are created by the programmer and refer to the
memory addresses of objects, rather than the actual values themselves.
• Classes: User-defined blueprints from which objects are created. They encapsulate data
(fields) and behavior (methods).
• Arrays: Objects used to store a collection of variables of the same data type (either
primitive or non-primitive).
• Interfaces:
Blueprints of a class that can contain methods and variables, but the methods
are abstract (without implementation).
• String: A sequence of characters. In Java, strings are objects, not primitive types.
6. Variables
Variable represents basic unit of storage in a Java program. In Java, all variables must be declared
before they can be used. The basic form of a variable declaration is shown here:
Example:
In Java, variables are containers for storing data values and must be declared with a specific data type.
They are classified into three primary types based on their declaration location and
scope: local, instance, and static variables.
In Java, variables are containers for storing data values and must be declared with a specific data type.
They are classified into three primary types based on their declaration location and
scope: local, instance, and static variables.
Types of Variables
Variable Scope Lifetime Default Value
Type
Local Inside a Exists only while None (must be initialized before use).
method, the method/block
constructor, or is executing.
block.
1. Local Variables
• Definition: Declared within the body of a method, constructor, or a specific code block.
• Characteristics: They are created when the block is entered and destroyed when it is exited. Their
scope is limited strictly to that block, and they must be explicitly initialized before use. They cannot be
declared using the static keyword.
2. Instance Variables
• Definition: Declared inside a class but outside any method, constructor, or block.
• Characteristics: Each object (instance) of the class gets its own copy of the instance variables. Changes
made to an instance variable in one object do not affect the same variable in another object. Java assigns
a default value if one is not provided.
• Definition: Declared using the static keyword within a class, outside any method, constructor, or block.
• Characteristics: Only one single copy of a static variable exists per class, shared among all instances.
They are created when the class is loaded into memory and can be accessed directly using the class
name (e.g., [Link] ).
Type Conversion and Casting: Assigning a value of one type to a variable of another type.
7. Arrays
An array is a group of variables that are referred to by a common name.
• Arrays of any type can be created and may have one or more dimensions.
One-Dimensional Arrays:
type var-name[ ];
Although this declaration establishes the fact that month_days is an array variable, no array
actually exists. In fact, the value of month_days is set to null, which represents an array with
no value. To link month_days with an actual, physical array of integers, you must allocate
one using new and assign it to month_days. new is a special operator that allocates memory.
• Another version:
It is possible to combine the declaration of the array variable with the allocation of the array
itself, as shown here:
• Another version:
– int month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; Here, we can initialize
arrays in curly braces by separating with comma.
• There is a second form that may be used to declare an array: type[ ] var-name;
• Here, the square brackets follow the type specifier, and not the name of the array variable.
• This alternative declaration form offers convenience when declaring several arrays at the
same time. For example,
– int[] nums, nums2, nums3; // create three arrays creates three array variables of type int.
class Array_Example
int month_days[];
month_days[0] = 31;
month_days[1] = 28;
month_days[2] = 31;
month_days[3] = 30;
month_days[4] = 31;
month_days[5] = 30;
month_days[7] = 31;
month_days[8] = 30;
month_days[9] = 31;
month_days[10] = 30;
month_days[11] = 31;
Multi-Dimension arrays:
To declare a multidimensional array variable, specify each additional index using another set
of square brackets. For example, the following declares a two dimensional
This allocates a 4 by 5 array and assigns it to twoD. Internally this matrix is implemented as
an array of arrays of int.
When you allocate memory for a multidimensional array, you need only specify the memory
for the first (leftmost) dimension. You can allocate the remaining dimensions separately. For
example, this following code allocates memory for the first dimension of twoD when it is
declared. It allocates the second dimension manually.
8. Operators
Java operators are symbols performing operations (like +, -, *, /) on operands (variables/values) and are
categorized into Arithmetic, Assignment, Relational, Logical, Bitwise, Ternary, and others, crucial for
calculations, comparisons, and control flow in programming, with each type having specific uses, such
as + for addition/concatenation, == for equality, && for logical AND, << for left shift, and ? : for conditional
logic, all following a defined precedence order.
• * (Multiplication), / (Division)
• % (Modulus - remainder)
• ++ (Increment), -- (Decrement)
• = (Simple assignment)
• >= (Greater than or equal to), <= (Less than or equal to)
• || (Logical OR)
• ! (Logical NOT)
• << (Left Shift), >> (Right Shift), >>> (Unsigned Right Shift)
Precedence: The order in which operators are evaluated (e.g., * before +).
Bitwise OR ` `
Logical OR `
9. Control Statements
Control structures in Java are mechanisms that dictate the flow of execution in a program based on
conditions or to repeat blocks of code. They fall into three main categories: selection (decision-making),
iteration (looping), and branching.
if (boolean_expression) {
// statements to execute if true
}
• if-else statement: Executes one block if the condition is true, and a different block if it is false.
if (boolean_expression) {
// statements to execute if true
} else {
// statements to execute if false
}
• if-else-if ladder: Checks multiple conditions in sequence, executing the block associated with the
first true condition.
if (condition1) {
// code block 1
} else if (condition2) {
// code block 2
} else {
// code block 3 (if none are true)
}
• switch statement: Allows branching on multiple outcomes by testing a variable against multiple
constant values (cases). It works with integer or character expressions and often uses break statements
to prevent "fall-through" to subsequent cases.
switch (expression) {
case value1:
// statements
break;
case value2:
// statements
break;
default:
// statements (optional)
}
Iteration (Looping) Statements
These structures are used to repeat a block of code multiple times until a certain condition is met.
• while loop: Repeats a statement or block of statements as long as a condition remains true. The
condition is checked before the loop body is executed.
while (boolean_expression) {
// statements to repeat
}
• do-while loop: Similar to the while loop, but it guarantees that the code block executes at least once
before the condition is checked.
do {
// statements to repeat
} while (boolean_expression); // Note the semicolon
• for loop: A concise way to write a loop when the number of iterations is known in advance. It combines
initialization, condition checking, and the step expression in a single line.
java
for (initialization; condition; update) {
// statements to repeat
}
• Enhanced for loop (for-each): Used to iterate over elements of arrays and collections easily.
Branching Statements
These statements alter the flow of control within loops or methods.
• break: Immediately terminates the innermost loop or switch statement and transfers control to the next
statement following the terminated structure.
• continue: Skips the current iteration of a loop and continues with the next iteration.
• return: Exits the current method and returns a value (if the method has a return type other than void).
10. Type Conversion and Casting
Java supports two types of type casting.
Automatic type conversion will take place if the following two conditions are met:
When these two conditions are met, a widening conversion takes place. For example, the int type is
always large enough to hold all valid byte values, so no explicit cast statement is required.
2. Explicit type casting: To create a conversion between two incompatible types, you must use a cast. A
cast is simply an explicit type conversion. It has this general form:
variable=(target-type) value
class Conversion_Example
byte b;
int i = 257;
double d = 323.142;
b = (byte) i;
i = (int) d;
b = (byte) d;
[Link]("d and b " + d + " " + b);
Output:
11. Constructors
In Java, a constructor is a special block of code that is automatically invoked when an object of a class
is created. Its primary purpose is to initialize the object's instance variables to ensure the new object
starts in a valid state.
• No Return Type: Constructors do not have an explicit return type, not even void.
• Automatic Invocation: They are called implicitly when you use the new keyword to instantiate an object
(e.g., MyClass obj = new MyClass(); ).
• Cannot be Abstract, Static, Final, or Synchronized: Constructors cannot use these modifiers.
• Access Modifiers: You can use access modifiers (public, private, protected, default) with constructors to
control object creation from other classes. A common use for a private constructor is in the Singleton
design pattern.
• Overloading is Possible, Overriding is Not: A class can have multiple constructors with different
parameter lists (constructor overloading), but a subclass cannot override a superclass's constructor.
• Inheritance: Constructors are not inherited by subclasses. However, a subclass constructor implicitly or
explicitly calls a superclass constructor using super() (or super(parameters)) as its first statement.
Types of Constructors
Java defines constructors in a few main types:
• Default Constructor: If you don't define any constructor in your class, the Java compiler automatically
provides a public, no-argument default constructor. It initializes all instance variables with default values
(e.g., 0 for int, null for String, false for boolean).
• No-Argument Constructor (No-Arg): This is a constructor you explicitly write that takes no parameters.
Unlike the compiler-generated default constructor, you can put custom initialization logic or other code
inside its body.
• Parameterized Constructor: This constructor accepts one or more parameters. It's used to initialize a
new object with specific, user-defined values at the time of creation, rather than default values.
• Copy Constructor: Java doesn't have a built-in copy constructor like C++, but you can implement one by
creating a constructor that takes an object of the same class as a parameter to copy its field values to a
new instance.
Return Must not have an explicit Must have a return type (or void).
Type return type.
Name Must have the same name as Can have any valid name (though a method can
the class. share the class name, it requires a return type)
12. Methods
A method in Java is a block of code that performs a specific task and only runs when it is called. Methods
provide code reusability and make programs more organized and readable.
java
modifier returnType methodName(parameterList) {
// method body
}
• modifier: Defines the access type (e.g., public, private, protected, or default) and other behaviors
(e.g., static, final, abstract).
• returnType: The data type of the value the method returns. Use the keyword void if the method does
not return a value.
• methodName: A unique identifier for the method. The convention is to use a verb in lowercase, with
subsequent words capitalized (camelCase).
• parameterList: A comma-delimited list of input parameters, each preceded by its data type, enclosed in
parentheses (). If there are no parameters, use empty parentheses.
• method body: Contains the statements and logic to be executed when the method is called, enclosed in
curly braces {}.
Calling a Method
Methods are called by their name.
• Static methods belong to the class and can be called directly using the class name (e.g., [Link](9,
7) or myMethod() within the same class).
• Instance methods belong to an object (instance) of a class and must be called using that object
(e.g., [Link](num1, num2) ).
• Predefined (Standard Library) Methods: These are built-in methods provided within Java's class
libraries, such as [Link]() or [Link]().
• User-defined Methods: These are methods created by the programmer to meet specific requirements of
their application.
• static Methods: Methods that can be called without creating an object of the class. The main method,
the entry point for any Java program, must be static.
o Accessor Methods (Getters): Read the value of instance variables, typically prefixed with get.
o Mutator Methods (Setters): Modify the value of instance variables, typically prefixed with set.
• Abstract Methods: Methods that have a declaration but no implementation (no method body). They are
declared within abstract classes and their implementation is provided by subclasses.
Key Concepts
• Parameters vs. Arguments: Parameters are the variables declared in the method signature, while
arguments are the actual values passed to the method when it is called.
• Method Overloading: This allows a class to have more than one method with the same name, provided
their parameter lists (number or data type of parameters) are different. The compiler differentiates them
based on the arguments passed.
• Memory Management: They get memory only once in the class area at the time of class loading, which
helps in efficient memory use for shared data.
• Shared: A single copy of the static variable is created and shared among all instances (objects) of the
class. If one object changes the value, it is changed for all others.
• Access: They can be accessed directly using the class name ([Link] ) without
requiring an object instance.
• Use Cases: Ideal for counters, constants (like [Link]), or configuration settings that are common to all
objects.
Static Methods
Static methods are functions associated with the class, not a specific object.
• Invocation: They can be invoked without creating an object of the class using the class name
([Link]() ).
• Access Rules:
o They can directly access only static data (variables) and other static methods.
o They cannot directly access non-static (instance) variables or methods because non-static members
belong to an object which might not exist when the static method is called.
o They cannot use the this or super keywords for the same reason.
• Use Cases: Commonly used for utility or helper functions that don't rely on the object's state
(e.g., [Link](), methods in the Math class). The main method must be static as it is the
application's entry point invoked by the JVM before any objects are created.
Static Blocks
A static block (also known as a static initializer block) is a set of statements in a class that is used to
initialize static variables or perform one-time setup operations.
• Execution Timing:
o It executes automatically only once when the class is first loaded into memory by the class loader.
o It runs even before the main() method and before any objects are instantiated.
• Purpose: Primarily used to perform complex initialization logic for static variables that cannot be done in
a single line, such as loading drivers, reading configuration files, or handling exceptions during
initialization.
• Structure: A class can have multiple static blocks, and they execute in the order they appear in the
source code.
java
public class StaticExample {
static String dbUrl;
static {
// This block runs first, for one-time initialization
[Link]("---Inside Static Block---");
dbUrl = "jdbc:mysql://localhost:3306/mydb";
}
Output:
The String class offers many methods for operations like comparison, searching, and extracting parts of
a string. Methods that appear to change a string actually create a new String object. Key methods
include:
StringBuffer methods allow direct modification of the buffer's content, which is more efficient for
extensive string changes than creating new String objects. Some common methods are:
• replace(int start, int end, String str) : Swaps a part of the buffer with another string.
Summary of Differences
Performance Slower for concatenation in Faster for frequent modifications, but slower
loops (creates new objects) than StringBuilder due to synchronization
overhead
Memory Uses String Constant Pool; more Uses Heap memory; more memory-efficient for
memory overhead with frequent modifications
changes
A third class, StringBuilder, offers mutable functionality similar to StringBuffer but is not
synchronized, making it faster and the preferred choice for single-threaded environments.