Java: Full lesson content. # JAR > Understanding Java Archive (JAR) files JAR (Java Archive) is a package file format used to aggregate multiple Java class files, associated metadata, and resources (text, images, etc.) into one file for distribution. ## What is a JAR file? [Section titled “What is a JAR file?”](#what-is-a-jar-file) A JAR file is essentially a ZIP file with a `.jar` extension that contains compiled Java classes and resources needed for a Java application or library. ## Creating JAR files [Section titled “Creating JAR files”](#creating-jar-files) The basic syntax for creating a JAR file using the command line: ```bash jar cf jar-file input-files ``` Where: * `c` indicates you want to create a new archive * `f` specifies the archive filename * `jar-file` is the name you want to give your JAR file * `input-files` are the files you want to include Example: ```bash jar cf myProgram.jar *.class ``` ## The Manifest file [Section titled “The Manifest file”](#the-manifest-file) JAR files can include a special META-INF/MANIFEST.MF file that contains metadata about the JAR: ```plaintext Manifest-Version: 1.0 Main-Class: com.example.MainClass ``` To create a JAR with a manifest: ```bash jar cfm myProgram.jar manifest.txt *.class ``` ## Executable JAR files [Section titled “Executable JAR files”](#executable-jar-files) To create an executable JAR: 1. Create a manifest file with Main-Class specified 2. Include the manifest when creating the JAR Example manifest (manifest.txt): ```plaintext Main-Class: com.example.MainClass ``` Creating the executable JAR: ```bash jar cfm myProgram.jar manifest.txt *.class ``` Running the JAR: ```bash java -jar myProgram.jar ``` ## Viewing JAR Contents [Section titled “Viewing JAR Contents”](#viewing-jar-contents) To list the contents of a JAR file: ```bash jar tf myProgram.jar ``` ## Extracting JAR Contents [Section titled “Extracting JAR Contents”](#extracting-jar-contents) To extract the contents of a JAR file: ```bash jar xf myProgram.jar ``` # Scanner > Using the Scanner class for input in Java The Scanner class in Java is used to get user input from various sources including the console (keyboard), files, and strings. ## Basic Usage [Section titled “Basic Usage”](#basic-usage) To use the Scanner class, you first need to import it: ```java import java.util.Scanner; ``` Then create a Scanner object: ```java // Create a Scanner object for console input Scanner scanner = new Scanner(System.in); ``` ## Reading Different Types of Input [Section titled “Reading Different Types of Input”](#reading-different-types-of-input) ### Reading Strings [Section titled “Reading Strings”](#reading-strings) ```java System.out.print("Enter your name: "); String name = scanner.nextLine(); // Reads a line of text ``` ### Reading Integers [Section titled “Reading Integers”](#reading-integers) ```java System.out.print("Enter your age: "); int age = scanner.nextInt(); // Reads an integer ``` ### Reading Floating Point Numbers [Section titled “Reading Floating Point Numbers”](#reading-floating-point-numbers) ```java System.out.print("Enter your height in meters: "); double height = scanner.nextDouble(); // Reads a double ``` ### Reading a Single Word [Section titled “Reading a Single Word”](#reading-a-single-word) ```java System.out.print("Enter a word: "); String word = scanner.next(); // Reads until whitespace ``` ## Important Methods [Section titled “Important Methods”](#important-methods) | Method | Description | | --------------- | ------------------------------------ | | `nextLine()` | Reads a line of text (until newline) | | `next()` | Reads the next token (word) | | `nextInt()` | Reads the next token as an int | | `nextDouble()` | Reads the next token as a double | | `nextBoolean()` | Reads the next token as a boolean | | `hasNext()` | Returns true if more tokens exist | | `hasNextLine()` | Returns true if more lines exist | ## Common Issues [Section titled “Common Issues”](#common-issues) ### Mixing nextLine() with other next methods [Section titled “Mixing nextLine() with other next methods”](#mixing-nextline-with-other-next-methods) When you use `nextInt()` or other non-line methods followed by `nextLine()`, you may encounter issues because `nextInt()` doesn’t consume the newline character: ```java // Issue example int number = scanner.nextInt(); // User enters "42" and presses Enter String text = scanner.nextLine(); // This immediately returns empty string! ``` Solution: ```java // Solution int number = scanner.nextInt(); // User enters "42" and presses Enter scanner.nextLine(); // Consume the leftover newline String text = scanner.nextLine(); // Now this waits for user input ``` ## Closing the Scanner [Section titled “Closing the Scanner”](#closing-the-scanner) It’s good practice to close the Scanner when you’re done with it: ```java scanner.close(); ``` ## Reading from Files [Section titled “Reading from Files”](#reading-from-files) You can also use Scanner to read from files: ```java import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; public class ReadFile { public static void main(String[] args) { try { File file = new File("example.txt"); Scanner fileScanner = new Scanner(file); while (fileScanner.hasNextLine()) { String line = fileScanner.nextLine(); System.out.println(line); } fileScanner.close(); } catch (FileNotFoundException e) { System.out.println("File not found"); e.printStackTrace(); } } } ``` # Business Concept > Understanding business concepts and their application in Java programming Business concepts in Java programming refer to how you model real-world business entities, processes, and rules in your applications. ## Domain-Driven Design (DDD) [Section titled “Domain-Driven Design (DDD)”](#domain-driven-design-ddd) Domain-Driven Design is an approach to software development that focuses on understanding the business domain and creating a model that reflects it. ### Key Elements of DDD [Section titled “Key Elements of DDD”](#key-elements-of-ddd) * **Entities**: Objects with a distinct identity (e.g., Customer, Order) * **Value Objects**: Objects defined by their attributes (e.g., Address, Money) * **Aggregates**: Clusters of entities and value objects treated as a unit * **Repositories**: Objects that handle persistence of aggregates * **Services**: Business operations that don’t naturally belong to entities ## Business Objects in Java [Section titled “Business Objects in Java”](#business-objects-in-java) ```java // Entity example public class Customer { private UUID id; private String name; private String email; private List orders; // Constructor, getters, setters, business methods } // Value object example public class Address { private final String street; private final String city; private final String zipCode; // Immutable, equals/hashCode based on all fields } ``` ## Business Logic Implementation [Section titled “Business Logic Implementation”](#business-logic-implementation) ### Service Layer [Section titled “Service Layer”](#service-layer) ```java public class OrderService { private OrderRepository orderRepository; private CustomerRepository customerRepository; private PaymentGateway paymentGateway; public Order placeOrder(UUID customerId, List items, PaymentDetails payment) { // Business logic for placing an order Customer customer = customerRepository.findById(customerId); Order order = new Order(customer, items); boolean paymentSuccessful = paymentGateway.processPayment(payment, order.getTotalAmount()); if (paymentSuccessful) { order.setStatus(OrderStatus.PAID); orderRepository.save(order); return order; } else { throw new PaymentFailedException("Payment could not be processed"); } } } ``` ## Business Rules [Section titled “Business Rules”](#business-rules) Business rules can be implemented in various ways: ### 1. Within Entity Methods [Section titled “1. Within Entity Methods”](#1-within-entity-methods) ```java public class Order { // Properties public void addItem(Product product, int quantity) { // Business rule: Cannot add out-of-stock items if (!product.isInStock(quantity)) { throw new InsufficientStockException(); } OrderItem item = new OrderItem(product, quantity); items.add(item); recalculateTotal(); } } ``` ### 2. Using the Specification Pattern [Section titled “2. Using the Specification Pattern”](#2-using-the-specification-pattern) ```java public interface OrderSpecification { boolean isSatisfiedBy(Order order); } public class CanBeShippedSpecification implements OrderSpecification { public boolean isSatisfiedBy(Order order) { return order.getStatus() == OrderStatus.PAID && order.getItems().stream().allMatch(item -> item.getProduct().isInStock(item.getQuantity())); } } ``` ## Transaction Script Pattern [Section titled “Transaction Script Pattern”](#transaction-script-pattern) For simple applications, business logic can be organized in transaction scripts: ```java public class InvoiceService { private final DataSource dataSource; public Invoice generateMonthlyInvoice(int customerId, int month, int year) { try (Connection conn = dataSource.getConnection()) { // Get customer data Customer customer = getCustomer(conn, customerId); // Get usage data for billing period List usageRecords = getUsageRecords(conn, customerId, month, year); // Calculate charges BigDecimal total = calculateCharges(usageRecords, customer.getPricingPlan()); // Create invoice Invoice invoice = new Invoice(customer, month, year, total); // Save invoice saveInvoice(conn, invoice); return invoice; } catch (SQLException e) { throw new InvoiceGenerationException("Failed to generate invoice", e); } } // Helper methods... } ``` ## Best Practices [Section titled “Best Practices”](#best-practices) 1. **Separate business logic from infrastructure concerns** 2. **Make business rules explicit** rather than implicit 3. **Use a ubiquitous language** shared by developers and domain experts 4. **Keep business logic testable** with unit tests 5. **Design for change** as business rules frequently evolve 6. **Document business rules** with comments and documentation # JDBC > Java Database Connectivity - Connecting Java applications to databases JDBC (Java Database Connectivity) is an API for connecting Java applications to relational databases. It provides methods for querying and updating data in a database. ## Setting up JDBC [Section titled “Setting up JDBC”](#setting-up-jdbc) ### 1. Import packages [Section titled “1. Import packages”](#1-import-packages) ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; ``` ### 2. Load and register the JDBC driver [Section titled “2. Load and register the JDBC driver”](#2-load-and-register-the-jdbc-driver) ```java Class.forName("com.mysql.cj.jdbc.Driver"); ``` ### 3. Establish a connection [Section titled “3. Establish a connection”](#3-establish-a-connection) ```java String url = "jdbc:mysql://localhost:3306/myDatabase"; String username = "user"; String password = "password"; Connection connection = DriverManager.getConnection(url, username, password); ``` ## Common JDBC Interfaces [Section titled “Common JDBC Interfaces”](#common-jdbc-interfaces) * **Connection**: Represents a connection to the database * **Statement**: Used to execute SQL queries * **PreparedStatement**: Precompiled SQL statement that can be parameterized * **CallableStatement**: Used to execute stored procedures * **ResultSet**: Contains the results of a query ## Executing SQL Statements [Section titled “Executing SQL Statements”](#executing-sql-statements) ### SELECT Queries [Section titled “SELECT Queries”](#select-queries) ```java Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM users"); while (resultSet.next()) { int id = resultSet.getInt("id"); String name = resultSet.getString("name"); System.out.println(id + ": " + name); } ``` ### INSERT, UPDATE, DELETE Statements [Section titled “INSERT, UPDATE, DELETE Statements”](#insert-update-delete-statements) ```java Statement statement = connection.createStatement(); int rowsAffected = statement.executeUpdate("INSERT INTO users(name, email) VALUES('John', 'john@example.com')"); System.out.println(rowsAffected + " row(s) inserted"); ``` ## Using PreparedStatement [Section titled “Using PreparedStatement”](#using-preparedstatement) PreparedStatements help prevent SQL injection and improve performance: ```java String sql = "INSERT INTO users(name, email) VALUES(?, ?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "John"); preparedStatement.setString(2, "john@example.com"); preparedStatement.executeUpdate(); ``` ## Transaction Management [Section titled “Transaction Management”](#transaction-management) ```java try { // Disable auto-commit connection.setAutoCommit(false); // Execute multiple statements Statement statement = connection.createStatement(); statement.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE id = 1"); statement.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE id = 2"); // Commit the transaction connection.commit(); } catch (SQLException e) { // Rollback in case of error connection.rollback(); e.printStackTrace(); } finally { // Re-enable auto-commit connection.setAutoCommit(true); } ``` ## Closing Resources [Section titled “Closing Resources”](#closing-resources) Always close JDBC resources to prevent memory leaks: ```java try { if (resultSet != null) resultSet.close(); if (statement != null) statement.close(); if (connection != null) connection.close(); } catch (SQLException e) { e.printStackTrace(); } ``` Using try-with-resources (Java 7+): ```java try ( Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM users") ) { while (resultSet.next()) { // Process results } } catch (SQLException e) { e.printStackTrace(); } ``` ## Database Connection Pooling [Section titled “Database Connection Pooling”](#database-connection-pooling) For production applications, connection pooling is recommended: ```java // Using HikariCP (add dependency to your project) HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase"); config.setUsername("user"); config.setPassword("password"); config.setMaximumPoolSize(10); HikariDataSource dataSource = new HikariDataSource(config); Connection connection = dataSource.getConnection(); ``` # Git > Version control basics with Git for Java development Git is a distributed version control system that helps you track changes to your code and collaborate with others. ## Installation [Section titled “Installation”](#installation) ### Windows [Section titled “Windows”](#windows) 1. Download Git from [git-scm.com](https://git-scm.com/download/win) 2. Run the installer with default options 3. Verify installation: `git --version` ### macOS [Section titled “macOS”](#macos) 1. Install with Homebrew: `brew install git` 2. Or download from [git-scm.com](https://git-scm.com/download/mac) 3. Verify installation: `git --version` ### Linux [Section titled “Linux”](#linux) ```bash # Debian/Ubuntu sudo apt update sudo apt install git # Fedora sudo dnf install git # Verify git --version ``` ## Initial Configuration [Section titled “Initial Configuration”](#initial-configuration) Set up your identity: ```bash git config --global user.name "Your Name" git config --global user.email "your.email@example.com" ``` ## Basic Git Commands [Section titled “Basic Git Commands”](#basic-git-commands) ### Creating Repositories [Section titled “Creating Repositories”](#creating-repositories) ```bash # Initialize a new repository git init # Clone an existing repository git clone https://github.com/username/repository.git ``` ### Basic Workflow [Section titled “Basic Workflow”](#basic-workflow) ```bash # Check status git status # Add files to staging git add filename.java # Single file git add . # All files # Commit changes git commit -m "Descriptive message about changes" # View commit history git log ``` ### Working with Branches [Section titled “Working with Branches”](#working-with-branches) ```bash # Create a new branch git branch feature-branch # Switch to a branch git checkout feature-branch # OR git switch feature-branch # Create and switch in one command git checkout -b new-feature # List all branches git branch # Merge a branch into current branch git merge feature-branch ``` ### Remote Repositories [Section titled “Remote Repositories”](#remote-repositories) ```bash # Add a remote git remote add origin https://github.com/username/repository.git # Push changes to remote git push origin main # Pull changes from remote git pull origin main # Fetch changes without merging git fetch origin ``` ## .gitignore [Section titled “.gitignore”](#gitignore) Create a `.gitignore` file to exclude build files and IDE configurations: ## Workflow [Section titled “Workflow”](#workflow) 1. **Create a feature branch** for new work: ```bash git checkout -b feat/user-authentication ``` 2. **Write and test your code** locally 3. **Commit changes** with descriptive messages: ```bash git add src/main/java/com/example/UserAuth.java git commit -m "Implement user authentication with password hashing" ``` 4. **Push changes** to remote repository: ```bash git push origin feat/user-authentication ``` 5. **Create a pull request** (on GitHub/GitLab/etc.) 6. **Review and merge** after approval ## Best Practices [Section titled “Best Practices”](#best-practices) * Commit early and often * Write meaningful commit messages * Use branches for features and fixes * Pull changes frequently to avoid merge conflicts * Review changes before committing * Don’t commit generated files or credentials # IDE Installation > Installing an Integrated Development Environment for Java development An Integrated Development Environment (IDE) provides tools to help you write, debug, and run your Java code efficiently. ## Recommended IDEs [Section titled “Recommended IDEs”](#recommended-ides) ### IntelliJ IDEA Community Edition [Section titled “IntelliJ IDEA Community Edition”](#intellij-idea-community-edition) ![](https://logonoid.com/images/intellij-idea-logo.png) * Free and open-source * Known for intelligent code assistance and robust refactoring tools * Download from [JetBrains website](https://www.jetbrains.com/idea/download/) ### Installation [Section titled “Installation”](#installation) 1. Download the installer from the JetBrains website 2. Run the installer and follow the on-screen instructions 3. Select the appropriate JDK during setup (or install one if needed) 4. Launch IntelliJ and configure initial settings ### Visual Studio Code [Section titled “Visual Studio Code”](#visual-studio-code) ![](https://code.visualstudio.com/assets/images/code-stable.png) * Lightweight editor with Java extensions * Install the following extensions: * Extension Pack for Java * Maven for Java * Debugger for Java * Download from [Visual Studio Code website](https://code.visualstudio.com/) ### Installation [Section titled “Installation”](#installation-1) 1. Download and install VS Code 2. Launch VS Code and navigate to Extensions (Ctrl+Shift+X) 3. Search for and install the Java Extension Pack 4. Configure Java settings as needed ## Online Java Compiler [Section titled “Online Java Compiler”](#online-java-compiler) ![](https://static.onecompiler.com/images/logo/oc_logo_v4_light.svg) You can quickly write, run, and test Java code without installing anything locally by using an online Java compiler. This is useful for experimenting with code snippets or practicing problems on the go. * [OneCompiler](https://onecompiler.com/java) # Java Installation > Installing Java Development Kit (JDK) on different operating systems The Java Development Kit (JDK) provides the tools needed to develop Java applications. This guide covers installation on different operating systems. ## Choosing a JDK [Section titled “Choosing a JDK”](#choosing-a-jdk) There are several JDK distributions available: * **Oracle JDK**: Official Oracle implementation (requires license for commercial use) * **OpenJDK**: Free, open-source implementation * **AdoptOpenJDK/Eclipse Temurin**: Community-maintained, production-ready OpenJDK builds For beginners, **Eclipse Temurin** (formerly AdoptOpenJDK) is recommended due to its ease of installation and long-term support. ## Windows [Section titled “Windows”](#windows) ### Using the installer [Section titled “Using the installer”](#using-the-installer) 1. Download the JDK installer from [Eclipse Temurin](https://adoptium.net/) 2. Run the installer and follow the installation wizard 3. The installer will set the `JAVA_HOME` environment variable automatically 4. Verify installation by opening Command Prompt and typing: ```plaintext java -version ``` ### Manual environment variable setup (if needed) [Section titled “Manual environment variable setup (if needed)”](#manual-environment-variable-setup-if-needed) 1. Right-click on “This PC” or “My Computer” and select “Properties” 2. Click on “Advanced system settings” 3. Click the “Environment Variables” button 4. Under System Variables, click “New” and add: * Variable name: `JAVA_HOME` * Variable value: Your JDK installation path (e.g., `C:\Program Files\Java\jdk-17`) 5. Edit the “Path” variable and add `%JAVA_HOME%\bin` ## macOS [Section titled “macOS”](#macos) ### Using Homebrew [Section titled “Using Homebrew”](#using-homebrew) 1. Install Homebrew if not already installed: ```plaintext /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" ``` 2. Install OpenJDK: ```plaintext brew install --cask temurin ``` 3. Verify installation: ```plaintext java -version ``` ### Using the installer [Section titled “Using the installer”](#using-the-installer-1) 1. Download the macOS `.pkg` file from [Eclipse Temurin](https://adoptium.net/) 2. Open the downloaded file and follow the installation instructions 3. Verify installation by opening Terminal and typing: ```plaintext java -version ``` ## Linux [Section titled “Linux”](#linux) ### Debian/Ubuntu [Section titled “Debian/Ubuntu”](#debianubuntu) ```bash sudo apt update sudo apt install openjdk-17-jdk ``` ### Fedora/RHEL [Section titled “Fedora/RHEL”](#fedorarhel) ```bash sudo dnf install java-17-openjdk-devel ``` ### Verify installation [Section titled “Verify installation”](#verify-installation) ```bash java -version ``` ## Multiple Java Versions [Section titled “Multiple Java Versions”](#multiple-java-versions) If you need multiple Java versions, consider using a version manager: * **Windows**: [SDKMAN for Windows](https://sdkman.io/install) (via WSL) * **macOS/Linux**: [SDKMAN](https://sdkman.io/) With SDKMAN, you can install and switch between Java versions: ```bash sdk install java 17.0.2-tem sdk use java 17.0.2-tem ``` ## Verifying Your Installation [Section titled “Verifying Your Installation”](#verifying-your-installation) Create a simple Hello World program to test your installation: 1. Create a file named `HelloWorld.java` with the following content: ```java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, Java!"); } } ``` 2. Compile the program: ```plaintext javac HelloWorld.java ``` 3. Run the program: ```plaintext java HelloWorld ``` If you see “Hello, Java!” printed in the console, your Java installation is working correctly. # Java I > Introduction to Java Welcome to Java I, your first step into the world of programming with one of the most widely used languages in the industry. This subject will take you from the basics of programming concepts to building your first Java applications with object-oriented principles. ## Subject Structure [Section titled “Subject Structure”](#subject-structure) This subject is designed to progressively build your Java skills from the ground up: 1. **Setting up your development environment** - Installing and configuring the tools you’ll need 2. **Understanding programming fundamentals** - Learning the basic building blocks of programming 3. **Mastering object-oriented programming** - Moving from procedural to object-oriented thinking 4. **Building practical applications** - Applying your knowledge with hands-on projects ## Getting Started [Section titled “Getting Started”](#getting-started) We recommend starting with the [IDE Installation](/java-1/environment-tools/ide-installation) guide to set up your development environment, followed by [Java Installation](/java-1/environment-tools/java-installation). Once your environment is ready, you can begin with the [Programming Basics](/java-1/programming-basics/main-method) section. ## Learning Outcomes [Section titled “Learning Outcomes”](#learning-outcomes) By the end of this subject, you will be able to: * Write and execute basic Java programs * Apply object-oriented programming principles * Create applications that interact with users via the command line * Work with databases using JDBC * Implement practical business logic in your applications Let’s start your journey into the world of Java programming! ## Use Cases [Section titled “Use Cases”](#use-cases) Java is a versatile language used across many industries and application domains. Its reliability, scalability, and strong community support make it a top choice for building: * Enterprise web applications * Mobile apps (especially Android) * Financial and banking systems * Big data and analytics platforms * Cloud-based services * Embedded systems ### Companies [Section titled “Companies”](#companies) Many leading organizations rely on Java for their core products and services, including: * Google (Android, backend services) * Amazon (web services, internal tools) * Netflix (streaming platform) * LinkedIn (backend infrastructure) * Uber (scalable backend systems) ## References [Section titled “References”](#references) * [The Java™ Tutorials](https://docs.oracle.com/javase/tutorial/java/index.html) * [Learn Java Programming](https://www.programiz.com/java-programming) * Introduction to Java Programming, Comprehensive Version, 10E by Y. Daniel Liang # Object-Oriented Programming (OOP) > Introduction to Object-Oriented Programming concepts in Java Object-Oriented Programming (OOP) is a programming paradigm based on the concept of “objects”. In Java, OOP is fundamental to the language design and structure. ## Key Concepts [Section titled “Key Concepts”](#key-concepts) * **Classes and Objects**: The basic units of OOP * **Encapsulation**: Hiding implementation details * **Inheritance**: Creating new classes from existing ones * **Polymorphism**: Allowing objects to take multiple forms ## Why OOP? [Section titled “Why OOP?”](#why-oop) OOP allows for: * Code reusability * Modularity * Easier maintenance * Organized code structure # Access Modifiers > Understanding access modifiers in Java Access modifiers control the visibility and accessibility of classes, methods, and fields. ## Types of Access Modifiers [Section titled “Types of Access Modifiers”](#types-of-access-modifiers) | Modifier | Class | Package | Subclass | World | | ----------------------- | ----- | ------- | -------- | ----- | | `public` | Yes | Yes | Yes | Yes | | `protected` | Yes | Yes | Yes | No | | `default` (no modifier) | Yes | Yes | No | No | | `private` | Yes | No | No | No | ## Public [Section titled “Public”](#public) The `public` modifier makes a class, method, or field accessible from any other class: ```java public class User { public String username; public User(String username) { this.username = username; } public void display() { System.out.println(username); } } ``` ## Protected [Section titled “Protected”](#protected) The `protected` modifier makes a method or field accessible within: * The same class * Classes in the same package * Subclasses (even in different packages) ```java public class Person { protected String name; protected void showDetails() { System.out.println("Name: " + name); } } class Student extends Person { public void display() { // Can access protected members from parent showDetails(); System.out.println("Student name: " + name); } } ``` ## Default (Package-Private) [Section titled “Default (Package-Private)”](#default-package-private) When no access modifier is specified, it defaults to “package-private”: * Accessible within the same class and package * Not accessible from outside the package ```java package com.example; class Helper { void utility() { // Implementation } } // In the same package class Main { void method() { Helper helper = new Helper(); helper.utility(); // Accessible } } ``` ## Private [Section titled “Private”](#private) The `private` modifier restricts access to within the same class only: ```java public class BankAccount { private double balance; public BankAccount(double initialAmount) { this.balance = initialAmount; } private void validateTransaction(double amount) { if (amount <= 0) { throw new IllegalArgumentException("Amount must be positive"); } } public void deposit(double amount) { validateTransaction(amount); balance += amount; } public double getBalance() { return balance; } } ``` ## Access Modifiers for Classes [Section titled “Access Modifiers for Classes”](#access-modifiers-for-classes) * Classes can be declared as `public` or with default access (package-private) * `private` and `protected` modifiers are not allowed for top-level classes * Inner classes can use all access modifiers ```java public class PublicClass { // Accessible from anywhere } class PackageClass { // Accessible only within the same package } public class OuterClass { private class PrivateInnerClass { // Accessible only within OuterClass } protected class ProtectedInnerClass { // Accessible within OuterClass, same package, and subclasses of OuterClass } } ``` ## Best Practices [Section titled “Best Practices”](#best-practices) 1. **Encapsulation**: Make fields private and provide public getter/setter methods 2. **Minimize Visibility**: Use the most restrictive access modifier possible 3. **Public APIs**: Carefully design public interfaces as they become part of your API contract 4. **Package Structure**: Organize classes by functionality into packages to leverage package-private access 5. **Protected for Extension**: Use protected for members intended to be accessed or overridden by subclasses # Class > Understanding Java class structure and syntax A class is the blueprint for creating objects, it defines the structure and behavior that objects will have. ## Basic Structure [Section titled “Basic Structure”](#basic-structure) ```java public class ClassName { // Fields (attributes) private int myField; // Constructor public ClassName() { // Initialize fields } // Methods public void myMethod() { // Method implementation } } ``` ### Components [Section titled “Components”](#components) 1. **Class Declaration**: Starts with optional access modifier, followed by the keyword `class` and the class name 2. **Fields**: Variables that belong to the class 3. **Constructors**: Special methods used to initialize objects 4. **Methods**: Functions that define the behavior of the class ### Example [Section titled “Example”](#example) ```java public class Person { // Fields private String name; private int age; // Constructor public Person(String name, int age) { this.name = name; this.age = age; } // Getter methods public String getName() { return name; } public int getAge() { return age; } // Method public void introduceYourself() { System.out.println("Hello, my name is " + name + " and I am " + age + " years old."); } } ``` ## Constructors [Section titled “Constructors”](#constructors) A constructor is a special method in a class that is called when an object is created. * It is used to initialize the object’s fields. * Constructors have the same name as the class and do not have a return type. ```java public class Car { private String model; // Constructor public Car(String model) { this.model = model; } public void showInfo() { System.out.println("Model: " + model); } } // Usage: Car car = new Car("Toyota"); car.showInfo(); // Output: Model: Toyota ``` ## Best Practices [Section titled “Best Practices”](#best-practices) * Class names should start with a capital letter * Follow camelCase naming convention * Keep classes focused on a single responsibility * Properly encapsulate fields using private access and public getter/setter methods # Core Concepts > The OOP concepts used for object-oriented design There are seven fundamental OOP concepts in Java: 1. [Encapsulation](#encapsulation) 2. [Inheritance](#inheritance) 3. [Polymorphism](#polymorphism) 4. [Abstraction](#abstraction) 5. [Association](#association) 6. [Aggregation](#aggregation) 7. [Composition](#composition) ## Encapsulation [Section titled “Encapsulation”](#encapsulation) Encapsulation is the process of bundling data (attributes) and methods (functions) that operate on the data within a single unit, known as a class. It helps protect an object’s internal state by restricting direct access to its attributes and providing controlled access through public methods. Let’s create a simple `BankAccount` class to demonstrate encapsulation: ```java public class BankAccount { private String accountNumber; private double balance; public BankAccount(String accountNumber) { this.accountNumber = accountNumber; this.balance = 0; } public void deposit(double amount) { if (amount > 0) { balance += amount; } } public boolean withdraw(double amount) { if (amount > 0 && balance >= amount) { balance -= amount; return true; } return false; } public double getBalance() { return balance; } } ``` In this example, we encapsulate the accountNumber and balance attributes by making them private. We provide public methods deposit(), withdraw(), and getBalance() to interact with these attributes in a controlled manner. ## Inheritance [Section titled “Inheritance”](#inheritance) Inheritance is the mechanism by which one class can inherit properties (attributes) and methods from another class. This allows developers to create new classes based on existing ones, promoting code reusability and reducing redundancy. Let’s create a simple class hierarchy to demonstrate inheritance: ```java public class Vehicle { private String make; private String model; private int year; public Vehicle(String make, String model, int year) { this.make = make; this.model = model; this.year = year; } public void start() { System.out.println("Starting the vehicle..."); } // Getters and setters } public class Car extends Vehicle { private int numberOfDoors; public Car(String make, String model, int year, int numberOfDoors) { super(make, model, year); this.numberOfDoors = numberOfDoors; } @Override public void start() { System.out.println("Starting the car..."); } // Getters and setters } ``` In this example, we create a Vehicle class and a Car class that inherits from Vehicle. The Car class inherits the attributes and methods from Vehicle and can also define its own, like numberOfDoors. We also override the start() method in the Car class to provide a custom implementation. ## Polymorphism [Section titled “Polymorphism”](#polymorphism) Polymorphism is the ability of an object to take on different forms. In Java, polymorphism allows objects of different classes to be treated as objects of a common superclass. This enables developers to write more flexible and extensible code. Let’s extend our `Vehicle` class hierarchy to demonstrate polymorphism: ```java public class Motorcycle extends Vehicle { private boolean hasSidecar; public Motorcycle(String make, String model, int year, boolean hasSidecar) { super(make, model, year); this.hasSidecar = hasSidecar; } @Override public void start() { System.out.println("Starting the motorcycle..."); } // Getters and setters } public class PolymorphismDemo { public static void main(String[] args) { Vehicle car = new Car("Toyota", "Camry", 2021, 4); Vehicle motorcycle = new Motorcycle("Harley-Davidson", "Sportster", 2021, false); startVehicle(car); startVehicle(motorcycle); } public static void startVehicle(Vehicle vehicle) { vehicle.start(); } } ``` In this example, we create a Motorcycle class that also inherits from Vehicle. In the PolymorphismDemo class, we create instances of Car and Motorcycle and pass them to the startVehicle() method, which accepts a Vehicle parameter. This demonstrates polymorphism, as the startVehicle() method can work with any object that is a subclass of Vehicle. ## Abstraction [Section titled “Abstraction”](#abstraction) Abstraction is the process of hiding the complexity of a system and exposing only the essential features to the user. In Java, abstraction can be achieved using abstract classes and interfaces. Abstract classes are classes that cannot be instantiated and can contain abstract methods (methods without a body). Interfaces define a contract for implementing classes, specifying a set of methods that must be implemented. Let’s create an abstract Animal class and an interface Swimmable to demonstrate abstraction: ```java public abstract class Animal { private String name; public Animal(String name) { this.name = name; } public abstract void makeSound(); // Getters and setters } public interface Swimmable { void swim(); } public class Dog extends Animal { public Dog(String name) { super(name); } @Override public void makeSound() { System.out.println("Woof!"); } } public class Dolphin extends Animal implements Swimmable { public Dolphin(String name) { super(name); } @Override public void makeSound() { System.out.println("Click!"); } @Override public void swim() { System.out.println("The dolphin is swimming..."); } } ``` In this example, we create an abstract Animal class with an abstract method makeSound(). We also create a Swimmable interface with a swim() method. The Dog class extends Animal and provides an implementation for makeSound(). The Dolphin class extends Animal and implements the Swimmable interface, providing implementations for both makeSound() and swim() methods. ## Association [Section titled “Association”](#association) Association is another fundamental principle of OOP that describes the relationship between classes. It represents a general “has-a” or “uses-a” relationship between objects, allowing them to communicate. Association can be unidirectional (one-way) or bidirectional (two-way), depending on whether the relationship is defined in one or both classes. Let’s explore the association principle with an example. Consider a library system with Author and Book classes: ```java public class Author { private String name; public Author(String name) { this.name = name; } // Getters and setters } public class Book { private String title; private Author author; public Book(String title, Author author) { this.title = title; this.author = author; } // Getters and setters } ``` In this example, a Book has an Author object, representing a unidirectional association relationship. The Book class has a reference to the Author class, indicating that a book has an author. However, the Author class does not have any reference to the Book class, so the relationship is one-way. If we want to make the relationship bidirectional, we can modify the Author class to include a list of Book objects: ```java public class Author { private String name; private List books; public Author(String name) { this.name = name; this.books = new ArrayList<>(); } public void addBook(Book book) { books.add(book); } // Getters and setters } ``` Now, the Author class has a list of Book objects, and the relationship between the Author and Book classes is bidirectional. Both classes have references to each other, allowing objects of one class to communicate with objects of the other class. ## Aggregation [Section titled “Aggregation”](#aggregation) Aggregation is a weak form of association that represents a “has-a” or “part-of” relationship between objects. In aggregation, the composed object (whole) can exist independently of its parts, and the whole does not manage the lifetime of the parts. If the whole is destroyed, the parts can still exist. Consider a university system with Department and Professor classes: ```java public class Professor { private String name; public Professor(String name) { this.name = name; } // Getters and setters } public class Department { private String name; private List professors; public Department(String name) { this.name = name; this.professors = new ArrayList<>(); } public void addProfessor(Professor professor) { professors.add(professor); } // Getters and setters } ``` In this example, a Department has a list of Professor objects, representing an aggregation relationship. The Department and Professor objects can exist independently of each other. If a Department is destroyed, the Professor objects can still exist and be associated with other departments. ## Composition [Section titled “Composition”](#composition) A composition is an intense form of association that represents a “has-a” or “part-of” relationship between objects, similar to aggregation. However, in composition, the composed object (entire) is responsible for managing the lifetime of its parts. If the entire is destroyed, its parts are also destroyed. Consider a computer system with Computer and Processor classes: ```java public class Processor { private String model; public Processor(String model) { this.model = model; } // Getters and setters } public class Computer { private String name; private Processor processor; public Computer(String name, String processorModel) { this.name = name; this.processor = new Processor(processorModel); } // Getters and setters } ``` In this example, a Computer has a Processor object, representing a composition relationship. The Computer object is responsible for creating and managing the lifetime of its Processor. If a Computer is destroyed, its Processor object is also destroyed, as it cannot exist independently. # Imports > How to use imports in Java to access classes from other packages Imports allow you to use classes and interfaces from other packages in your Java code without having to use their fully qualified names. ## Basic Import Syntax [Section titled “Basic Import Syntax”](#basic-import-syntax) ```java import package.name.ClassName; // Import a specific class import package.name.*; // Import all classes from a package ``` ## Examples [Section titled “Examples”](#examples) ### Importing a Specific Class [Section titled “Importing a Specific Class”](#importing-a-specific-class) ```java import java.util.ArrayList; public class Example { public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add("Hello"); System.out.println(list); } } ``` ### Importing Multiple Classes [Section titled “Importing Multiple Classes”](#importing-multiple-classes) ```java import java.util.ArrayList; import java.util.HashMap; import java.util.Scanner; public class Example { public static void main(String[] args) { ArrayList list = new ArrayList<>(); HashMap map = new HashMap<>(); Scanner scanner = new Scanner(System.in); } } ``` ### Importing an Entire Package (Wildcard Import) [Section titled “Importing an Entire Package (Wildcard Import)”](#importing-an-entire-package-wildcard-import) To import all classes from a package: ```java import java.util.*; public class Example { public static void main(String[] args) { ArrayList list = new ArrayList<>(); HashMap map = new HashMap<>(); } } ``` ## Java’s Default Imports [Section titled “Java’s Default Imports”](#javas-default-imports) Java automatically imports: * `java.lang.*` package (includes `String`, `System`, `Object`, etc.) * Classes from the current package ```java // These imports are not needed: // import java.lang.String; // import java.lang.System; public class Example { public static void main(String[] args) { String text = "Hello World"; System.out.println(text); } } ``` ## Using Classes Without Import [Section titled “Using Classes Without Import”](#using-classes-without-import) You can use a class without importing it by using its fully qualified name: ```java public class Example { public static void main(String[] args) { java.util.ArrayList list = new java.util.ArrayList<>(); list.add("Hello"); System.out.println(list); } } ``` ## Static Imports [Section titled “Static Imports”](#static-imports) Static imports allow you to access static members of a class without class qualification: ```java import static java.lang.Math.PI; import static java.lang.Math.sqrt; import static java.lang.System.out; public class Example { public static void main(String[] args) { double radius = 5.0; double area = PI * radius * radius; out.println("Area: " + area); out.println("Square root of area: " + sqrt(area)); } } ``` ## Import Rules and Best Practices [Section titled “Import Rules and Best Practices”](#import-rules-and-best-practices) 1. Imports do not include sub-packages 2. You cannot use wildcard imports to import classes from multiple packages 3. If there are naming conflicts, you must use fully qualified names 4. Import statements should appear after the package declaration but before any class declarations 5. Avoid using wildcard imports when only a few classes from a package are needed 6. Most IDEs will automatically manage imports for you ## Naming Conflicts [Section titled “Naming Conflicts”](#naming-conflicts) If two packages have classes with the same name, you need to use fully qualified names for at least one of them: ```java import java.util.Date; public class Example { public static void main(String[] args) { Date utilDate = new Date(); // java.util.Date java.sql.Date sqlDate = new java.sql.Date(0); // java.sql.Date with fully qualified name } } ``` # Method Overloading > Understanding method overloading in Java Method overloading is a feature in Java that allows a class to have multiple methods with the same name but different parameter lists. ## Basic Method Overloading [Section titled “Basic Method Overloading”](#basic-method-overloading) ```java public class Calculator { // Method with two int parameters public int add(int a, int b) { return a + b; } // Method with three int parameters public int add(int a, int b, int c) { return a + b + c; } // Method with two double parameters public double add(double a, double b) { return a + b; } } ``` ## How Overloading Works [Section titled “How Overloading Works”](#how-overloading-works) Method overloading is resolved at compile time based on: 1. Number of parameters 2. Types of parameters 3. Order of parameters The Java compiler selects the most appropriate method to call based on the arguments you provide. ## Overloading Rules [Section titled “Overloading Rules”](#overloading-rules) * Methods must have the same name * Methods must have different parameter lists * Return type alone is not enough to distinguish overloaded methods * Access modifiers don’t affect method overloading ## Valid Overloading Examples [Section titled “Valid Overloading Examples”](#valid-overloading-examples) ```java class Example { void display(int num) { System.out.println("Integer: " + num); } void display(String text) { System.out.println("String: " + text); } void display(int num1, int num2) { System.out.println("Two integers: " + num1 + " and " + num2); } // Different order of parameters void process(int id, String name) { System.out.println("Processing ID: " + id + ", Name: " + name); } void process(String name, int id) { System.out.println("Processing Name: " + name + ", ID: " + id); } } ``` ## Invalid Overloading Examples [Section titled “Invalid Overloading Examples”](#invalid-overloading-examples) ```java class InvalidExample { // Invalid: Only the return type is different int getValue() { return 10; } // double getValue() { return 10.5; } // Won't compile // Valid: Different parameter list double getValue(double multiplier) { return 10 * multiplier; } } ``` ## Automatic Type Promotion [Section titled “Automatic Type Promotion”](#automatic-type-promotion) Java may automatically promote a data type when searching for a matching method: ```java class TypePromotion { void show(int num) { System.out.println("int method: " + num); } void show(double num) { System.out.println("double method: " + num); } public static void main(String[] args) { TypePromotion obj = new TypePromotion(); obj.show(5); // Calls int version obj.show(5.5); // Calls double version obj.show('A'); // Calls int version (char promoted to int) } } ``` ## Overloading vs. Overriding [Section titled “Overloading vs. Overriding”](#overloading-vs-overriding) Don’t confuse overloading with overriding: * **Overloading**: Multiple methods with the same name but different parameters in the same class * **Overriding**: Replacing a method from a parent class with a new implementation in a child class ## Benefits of Method Overloading [Section titled “Benefits of Method Overloading”](#benefits-of-method-overloading) * Improves code readability and reusability * Reduces the need for remembering different method names for similar operations * Allows methods to handle different data types and parameter counts # Object > Understanding objects, object references and memory management in Java An object is an instance of a class, a concrete realization with specific values for the attributes defined in the class which occupies memory. ## Create Object [Section titled “Create Object”](#create-object) ```java // Declaration and initialization Person person = new Person("John", 25); ``` ## Object Reference [Section titled “Object Reference”](#object-reference) In Java, variables of reference types don’t contain the actual object but instead hold a reference (memory address) to where the object is stored. ```java // Creating an object and assigning its reference String text; text = new String("Hello"); ``` ## Garbage Collection [Section titled “Garbage Collection”](#garbage-collection) When an object no longer has any references pointing to it, it becomes eligible for garbage collection: ```java Person person = new Person("John", 25); person = new Person("Jane", 28); // Original "John" object is now unreachable ``` # Packages > Understanding packages and imports in Java Packages in Java are used to organize related classes and interfaces. They provide a namespace for classes and prevent naming conflicts. ### Creating a Package [Section titled “Creating a Package”](#creating-a-package) To declare a package, use the `package` statement at the top of your Java file: ```java package com.company.project; public class MyClass { // Class implementation } ``` ### Package Naming Conventions [Section titled “Package Naming Conventions”](#package-naming-conventions) * Use lowercase letters * Start with your organization’s domain name in reverse (e.g., `com.company.project`) * Package names should be singular * Use meaningful and descriptive names ### Directory Structure [Section titled “Directory Structure”](#directory-structure) Package structure should mirror directory structure: * A class in `package com.company.project` should be in a directory path `/com/company/project/` ## Best Practices [Section titled “Best Practices”](#best-practices) 1. Avoid importing classes with the same name from different packages # Parameters > Understanding method parameters in Java Parameters are variables that are defined in a method’s signature, allowing you to pass data into methods. ## Basic Parameter Usage [Section titled “Basic Parameter Usage”](#basic-parameter-usage) ```java public void greet(String name) { System.out.println("Hello, " + name + "!"); } ``` In this example, `name` is a parameter of type `String`. ## Multiple Parameters [Section titled “Multiple Parameters”](#multiple-parameters) Methods can accept multiple parameters, separated by commas: ```java public int add(int num1, int num2) { return num1 + num2; } ``` ## Parameter Types [Section titled “Parameter Types”](#parameter-types) Parameters can be of any valid Java type: * Primitive types (int, boolean, double, etc.) * Objects (String, ArrayList, custom classes) * Arrays ```java public void processData(int id, String name, double[] values) { // Method body } ``` ## Pass-by-Value [Section titled “Pass-by-Value”](#pass-by-value) Java uses “pass-by-value” semantics for all parameters: * For primitive types, a copy of the actual value is passed * For objects, a copy of the reference is passed ```java public static void main(String[] args) { int x = 10; updateValue(x); System.out.println(x); // Still outputs 10 int[] arr = {1, 2, 3}; updateArray(arr); System.out.println(arr[0]); // Outputs 99 } public static void updateValue(int value) { value = 20; // Only changes the local copy } public static void updateArray(int[] array) { array[0] = 99; // Modifies the actual array object } ``` ## Variable-Length Parameters (Varargs) [Section titled “Variable-Length Parameters (Varargs)”](#variable-length-parameters-varargs) Java supports variable-length parameter lists using `...` syntax: ```java public int sum(int... numbers) { int total = 0; for (int num : numbers) { total += num; } return total; } // Can be called with any number of arguments sum(1, 2); // Returns 3 sum(1, 2, 3, 4, 5); // Returns 15 sum(); // Returns 0 ``` Varargs must be the last parameter in the method signature. ## Final Parameters [Section titled “Final Parameters”](#final-parameters) You can declare parameters as `final` to prevent them from being modified within the method: ```java public void process(final int id) { // id = 100; // This would cause a compilation error System.out.println("Processing ID: " + id); } ``` # Return Types > Understanding method return types in Java Every method in Java must declare a return type, which specifies what kind of value the method will return to the caller. ## Void Return Type [Section titled “Void Return Type”](#void-return-type) When a method doesn’t return any value, use `void`: ```java public void printMessage(String message) { System.out.println(message); // No return statement needed } ``` ## Primitive Return Types [Section titled “Primitive Return Types”](#primitive-return-types) Methods can return any primitive data type: ```java public int add(int a, int b) { return a + b; } public double calculateArea(double radius) { return Math.PI * radius * radius; } public boolean isAdult(int age) { return age >= 18; } public char getFirstCharacter(String text) { if (text != null && text.length() > 0) { return text.charAt(0); } return '\0'; // null character } ``` ## Reference Return Types [Section titled “Reference Return Types”](#reference-return-types) Methods can return objects (reference types): ```java public String formatName(String firstName, String lastName) { return lastName + ", " + firstName; } public Date getCurrentDate() { return new Date(); } public int[] getEvenNumbers(int count) { int[] result = new int[count]; for (int i = 0; i < count; i++) { result[i] = i * 2; } return result; } ``` ## The `return` Statement [Section titled “The return Statement”](#the-return-statement) * The `return` statement exits the method immediately * For non-void methods, a `return` statement with a value is required * Multiple `return` statements are allowed ```java public String getLetterGrade(int score) { if (score >= 90) return "A"; if (score >= 80) return "B"; if (score >= 70) return "C"; if (score >= 60) return "D"; return "F"; } ``` ## Return Type Compatibility [Section titled “Return Type Compatibility”](#return-type-compatibility) The returned value must be compatible with the declared return type: ```java public int getNumber() { return 42; // OK // return 3.14; // Error: double cannot be converted to int // return "42"; // Error: String cannot be converted to int } public Object getObject() { return "Hello"; // OK: String is a subclass of Object // return 42; // OK: autoboxed to Integer which is a subclass of Object } ``` ## Covariant Return Types [Section titled “Covariant Return Types”](#covariant-return-types) When overriding methods, the return type can be a subclass of the original return type: ```java class Animal { } class Dog extends Animal { } class AnimalShelter { public Animal getAnimal() { return new Animal(); } } class DogShelter extends AnimalShelter { @Override public Dog getAnimal() { // Covariant return type return new Dog(); } } ``` ## Common Patterns [Section titled “Common Patterns”](#common-patterns) ### Returning Optional Values [Section titled “Returning Optional Values”](#returning-optional-values) ```java public Optional findUserById(int id) { User user = database.lookup(id); return Optional.ofNullable(user); } ``` ### Chaining Method Calls [Section titled “Chaining Method Calls”](#chaining-method-calls) ```java public class StringBuilder { public StringBuilder append(String str) { // append the string return this; // Return this object for chaining } } // Usage new StringBuilder() .append("Hello") .append(" ") .append("World"); ``` ### Returning Status or Result Objects [Section titled “Returning Status or Result Objects”](#returning-status-or-result-objects) ```java public class Result { private final boolean success; private final String message; private final Object data; // constructor and getters } public Result saveUser(User user) { try { database.save(user); return new Result(true, "User saved successfully", user); } catch (Exception e) { return new Result(false, e.getMessage(), null); } } ``` # Arrays > Working with arrays in Java Arrays are fixed-size containers that store multiple values of the same type. ## Creating Arrays [Section titled “Creating Arrays”](#creating-arrays) ```java // Declaration int[] numbers; // Initialization with size numbers = new int[5]; // Declaration and initialization combined int[] scores = new int[10]; // Declaration, creation and initialization with values String[] names = {"John", "Alice", "Bob"}; ``` ## Accessing Elements [Section titled “Accessing Elements”](#accessing-elements) Array elements are accessed using zero-based indexing: ```java int[] numbers = {10, 20, 30, 40, 50}; // Accessing elements int firstNumber = numbers[0]; // 10 int thirdNumber = numbers[2]; // 30 // Modifying elements numbers[1] = 25; // Changes 20 to 25 ``` ## Array Length [Section titled “Array Length”](#array-length) The length property gives the size of an array: ```java int[] scores = new int[8]; System.out.println(scores.length); // 8 String[] names = {"John", "Alice", "Bob"}; System.out.println(names.length); // 3 ``` ## Iterating [Section titled “Iterating”](#iterating) ```java // Using for loop int[] numbers = {1, 2, 3, 4, 5}; for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); } ``` ## Common Pitfalls [Section titled “Common Pitfalls”](#common-pitfalls) * **Array Index Out of Bounds**: Accessing an index outside the array’s valid range * **NullPointerException**: Using an array reference that hasn’t been initialized * **Fixed Size**: Arrays cannot be resized after creation (use ArrayList for resizable collections) # Data Types > Understanding Java's primitive and reference data types A data type defines the kind of data a variable can hold and how much memory it uses and what operations can be performed on it. Java has two categories of data types: 1. Primitive data types 2. Reference data types ## Primitive Data Types [Section titled “Primitive Data Types”](#primitive-data-types) Primitive types are the basic building blocks and are not objects. | Data Type | Size | Description | Range | Example | | --------- | ------- | ----------------- | ----------------- | ---------------------- | | `byte` | 8 bits | Integer | -128 to 127 | `byte b = 100;` | | `short` | 16 bits | Integer | -32,768 to 32,767 | `short s = 10000;` | | `int` | 32 bits | Integer | -2³¹ to 2³¹-1 | `int i = 100000;` | | `long` | 64 bits | Integer | -2⁶³ to 2⁶³-1 | `long l = 100000L;` | | `float` | 32 bits | Floating-point | \~±3.402… | `float f = 3.14f;` | | `double` | 64 bits | Floating-point | \~±1.797… | `double d = 3.14159;` | | `char` | 16 bits | Unicode character | 0 to 65,535 | `char c = 'A';` | | `boolean` | 1 bit | True/false value | `true` or `false` | `boolean flag = true;` | ### Integer Types [Section titled “Integer Types”](#integer-types) ```java byte smallNumber = 127; short mediumNumber = 32767; int regularNumber = 2147483647; long largeNumber = 9223372036854775807L; // Note the 'L' suffix ``` ### Floating-Point Types [Section titled “Floating-Point Types”](#floating-point-types) ```java float simpleDecimal = 3.14f; // Note the 'f' suffix double preciseDecimal = 3.141592653589793; ``` ### Character Type [Section titled “Character Type”](#character-type) ```java char letter = 'A'; char unicodeChar = '\u00A9'; // Copyright symbol © ``` ### Boolean Type [Section titled “Boolean Type”](#boolean-type) ```java boolean isActive = true; boolean hasPermission = false; ``` ## Reference Data Types [Section titled “Reference Data Types”](#reference-data-types) Reference types are derived from classes and interfaces. ### String [Section titled “String”](#string) ```java String greeting = "Hello, Java!"; String empty = ""; // Empty string String nullString = null; // Null reference ``` ### Arrays [Section titled “Arrays”](#arrays) ```java int[] numbers = {1, 2, 3, 4, 5}; String[] names = new String[3]; names[0] = "Alice"; names[1] = "Bob"; names[2] = "Charlie"; ``` ### Classes and Objects [Section titled “Classes and Objects”](#classes-and-objects) ```java // Define a class class Person { String name; int age; } // Create an object Person person = new Person(); person.name = "John"; person.age = 30; ``` ### Wrapper Classes [Section titled “Wrapper Classes”](#wrapper-classes) Every primitive type has a corresponding wrapper class: | Primitive Type | Wrapper Class | | -------------- | ------------- | | `byte` | `Byte` | | `short` | `Short` | | `int` | `Integer` | | `long` | `Long` | | `float` | `Float` | | `double` | `Double` | | `char` | `Character` | | `boolean` | `Boolean` | ```java Integer wrappedInt = 42; ``` ## Differences [Section titled “Differences”](#differences) | Feature | Primitive Data Types | Reference Data Types | | ----------------- | -------------------------------------- | -------------------------------------------------------- | | Storage | Store actual values directly in memory | Store references (addresses) to objects in memory | | Definition | Predefined by the Java language | Created from classes or interfaces (can be user-defined) | | Size | Fixed size | Size can vary (depends on the object) | | Are they objects? | No | Yes | | Examples | `int`, `double`, `char`, `boolean` | `String`, arrays, all class objects | ## Best Practices [Section titled “Best Practices”](#best-practices) 1. Use the appropriate type for the data you’re storing 2. Use `int` for most integer values unless you need a larger range 3. Use `double` for most floating-point calculations 4. Use wrapper classes when you need to treat primitives as objects 5. Be careful with type conversions to avoid data loss # Decision-Making Statements > Overview of decision-making statements in Java Decision-making statements allow a program to choose different paths of execution based on certain conditions. ## Purposes [Section titled “Purposes”](#purposes) * They are essential for controlling the flow of a program and making it respond to different situations. * To execute different code blocks depending on whether a condition is true or false * To check boolean expressions and control program logic ## How They Work [Section titled “How They Work”](#how-they-work) * A condition or boolean expression is evaluated * If the condition is true, a specific block of code is executed * If the condition is false, another block of code may be executed or skipped ## Common Decision-Making Statements [Section titled “Common Decision-Making Statements”](#common-decision-making-statements) * [If–Else Statement](../if-else) * [Switch Statement](../switch) ## If-Else vs. Switch [Section titled “If-Else vs. Switch”](#if-else-vs-switch) | Feature | If-Else | Switch | | ----------- | ---------------------------------------------------- | ----------------------------------------------- | | Readability | Better for different variables or complex conditions | Better for many conditions on a single variable | | Flexibility | Can check any boolean condition | Limited to equality checks against constants | # If–Else > Working with if-else statements in Java If-else statements in Java allow you to test multiple conditions and execute different code blocks based on which condition is true. ## Basic Syntax [Section titled “Basic Syntax”](#basic-syntax) ```java if (condition1) { // Code executed if condition1 is true } else if (condition2) { // Code executed if condition1 is false and condition2 is true } else { // Code executed if all conditions are false } ``` ## Basic If-Else [Section titled “Basic If-Else”](#basic-if-else) ```java int score = 85; char grade; if (score >= 90) { grade = 'A'; } else if (score >= 80) { grade = 'B'; } else { grade = 'C'; } System.out.println("Grade: " + grade); // Output: Grade: B ``` ## Nested If-Else-If [Section titled “Nested If-Else-If”](#nested-if-else-if) You can nest if-else-if statements inside other if-else-if statements: ```java int age = 25; boolean hasLicense = true; if (age >= 18) { if (hasLicense) { System.out.println("You can drive alone."); } else { System.out.println("You need to get a license first."); } } else if (age >= 16) { System.out.println("You can drive with an adult supervisor."); } else { System.out.println("You are too young to drive."); } ``` ## Logical Operators in Conditions [Section titled “Logical Operators in Conditions”](#logical-operators-in-conditions) You can combine multiple conditions using logical operators: ```java int temperature = 25; boolean isRaining = false; if (temperature > 30 && !isRaining) { System.out.println("Great day for the beach!"); } else if (temperature > 20 || !isRaining) { System.out.println("Good day for outdoor activities."); } else { System.out.println("Better stay indoors today."); } ``` # Loops > Understanding different types of loops in Java Loops allow you to execute a block of code repeatedly. ## For Loop [Section titled “For Loop”](#for-loop) The for loop is used when you know how many times you want to execute a block of code. ```java // Basic for loop for (int i = 0; i < 5; i++) { System.out.println("Count: " + i); } ``` ## While Loop [Section titled “While Loop”](#while-loop) Executes a block of code as long as a condition is true. ```java int count = 0; while (count < 5) { System.out.println("Count: " + count); count++; } ``` ## Do-While Loop [Section titled “Do-While Loop”](#do-while-loop) Similar to while loop, but guarantees at least one execution of the code block. ```java int count = 0; do { System.out.println("Count: " + count); count++; } while (count < 5); ``` ## Loop Control Statements [Section titled “Loop Control Statements”](#loop-control-statements) ### Break [Section titled “Break”](#break) Terminates the loop immediately. ```java for (int i = 0; i < 10; i++) { if (i == 5) { break; // Exit the loop when i is 5 } System.out.println(i); } ``` ### Continue [Section titled “Continue”](#continue) Skips the current iteration and continues with the next iteration. ```java for (int i = 0; i < 10; i++) { if (i % 2 == 0) { continue; // Skip even numbers } System.out.println(i); // Only prints odd numbers } ``` ## Infinite Loops [Section titled “Infinite Loops”](#infinite-loops) An infinite loop is a loop that keeps running forever because the exit condition never becomes true or is missing entirely. This can happen if you forget to update the loop variable, use the wrong condition, or intentionally create a loop that never ends. ```java // Infinite for loop for (;;) { // Code to execute if (someCondition) { break; } } ``` # Main Method > Understanding the main method in Java applications The main method is the entry point for every Java application - it’s where program execution begins. ## Basic Structure [Section titled “Basic Structure”](#basic-structure) ```java public class MyClass { public static void main(String[] args) { // Program execution starts here System.out.println("Hello, World!"); } } ``` ## Main Method Components [Section titled “Main Method Components”](#main-method-components) * `public`: Access modifier making the method accessible from anywhere * `static`: Makes the method accessible without creating an instance of the class * `void`: Return type indicating the method doesn’t return any value * `main`: Method name (must be exactly “main”) * `String[] args`: Command-line arguments passed to the program ## Command-Line Arguments [Section titled “Command-Line Arguments”](#command-line-arguments) The `String[] args` parameter allows passing information to your program when it starts: ```java public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("Argument " + i + ": " + args[i]); } } ``` When executed with: `java MyClass first second third` Output: ```plaintext Argument 0: first Argument 1: second Argument 2: third ``` ## Multiple Main Methods [Section titled “Multiple Main Methods”](#multiple-main-methods) * A Java project can have multiple classes with main methods * The JVM executes the main method in the class specified at runtime * This allows different entry points for different purposes ## Best Practices [Section titled “Best Practices”](#best-practices) * Keep the main method simple and focused on program initialization * Consider extracting logic to separate methods and classes * Use command-line arguments for configuration when appropriate # Methods > Understanding methods in Java Methods are blocks of code that perform specific tasks. They help organize code, enable reuse, and provide abstraction. ## Method Declaration [Section titled “Method Declaration”](#method-declaration) ```java public int calculateSum(int a, int b) { return a + b; } ``` A method declaration includes: * Access modifier (`public`) * Return type (`int`) * Method name (`calculateSum`) * Parameters (`int a, int b`) * Method body (code between curly braces) ## Method Invocation [Section titled “Method Invocation”](#method-invocation) ```java int result = calculateSum(5, 3); // result = 8 ``` ## Static vs. Instance Methods [Section titled “Static vs. Instance Methods”](#static-vs-instance-methods) ### Static Methods [Section titled “Static Methods”](#static-methods) * Belong to the class rather than objects * Called using the class name * Cannot access instance variables directly ```java public class MathHelper { public static int add(int a, int b) { return a + b; } } // Calling a static method int sum = MathHelper.add(5, 3); ``` ### Instance Methods [Section titled “Instance Methods”](#instance-methods) * Belong to objects of the class * Require an instance to be called * Can access instance variables ```java public class Calculator { private int memory; public void store(int value) { memory = value; } public int recall() { return memory; } } // Using instance methods Calculator calc = new Calculator(); calc.store(10); int value = calc.recall(); // value = 10 ``` ## Method Parameters [Section titled “Method Parameters”](#method-parameters) ### Parameter Passing [Section titled “Parameter Passing”](#parameter-passing) * Primitive types are passed by value (a copy is passed) * Objects are passed by reference value (a copy of the reference is passed) ```java public void modifyValues(int number, StringBuilder text) { number = 100; // Only modifies the local copy text.append(" World"); // Modifies the actual object } int n = 5; StringBuilder sb = new StringBuilder("Hello"); modifyValues(n, sb); System.out.println(n); // Still 5 System.out.println(sb); // "Hello World" ``` ## Method Recursion [Section titled “Method Recursion”](#method-recursion) A method that calls itself: ```java public int factorial(int n) { if (n <= 1) { return 1; // Base case } return n * factorial(n - 1); // Recursive case } ``` ## Best Practices [Section titled “Best Practices”](#best-practices) 1. **Single Responsibility**: A method should do one thing well 2. **Descriptive Names**: Method names should clearly describe what they do # Operators > Understanding different types of operators in Java Operators are symbols that perform operations on variables and values. Operators in Java can be classified into 6 categories: 1. Arithmetic Operators 2. Assignment Operators 3. Comparison/Relational Operators 4. Logical Operators 5. Unary Operators 6. Bitwise Operators ## Arithmetic Operators [Section titled “Arithmetic Operators”](#arithmetic-operators) Arithmetic operators are used to perform arithmetic operations on variables and data. | Operator | Description | Example | | -------- | ------------------- | -------------- | | `+` | Addition | `a + b` | | `-` | Subtraction | `a - b` | | `*` | Multiplication | `a * b` | | `/` | Division | `a / b` | | `%` | Modulus (remainder) | `a % b` | | `++` | Increment | `a++` or `++a` | | `--` | Decrement | `a--` or `--a` | ```java int sum = 5 + 3; // 8 int diff = 5 - 3; // 2 int product = 5 * 3; // 15 int quotient = 5 / 2; // 2 (integer division) double exactQuotient = 5.0 / 2.0; // 2.5 int remainder = 5 % 2; // 1 int a = 5; a++; // a is now 6 ++a; // a is now 7 (prefix: increment then use) a--; // a is now 6 ``` ## Assignment Operators [Section titled “Assignment Operators”](#assignment-operators) Assignment operators are used in Java to assign values to variables. | Operator | Description | Example | Equivalent to | | -------- | ------------------- | -------- | ------------- | | `=` | Assignment | `a = b` | `a = b` | | `+=` | Add and assign | `a += b` | `a = a + b` | | `-=` | Subtract and assign | `a -= b` | `a = a - b` | | `*=` | Multiply and assign | `a *= b` | `a = a * b` | | `/=` | Divide and assign | `a /= b` | `a = a / b` | | `%=` | Modulus and assign | `a %= b` | `a = a % b` | ```java int x = 10; x += 5; // x = 15 x -= 3; // x = 12 x *= 2; // x = 24 x /= 3; // x = 8 x %= 5; // x = 3 ``` ## Comparison/Relational Operators [Section titled “Comparison/Relational Operators”](#comparisonrelational-operators) Relational operators are used to check the relationship between two operands. | Operator | Description | Example | | -------- | ------------------------ | -------- | | `==` | Equal to | `a == b` | | `!=` | Not equal to | `a != b` | | `>` | Greater than | `a > b` | | `<` | Less than | `a < b` | | `>=` | Greater than or equal to | `a >= b` | | `<=` | Less than or equal to | `a <= b` | ```java int a = 5; int b = 7; boolean isEqual = (a == b); // false boolean isNotEqual = (a != b); // true boolean isGreater = (a > b); // false boolean isLess = (a < b); // true boolean isGreaterOrEqual = (a >= b); // false boolean isLessOrEqual = (a <= b); // true ``` ## Logical Operators [Section titled “Logical Operators”](#logical-operators) Logical operators are used to check whether an expression is `true` or `false`. | Operator | Description | Example | | -------- | ----------- | ---------- | | `&&` | Logical AND | `a && b` | | `\|\|` | Logical OR | `a \|\| b` | | `!` | Logical NOT | `!a` | ```java boolean a = true; boolean b = false; boolean andResult = a && b; // false boolean orResult = a || b; // true boolean notResult = !a; // false ``` ## Unary Operators [Section titled “Unary Operators”](#unary-operators) Unary operators are used with only one operand. ## Bitwise Operators [Section titled “Bitwise Operators”](#bitwise-operators) Bitwise operators in Java are used to perform operations on individual bits. | Operator | Description | Example | | -------- | -------------------- | --------- | | `&` | Bitwise AND | `a & b` | | `\|` | Bitwise OR | `a \| b` | | `^` | Bitwise XOR | `a ^ b` | | `~` | Bitwise NOT | `~a` | | `<<` | Left shift | `a << n` | | `>>` | Right shift | `a >> n` | | `>>>` | Unsigned right shift | `a >>> n` | ```java int a = 5; // 0101 in binary int b = 3; // 0011 in binary int bitwiseAnd = a & b; // 0001 -> 1 int bitwiseOr = a | b; // 0111 -> 7 int bitwiseXor = a ^ b; // 0110 -> 6 int bitwiseNot = ~a; // 1010 -> -6 (in two's complement) int leftShift = a << 1; // 1010 -> 10 int rightShift = a >> 1; // 0010 -> 2 ``` # Switch > Using switch statements in Java Switch statements in Java provide a cleaner way to handle multiple conditions compared to long if-else-if chains, especially when comparing a single variable against multiple values. ## Basic Syntax [Section titled “Basic Syntax”](#basic-syntax) ```java switch (expression) { case value1: // Code to execute if expression equals value1 break; case value2: // Code to execute if expression equals value2 break; // More cases... default: // Code to execute if expression doesn't match any case } ``` ## Example [Section titled “Example”](#example) ```java int day = 3; String dayName; switch (day) { case 1: dayName = "Monday"; break; case 2: dayName = "Tuesday"; break; default: dayName = "Invalid day"; } System.out.println(dayName); // Output: Wednesday ``` # Variables > Different ways to assign values to variables in Java A **variable** in Java is a named storage location in memory that holds a value which can be changed during program execution. Variables allow you to store, retrieve, and manipulate data in your programs. ### Properties [Section titled “Properties”](#properties) * Has a specific data type (e.g., `int`, `double`, `String`) * Has a name (identifier) * Can store a value (which may change during program execution) * Has a scope (where it can be accessed in the code) ### Declaration vs. Definition [Section titled “Declaration vs. Definition”](#declaration-vs-definition) | Term | Description | Example | | ----------- | --------------------------------------------------------------------------------------------- | ------------- | | Declaration | Introducing a variable’s name and type to the compiler, without necessarily assigning a value | `int x;` | | Definition | Both declaring a variable and assigning it an initial value | `int x = 10;` | ## Basic Assignment [Section titled “Basic Assignment”](#basic-assignment) The basic way to assign a value is with the assignment operator (`=`): ```java // Simple variable declaration and assignment int age = 25; double salary = 75000.50; char grade = 'A'; boolean isActive = true; String name = "John Smith"; ``` ## Assignment with Expressions [Section titled “Assignment with Expressions”](#assignment-with-expressions) You can assign the result of an expression to a variable: ```java int a = 5; int b = 10; int sum = a + b; // sum equals 15 int product = a * b; // product equals 50 double result = (a + b) / 2.0; // result equals 7.5 ``` ## Best Practices [Section titled “Best Practices”](#best-practices) 1. **Initialize variables** when declaring them, unless there’s a specific reason not to 2. **Use meaningful variable names** that describe what the variable represents 3. **Limit variable scope** to where it’s needed 4. **Use `final`** for values that shouldn’t change 5. **Be careful with type conversions** to avoid data loss