Wednesday, July 30, 2025

Introduction to Java and OOP for MCA and IT Students

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