Develop By : Prof. Uday Shah (HOD - IT)
Introduction to Java and OOP
1. History and Features of Java
-
Java was developed by James Gosling and his team at Sun Microsystems in 1991 and released in 1995.
-
It was initially called Oak and later renamed Java.
-
Java was designed as a platform-independent language for embedded systems.
-
One of Java's key features is its "Write Once, Run Anywhere" capability.
-
Java is object-oriented, which makes programs modular and reusable.
-
It supports automatic memory management through garbage collection.
-
Java has strong security features, making it suitable for web applications.
-
It supports multi-threading for better performance in concurrent applications.
-
Java is robust because of its strong type checking and exception handling.
-
It is widely used in mobile, web, desktop, and enterprise applications.
-
Java continues to evolve with regular updates from Oracle.
-
The language is known for its simplicity and portability.
2. Java Virtual Machine (JVM)
-
JVM is a part of the Java Runtime Environment (JRE).
-
It interprets Java bytecode and converts it into machine code for execution.
-
JVM is platform-dependent, but Java bytecode is platform-independent.
-
It provides a secure execution environment for Java programs.
-
JVM manages memory allocation and garbage collection automatically.
-
It loads classes dynamically during program execution.
-
JVM uses Just-In-Time (JIT) compilation to improve performance.
-
It provides stack-based architecture for instruction execution.
-
JVM handles exception management in Java applications.
-
It has different implementations for different operating systems.
-
JVM ensures that programs adhere to Java's security model.
-
Without JVM, Java programs cannot be executed.
3. JDK (Java Development Kit)
-
JDK is a complete software development kit required to develop Java applications.
-
It includes the JRE (Java Runtime Environment) and development tools.
-
The JDK contains the Java compiler (javac
) to compile Java code into bytecode.
-
It also includes tools like javadoc
for documentation and jdb
for debugging.
-
JDK provides libraries, APIs, and other utilities required for development.
-
Different versions of JDK exist (Standard Edition, Enterprise Edition, etc.).
-
It supports both command-line and IDE-based Java development.
-
JDK updates regularly to include new features and security patches.
-
Developers must install JDK to write and run Java applications.
-
JDK includes the Java Archive (JAR) tool for packaging applications.
-
JDK can be installed on various operating systems like Windows, Linux, and macOS.
-
JDK is essential for both beginners and advanced Java developers.
4. JRE (Java Runtime Environment)
-
JRE provides the runtime environment for executing Java applications.
-
It includes the JVM and class libraries necessary for execution.
-
Unlike JDK, JRE does not include development tools like compilers.
-
Users who only need to run Java applications can install JRE instead of JDK.
-
JRE handles class loading, memory management, and security.
-
It includes Java core libraries like java.lang, java.util, etc.
-
JRE is platform-specific but supports platform-independent bytecode.
-
It is essential for running applets, applications, and servlets.
-
JRE is lighter compared to JDK because it lacks development utilities.
-
It supports plug-ins to run Java applications inside web browsers.
-
JRE works closely with the JVM to provide an execution environment.
-
Developers must distribute applications compatible with JRE versions.
5) Java Program Structure
-
A basic Java file contains one public class whose name must match the filename (e.g., Main.java
→ public class Main
).
-
The entry point of a standalone app is the public static void main(String[] args)
method.
-
Code is organized into packages; the optional package
statement must be the first line (before imports).
-
The import
statements allow you to reference classes without fully qualified names.
-
A class typically defines fields (state) and methods (behavior); access is controlled with modifiers like public
, private
, protected
.
-
Comments document code: single-line //
, multi-line /* ... */
, and Javadoc /** ... */
.
-
Constants are commonly declared with static final
and named in UPPER_SNAKE_CASE
.
-
Only one public top‑level class is allowed per .java
file; other top‑level classes in the file must be package‑private.
-
Compilation (javac
) turns .java
into .class
bytecode; execution (java
) runs it on the JVM.
-
The static context (e.g., static
methods/blocks) belongs to the class, not any particular object.
-
Exception handling (try/catch/finally
or throws
) shapes how error conditions are managed.
-
Typical source layout mirrors packages (e.g., com/example/app/Main.java
).
6) Data Types
-
Java has 8 primitive types: byte
, short
, int
, long
, float
, double
, char
, and boolean
.
-
Reference types include classes, arrays, interfaces, and enums; variables hold references, not the objects themselves.
-
Integer types differ by size and range (byte
8‑bit, short
16‑bit, int
32‑bit, long
64‑bit).
-
Floating‑point types float
(single precision) and double
(double precision) follow IEEE‑754.
-
char
is a 16‑bit unsigned UTF‑16 code unit; some Unicode characters need surrogate pairs.
-
boolean
has only true
and false
; it does not convert to numbers.
-
Literals: 123
, 0b1010
, 0xFF
, 1_000
, 3.14
, 'A'
, true
, "text"
, 123L
, 3.14f
.
-
Type casting can be implicit (widening) or explicit (narrowing) with potential precision loss.
-
Primitive variables of fields get default values; local primitives do not—must be initialized.
-
Wrappers (e.g., Integer
) provide object counterparts to primitives for collections and utilities.
-
Overflow/underflow wraps for integers; floating‑point has special values like NaN
and Infinity
.
-
Strings are reference types, immutable, and not primitives (despite special literal syntax).
7) Variables
-
Declared with a type and name; may be initialized at declaration (e.g., int count = 0;
).
-
Scopes: block/local scope (inside {}
), parameter scope (method params), and class scope (fields).
-
Lifetimes: local variables exist while their block executes; objects live until unreachable and collected.
-
Field kinds: instance fields (per object) vs. static
fields (shared by the class).
-
Final variables become constants after first assignment; for object references, the reference can’t change but the object might.
-
Default values apply to fields (0
, false
, null
), not to local variables.
-
Shadowing occurs when a local/parameter name hides a field with the same name; use this
to disambiguate.
-
Parameters are passed by value; for object refs, the reference value is copied (not the object).
-
Naming uses lowerCamelCase; be descriptive and avoid abbreviations that reduce clarity.
-
Varargs (type... args
) allow methods to accept a variable number of arguments.
-
You can group related constants with enum
instead of multiple int
or String
constants.
-
Proper initialization order matters: fields → instance initializers → constructor body.
8) Operators
-
Arithmetic: + - * / %
for numeric types; /
on integers truncates toward zero.
-
Unary: + - ++ -- !
and bitwise complement ~
; prefix/postfix ++/--
differ in evaluation order.
-
Relational: == != < > <= >=
compare primitives; for objects, ==
compares references, not content.
-
Logical: &&
and ||
are short‑circuiting; &
and |
on booleans evaluate both sides.
-
Assignment and compound assignments: =
, +=
, -=
, *=
, etc., with implicit casts.
-
Ternary conditional: condition ? expr1 : expr2
returns one of two expressions.
-
Bitwise/shift: & | ^ << >> >>>
operate on integer types for low‑level manipulation.
-
instanceof checks type compatibility at runtime (works with classes, interfaces, and null‑safe patterning in newer Java).
-
Precedence/associativity determine evaluation order; parentheses improve readability and correctness.
-
Be aware of overflow in integer arithmetic; consider Math.addExact
to detect it.
-
String concatenation uses +
; heavy concatenation is more efficient with StringBuilder
.
-
Side effects inside expressions (e.g., i++
in conditions) can reduce clarity—use sparingly.
9) Control Statements
-
Selection: if
, if-else
, and nested conditionals direct flow based on boolean expressions.
-
switch chooses among multiple branches; works with int
, char
, String
, enums; break
prevents fall‑through.
-
Loops: for
, while
, and do-while
repeat blocks while conditions hold.
-
Enhanced for (for (T x : collection)
) iterates over arrays/iterables safely and readably.
-
break exits the nearest loop/switch; continue skips to the next iteration.
-
Labeled break
/continue
can control outer loops in nested scenarios.
-
try/catch/finally handles exceptional control flow and resource cleanup.
-
try-with-resources automatically closes resources implementing AutoCloseable
.
-
return exits a method optionally returning a value; methods declared void
return nothing.
-
Guard clauses (early returns) simplify complex nested conditionals for readability.
-
Favor clear loop invariants and limit mutable state to avoid subtle bugs.
-
Keep conditions side‑effect free when possible to make flow predictable.
10) Arrays
-
Declare with type[] name
; allocate with new type[size]
or initialize with literals {...}
.
-
Indices start at 0
and go to length - 1
; accessing outside throws ArrayIndexOutOfBoundsException
.
-
The length
field (no parentheses) gives the fixed size determined at creation time.
-
Arrays are reference types; assigning or passing them copies the reference, not the contents.
-
Default values fill newly allocated arrays (e.g., 0
, false
, null
for references).
-
Multidimensional arrays are arrays of arrays; inner lengths can differ (jagged arrays).
-
Iterate using classic for
with indices or enhanced for
for simplicity.
-
Use java.util.Arrays
for utilities like sort
, binarySearch
, copyOf
, equals
, and toString
.
-
Cloning (arr.clone()
) makes a shallow copy; deep copies require manual copying of contained objects.
-
Arrays are efficient but have fixed size; prefer ArrayList
when dynamic resizing is needed.
-
Passing arrays to methods allows in‑place mutation; document whether a method mutates inputs.
-
For performance‑critical code, primitive arrays avoid boxing overhead.
11) Introduction to Classes and Objects
-
A class defines a blueprint: fields (state), methods (behavior), constructors, and nested types.
-
An object is an instance of a class created with new
; multiple objects share the class definition.
-
Encapsulation hides implementation details using access modifiers and exposes a clean API.
-
Methods can be overloaded (same name, different parameter lists) to offer varied usage.
-
Class members can be static
(belong to the class) or instance members (belong to each object).
-
Inheritance (extends
) enables code reuse and polymorphism; child classes inherit accessible members.
-
Interfaces (implements
) specify capabilities a class promises to provide.
-
toString
, equals
, and hashCode
should be overridden meaningfully for domain objects.
-
Composition (objects containing other objects) is often preferred over deep inheritance.
-
Objects reside on the heap; references are stored in variables and passed by value.
-
Packages group related classes; visibility rules (public/protected/package/private) control access.
-
Good class design focuses on cohesion, low coupling, and clear responsibilities (e.g., SRP).
12) Constructors
-
Constructors initialize new objects; their name matches the class and they have no return type.
-
If you define no constructor, Java provides a default no‑arg constructor.
-
Parameterized constructors let callers provide initial values for fields.
-
Constructors can be overloaded to support different initialization scenarios.
-
this(...)
invokes another constructor in the same class (must be the first statement).
-
super(...)
calls a superclass constructor (also must be first if used).
-
Initialization order: field initializers → instance initializer blocks → constructor body.
-
Constructors can perform validation and may throw checked/unchecked exceptions.
-
They are not inherited but are invoked in an inheritance chain (superclass first).
-
Access modifiers on constructors control how objects can be created (e.g., private for singletons/factories).
-
Avoid heavy work or leaking this
from constructors (e.g., starting threads that escape partially built objects).
-
Prefer factory methods when naming or caching instances improves clarity/performance.
13) this
Keyword
-
this
refers to the current object whose method or constructor is executing.
-
Use this.field
to distinguish a field from a parameter with the same name.
-
this(...)
calls another constructor in the same class to centralize initialization.
-
Methods can return this
to support fluent APIs or method chaining.
-
Pass this
to another method to provide a reference to the current object.
-
In inner classes, OuterClass.this
names the enclosing instance explicitly.
-
this
is not allowed in a static context because no instance exists.
-
Avoid exposing this
during construction (before the object is fully initialized).
-
Helps clarify intent when accessing members that could be shadowed by locals.
-
Can be captured by lambdas/anonymous classes, but be mindful of lifecycle leaks.
-
Useful for builder patterns where setters return the same instance.
-
In equals/hashCode implementations, this
is the left‑hand operand instance.
14) Abstract Class
-
Declared with abstract
; it cannot be instantiated directly.
-
May contain abstract methods (no body) and concrete methods (with implementations).
-
Used to capture shared state and behavior for related subclasses.
-
Subclasses must implement all inherited abstract methods unless they are abstract themselves.
-
Abstract classes can define constructors for initializing common state.
-
They can have fields, including private ones, enabling encapsulation across a hierarchy.
-
Favor an abstract class when you want partial implementation plus shared code.
-
Compared to interfaces, abstract classes allow state and implemented methods without multiple inheritance.
-
Polymorphism: variables typed as the abstract class can hold any subclass instance.
-
You can combine both: a class can extend an abstract class and implement interfaces.
-
Design carefully to avoid deep, brittle inheritance trees; consider composition when suitable.
-
Keep the abstract surface minimal and stable; evolve via protected hooks/template methods.
15) Wrapper Classes
-
Each primitive has a wrapper: Boolean
, Byte
, Short
, Integer
, Long
, Float
, Double
, Character
.
-
Wrappers make primitives usable in collections and APIs that require objects.
-
Autoboxing converts primitives to wrappers automatically; unboxing does the reverse.
-
Wrapper objects are immutable; operations create new objects, not modify existing ones.
-
Utility methods: parseXxx(String)
, valueOf(String)
, and toString()
convert between text and numbers.
-
Constants like Integer.MAX_VALUE
and MIN_VALUE
expose type limits.
-
compareTo
, compare
, and equals
provide ordering and equality semantics.
-
Be mindful of null when unboxing; NullPointerException
occurs if a null reference is unboxed.
-
Number
is a common superclass for numeric wrappers (except Boolean
and Character
).
-
Performance: boxing/unboxing and object allocation add overhead; use primitives in hot loops.
-
Some wrappers (e.g., Integer
) cache small values (commonly −128 to 127) for reuse.
-
Use wrappers when you need generics, optionality (null
), or methods; prefer primitives otherwise.
:: Best of Luck ::