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