W6. Introduction to Java, Compilation, JVM, JRE, JDK, Memory Model, OOP Concepts, Classes, Objects

Author

Eugene Zouev, Munir Makhmutov

Published

October 7, 2025

Quiz | Flashcards

1. Summary

1.1 The Landscape of Programming Languages

A software professional should know several programming languages, as there is no single “best” language. Each language is designed for a specific application domain. For example, C is a system-level language, JavaScript is used for web programming, and Python is popular for scripting and data science.

The key to being a versatile programmer is not just to learn a specific language, but to learn the fundamental principles behind them. Languages often share core concepts, and understanding these principles allows you to learn a new language relatively quickly. However, be cautious of claims that languages with similar syntax are easy to transition between; their underlying semantics can be very different.

1.2 Program Compilation and Execution
1.2.1 Conventional Model (e.g., C/C++)

In a conventional model, the process is straightforward:

  1. Compilation: The source code is translated by a compiler into an intermediate representation.
  2. Code Generation: The intermediate code is converted into machine code, which is a set of instructions specific to the computer’s processor (CPU).
  3. Execution: The operating system loads and runs the machine code directly on the hardware.

The primary disadvantage is that the compiled program is not portable; it can only run on the specific type of machine it was compiled for.

1.2.2 The Java Model: Platform Independence

Java introduces a layer of abstraction to achieve portability.

  1. Compilation: The javac compiler translates Java source code (.java file) into bytecode (.class file). Bytecode is a highly optimized set of instructions for a hypothetical, abstract computer.
  2. Execution: This bytecode is not tied to any specific hardware. It is executed by a Java Virtual Machine (JVM), which is a software program that interprets the bytecode and translates it into native machine code for the host computer.

This model is the foundation of Java’s slogan: “Write once, run everywhere.” As long as a device has a JVM, it can run any compiled Java bytecode.

1.3 The Java Platform: JDK, JRE, and JVM

These three acronyms are central to the Java ecosystem and are often confused. They represent a layered set of tools.

1.3.1 JVM (Java Virtual Machine)

The JVM is the core component that makes Java platform-independent. It is a specification for a virtual processor that executes Java bytecode. When you run a Java program, a JVM instance is created to provide the runtime environment. Its major features include:

  • Hardware Independence: It abstracts away the details of the underlying operating system and hardware.
  • Stack-Based Execution Model: It uses a stack to manage method calls and expression calculations, which is simpler than a register-based model.
  • Automatic Memory Management: It includes a garbage collector to automatically reclaim memory that is no longer in use, preventing common memory leaks.
1.3.2 JRE (Java Runtime Environment)

The JRE is the software package required to run Java applications. It contains everything needed for execution, including:

  • An implementation of the JVM.
  • The Java Class Library, which provides a rich set of pre-built functionalities.

If you only want to run Java programs and not develop them, you only need to install the JRE.

1.3.3 JDK (Java Development Kit)

The JDK is a full-featured software development kit for creating Java applications. It is a superset of the JRE and contains everything in the JRE, plus development tools such as:

  • javac: The Java compiler.
  • jdb: The Java debugger.
  • javadoc: The documentation generator.

Programmers need to install the JDK to write, compile, and debug Java code.

1.4 Java Memory Model

When a Java program runs, the JVM allocates memory into three distinct areas:

  • Code Area: This is where the compiled bytecode for the classes is loaded and stored. In Java, classes are loaded on an as-needed basis.
  • Stack: The stack manages method execution. Each time a method is called, a new stack frame (or activation record) is pushed onto the stack. This frame holds the method’s local variables (including primitive types and references to objects), and parameters. When the method finishes, its frame is popped off the stack. This Last-In, First-Out (LIFO) structure allows for recursion.
  • Heap: This is the dynamic memory area where all Java objects are allocated. Unlike the stack, the heap is managed by the JVM’s garbage collector.
1.5 Introduction to Object-Oriented Programming (OOP)
1.5.1 The Core Idea

OOP is a programming paradigm that treats a program as a model of a real-world system. The real world is composed of objects that have properties and behaviors, and they interact with each other. OOP provides a way to represent these objects, their relationships, and their interactions in code.

1.5.2 Class and Object

The two fundamental concepts in OOP are the class and the object.

  • A class is a blueprint, template, or user-defined type that describes the structure (data) and behavior (methods) of a certain kind of object. It is a compile-time concept. For example, a Car class would define that all cars have properties like color and speed, and behaviors like startEngine() and accelerate().
  • An object is a concrete instance of a class. It is a run-time entity that exists in memory. You can create many objects from a single class, each with its own state. For example, myCar and yourCar could both be objects of the Car class, but myCar could be red while yourCar is blue.

In Java, a program is a collection of class declarations. The class is the main building block.

1.6 Working with Objects in Java
1.6.1 Value Types vs. Reference Types

Java has two categories of data types:

  • Value Types (Primitives): These are the basic data types (byte, short, int, long, float, double, char, boolean). A variable of a primitive type directly stores its value in the memory allocated for it (usually on the stack).
  • Reference Types (Classes): Any class is a reference type. A variable of a reference type does not store the object itself. Instead, it stores a reference (or memory address) to the object, which resides on the heap.
1.6.2 Creating Objects

Objects are created (instantiated) from a class using the new keyword.

Point p1 = new Point();

The new operator performs three actions:

  1. Allocates memory on the heap for the new Point object.
  2. Initializes the object’s state (its member variables).
  3. Returns a reference to the newly created object, which is then assigned to the variable p1.
1.6.3 Objects and References

Because class variables hold references, assigning one reference variable to another does not copy the object. It only copies the reference.

Point p1 = new Point();
Point p2 = p1; // p2 now refers to the SAME object as p1

After this code, both p1 and p2 point to the single Point object on the heap. Any changes made through p2 will be visible through p1. If an object no longer has any references pointing to it, it becomes eligible for garbage collection.

1.6.4 Accessing Instance Members

To access the fields or methods of an object, you use dot notation with a reference to the instance.

p1.move(10, 5); // Calls the move method on the object p1 refers to
1.6.5 Constructors

A constructor is a special method used to initialize the state of a new object. It has the same name as the class and is called automatically when you use the new operator. A class can have multiple constructors with different parameters, allowing for different ways to create instances.

public class Point {
    int x, y;

    // Default constructor
    public Point() {
        this.x = 0;
        this.y = 0;
    }

    // Parameterized constructor
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
1.6.6 Interface vs. Implementation

A key principle of OOP is encapsulation, which involves hiding the internal complexity of a class.

  • The interface of a class consists of its public members (methods and fields). This is the “contract” the class provides to the outside world, defining how other parts of the program can interact with its objects.
  • The implementation consists of the private members and the code inside the methods. This is the internal logic, which can be changed without affecting the clients of the class, as long as the public interface remains the same.

By default, class members in Java are package-private (accessible only within the same package). It is good practice to explicitly mark members as public or private.

1.7 Java Basics
1.7.1 Naming Conventions
  • Classes: Use UpperCamelCase (e.g., HelloWorld, StringParser).
  • Methods and Variables: Use lowerCamelCase (e.g., calculateSum, userName).
1.7.2 Wrapper Classes

For every primitive type, Java provides a corresponding wrapper class (e.g., Integer for int, Double for double). These classes “wrap” a primitive value in an object, which is necessary when you need to use primitives in contexts that require objects, such as with generic collections.

1.7.3 Comments

Java supports three types of comments:

  • // Single-line comment
  • /* Multi-line comment */
  • /** Javadoc comment */ (Used by the javadoc tool to generate documentation)

2. Definitions

  • JVM (Java Virtual Machine): An abstract computing machine that enables a computer to run a Java program. It executes bytecode.
  • JRE (Java Runtime Environment): A software package that provides the Java class libraries, the JVM, and other components necessary to run Java applications.
  • JDK (Java Development Kit): A software development kit that includes the JRE plus development tools like the compiler (javac) and debugger (jdb).
  • Bytecode: A portable, intermediate language that a Java compiler generates from source code. It is executed by the JVM.
  • Class: A blueprint or template for creating objects. It defines an object’s properties (fields) and behaviors (methods).
  • Object: A concrete instance of a class, with its own state and behavior. It exists in the computer’s memory during runtime.
  • Instance: Another term for an object.
  • Stack: A region of memory used to store local variables and manage method invocations in a Last-In, First-Out (LIFO) manner.
  • Heap: A region of memory used for dynamic memory allocation, where all Java objects are stored.
  • Garbage Collection: The automatic process of finding and reclaiming memory occupied by objects that are no longer in use.
  • Value Type: A data type that stores its actual value directly in memory (e.g., int, double).
  • Reference Type: A data type that stores a reference (memory address) to an object, rather than the object itself. All classes are reference types.
  • Constructor: A special method for creating and initializing an object instance of its class.
  • Method: A block of code associated with a class or object that performs a specific task.
  • Interface (of a class): The set of public methods and fields of a class that are accessible to external code.
  • Implementation (of a class): The private, internal logic and data of a class, which is hidden from the outside.

3. Examples

3.1. Swap Two Numbers (Lab 6, Task 1)

Write a program to swap two numbers in Java.

Click to see the solution
import java.util.Scanner;

public class SwapNumbers {
    public static void main(String[] args) {
        // Create a Scanner object to read user input.
        Scanner input = new Scanner(System.in);

        // Prompt for and read the first number.
        System.out.print("Enter first number: ");
        int num1 = input.nextInt();

        // Prompt for and read the second number.
        System.out.print("Enter second number: ");
        int num2 = input.nextInt();

        System.out.println("--Before swap--");
        System.out.println("First number = " + num1);
        System.out.println("Second number = " + num2);

        // Swapping logic using a temporary variable.
        int temp = num1;
        num1 = num2;
        num2 = temp;

        System.out.println("\n--After swap--");
        System.out.println("First number = " + num1);
        System.out.println("Second number = " + num2);
        
        input.close();
    }
}
3.2. Find ASCII Value of a Character (Lab 6, Task 2)

Write a program which finds an ASCII value of a character.

Click to see the solution
import java.util.Scanner;

public class AsciiValue {
    public static void main(String[] args) {
        // Create a Scanner object.
        Scanner scanner = new Scanner(System.in);

        // Prompt the user to enter a character.
        System.out.print("Enter a character: ");
        
        // Read the first character of the user's input.
        char character = scanner.next().charAt(0);
        
        // In Java, a 'char' can be directly cast to an 'int' to get its ASCII value.
        int asciiValue = (int) character;
        
        // Print the result.
        System.out.println("The ASCII value of '" + character + "' is: " + asciiValue);
        
        scanner.close();
    }
}
3.3. Get Index of All Alphabet Characters (Lab 6, Task 3)

Write a Java program to get the index of all the characters of the English alphabet in a given string.

Click to see the solution
public class AlphabetIndex {
    public static void main(String[] args) {
        // The string to search within.
        String str = "The quick brown fox jumps over the lazy dog.";

        System.out.println("Finding indices of alphabet characters in the string:");
        System.out.println("'" + str + "'\n");

        // Iterate through each character of the alphabet from 'a' to 'z'.
        for (char alphabet = 'a'; alphabet <= 'z'; alphabet++) {
            // Use the indexOf method to find the first occurrence of the character.
            // indexOf returns -1 if the character is not found.
            int index = str.indexOf(alphabet);
            
            // If the character is found, print its index.
            if (index != -1) {
                System.out.println("'" + alphabet + "' is found at index: " + index);
            } else {
                System.out.println("'" + alphabet + "' is not found in the string.");
            }
        }
    }
}
3.4. Compare Two Strings Lexicographically (Lab 6, Task 4)

Write a Java program to compare 2 strings lexicographically.

Click to see the solution
import java.util.Scanner;

public class LexicographicalCompare {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // Get the first string from the user.
        System.out.print("Enter the first string: ");
        String str1 = scanner.nextLine();

        // Get the second string from the user.
        System.out.print("Enter the second string: ");
        String str2 = scanner.nextLine();

        // The compareTo() method is the standard way to compare strings lexicographically in Java.
        int result = str1.compareTo(str2);

        // Analyze the result of compareTo().
        if (result < 0) {
            System.out.println("\"" + str1 + "\" is lexicographically less than \"" + str2 + "\"");
        } else if (result > 0) {
            System.out.println("\"" + str1 + "\" is lexicographically greater than \"" + str2 + "\"");
        } else {
            System.out.println("\"" + str1 + "\" is lexicographically equal to \"" + str2 + "\"");
        }
        
        scanner.close();
    }
}
3.5. Count Vowels in a String (Lab 6, Task 5)

Write a Java method to count all vowels in a string.

Click to see the solution
import java.util.Scanner;

public class VowelCounter {

    // This method takes a string and returns the number of vowels in it.
    public static int countVowels(String str) {
        int count = 0;
        // Convert the string to lower case to simplify the check.
        String lowerStr = str.toLowerCase();
        
        // Iterate through each character of the string.
        for (int i = 0; i < lowerStr.length(); i++) {
            char ch = lowerStr.charAt(i);
            // Check if the character is a vowel.
            if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
                count++;
            }
        }
        return count;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter a string: ");
        String userInput = scanner.nextLine();
        
        // Call the method to count the vowels.
        int vowelCount = countVowels(userInput);
        
        System.out.println("The number of vowels in the string is: " + vowelCount);
        
        scanner.close();
    }
}
3.6. Convert Fahrenheit to Celsius (Lab 6, Task 6)

Write a Java program to convert temperature from Fahrenheit to Celsius degree.

Click to see the solution
import java.util.Scanner;

public class TempConverter {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Prompt the user for the temperature in Fahrenheit.
        System.out.print("Enter temperature in Fahrenheit: ");
        // Use double to allow for decimal values.
        double fahrenheit = scanner.nextDouble();
        
        // Apply the conversion formula: Celsius = (Fahrenheit - 32) * 5 / 9.
        double celsius = (fahrenheit - 32) * 5.0 / 9.0;
        
        // Print the result, formatted to two decimal places.
        System.out.printf("Temperature in Celsius is: %.2f\n", celsius);
        
        scanner.close();
    }
}
3.7. Calculate Difference Between Two Time Periods (Lab 6, Task 7)

Calculate the difference between two Time periods by creating a class Time.

Click to see the solution
public class TimeDifference {

    // The Time class to store hours, minutes, and seconds.
    static class Time {
        int hours;
        int minutes;
        int seconds;

        // Constructor to initialize the Time object.
        public Time(int h, int m, int s) {
            this.hours = h;
            this.minutes = m;
            this.seconds = s;
        }
        
        // Method to convert the entire time period into seconds for easy calculation.
        public int toSeconds() {
            return hours * 3600 + minutes * 60 + seconds;
        }

        // Static method to calculate the difference between two Time objects.
        public static Time difference(Time start, Time stop) {
            int diffInSeconds = stop.toSeconds() - start.toSeconds();
            
            // Handle cases where the difference might be negative.
            if (diffInSeconds < 0) {
                diffInSeconds = -diffInSeconds; // Take the absolute difference
            }
            
            // Convert the difference in seconds back to H:M:S format.
            int h = diffInSeconds / 3600;
            int m = (diffInSeconds % 3600) / 60;
            int s = diffInSeconds % 60;
            
            return new Time(h, m, s);
        }
    }

    public static void main(String[] args) {
        // Create two Time objects.
        Time startTime = new Time(10, 30, 15);
        Time endTime = new Time(12, 15, 45);

        // Calculate the difference.
        Time diff = Time.difference(startTime, endTime);

        // Print the results.
        System.out.printf("Start Time = %d:%d:%d\n", startTime.hours, startTime.minutes, startTime.seconds);
        System.out.printf("End Time   = %d:%d:%d\n", endTime.hours, endTime.minutes, endTime.seconds);
        System.out.printf("Difference = %d:%d:%d\n", diff.hours, diff.minutes, diff.seconds);
    }
}
3.8. Number System Converter (Lab 6, Task 8)

Write a Java program to convert binary, decimal, and hexadecimal numbers.

Click to see the solution
import java.util.Scanner;

public class NumberConverter {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // --- Decimal to Others ---
        System.out.print("Enter a decimal number: ");
        int decimal = scanner.nextInt();
        
        // Java's Integer class has built-in static methods for conversion.
        String binary = Integer.toBinaryString(decimal);
        String hex = Integer.toHexString(decimal);
        
        System.out.println("Binary equivalent: " + binary);
        System.out.println("Hexadecimal equivalent: " + hex.toUpperCase());
        
        // --- Binary to Decimal ---
        System.out.print("\nEnter a binary number: ");
        String binaryInput = scanner.next();
        // The parseInt method can take a radix (base) as a second argument.
        int decimalFromBinary = Integer.parseInt(binaryInput, 2);
        System.out.println("Decimal equivalent: " + decimalFromBinary);
        
        // --- Hexadecimal to Decimal ---
        System.out.print("\nEnter a hexadecimal number: ");
        String hexInput = scanner.next();
        int decimalFromHex = Integer.parseInt(hexInput, 16);
        System.out.println("Decimal equivalent: " + decimalFromHex);
        
        scanner.close();
    }
}
3.9. Calculate Average of an Array (Lab 6, Task 9)

Write a program to calculate the average value of integer array elements.

Click to see the solution
public class ArrayAverage {
    public static void main(String[] args) {
        // Initialize an integer array.
        int[] numbers = {10, 20, 30, 40, 50, 60};
        
        // Variable to hold the sum of the elements.
        double sum = 0;
        
        // Iterate through the array using an enhanced for loop.
        for (int number : numbers) {
            sum += number;
        }
        
        // Calculate the average. Cast one of the operands to double for floating-point division.
        double average = sum / numbers.length;
        
        // Print the result.
        System.out.println("The average of the array elements is: " + average);
    }
}
3.10. Insert an Element into an Array (Lab 6, Task 10)

Write a program to insert an element (at a specific position) into an array.

Click to see the solution
import java.util.Arrays;
import java.util.Scanner;

public class InsertIntoArray {
    public static void main(String[] args) {
        // Original array. Note: array size is fixed in Java.
        int[] originalArray = {10, 20, 30, 40, 50};
        int currentSize = originalArray.length;
        
        Scanner scanner = new Scanner(System.in);

        System.out.println("Original array: " + Arrays.toString(originalArray));
        
        // Get the element and position from the user.
        System.out.print("Enter the element to insert: ");
        int elementToInsert = scanner.nextInt();
        
        System.out.print("Enter the position to insert at (0-based index): ");
        int position = scanner.nextInt();

        // Create a new array with one more space.
        int[] newArray = new int[currentSize + 1];

        // Copy elements from the original array to the new one up to the insertion point.
        for(int i=0; i < position; i++){
            newArray[i] = originalArray[i];
        }

        // Insert the new element at the specified position.
        newArray[position] = elementToInsert;
        
        // Copy the remaining elements from the original array, shifting their positions.
        for(int i=position; i < currentSize; i++){
            newArray[i+1] = originalArray[i];
        }
        
        System.out.println("New array: " + Arrays.toString(newArray));
        scanner.close();
    }
}
3.11. Find Duplicate Values in an Array (Lab 6, Task 11)

Write a program to find the duplicate values of an array of integer values.

Click to see the solution
public class FindDuplicates {
    public static void main(String[] args) {
        int[] array = {1, 2, 5, 5, 6, 6, 7, 2};
 
        System.out.println("Duplicate elements in the array are: ");
        // Use nested loops to compare each element with every other element.
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = i + 1; j < array.length; j++) {
                // If two elements are the same and their indices are different, it's a duplicate.
                if (array[i] == array[j]) {
                    System.out.println(array[j]);
                }
            }
        }
    }
}
3.12. Check if a File or Directory Exists (Lab 6, Task 12)

Write a program to check whether a file or directory specified by a pathname exists or not.

Click to see the solution
import java.io.File;
import java.util.Scanner;

public class FileExistsChecker {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("Enter a file or directory path: ");
        String path = scanner.nextLine();
        
        // Create a File object from the path string.
        File file = new File(path);
        
        // The exists() method returns true if the file or directory exists.
        if (file.exists()) {
            System.out.println("The file or directory at '" + path + "' exists.");
        } else {
            System.out.println("The file or directory at '" + path + "' does not exist.");
        }
        
        scanner.close();
    }
}
3.13. Check if a Path is a File or Directory (Lab 6, Task 13)

Write a Java program to check if a given pathname is a directory or a file.

Click to see the solution
import java.io.File;
import java.util.Scanner;

public class FileOrDirChecker {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter a file or directory path: ");
        String path = scanner.nextLine();
        
        File file = new File(path);
        
        if (file.exists()) {
            // The isDirectory() method returns true if the path points to a directory.
            if (file.isDirectory()) {
                System.out.println("The path '" + path + "' points to a directory.");
            } 
            // The isFile() method returns true if the path points to a file.
            else if (file.isFile()) {
                System.out.println("The path '" + path + "' points to a file.");
            }
        } else {
            System.out.println("The path '" + path + "' does not exist.");
        }
        
        scanner.close();
    }
}
3.14. Copy a Text File (Lab 6, Task 14)

Write a program that reads the data from a text file and writes it into another text file.

Click to see the solution
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileCopier {
    public static void main(String[] args) {
        // Define file objects for the source and destination.
        File sourceFile = new File("source.txt");
        File destFile = new File("destination.txt");
        
        try {
            // Create a FileReader to read from the source file.
            FileReader reader = new FileReader(sourceFile);
            // Create a FileWriter to write to the destination file.
            FileWriter writer = new FileWriter(destFile);
            
            // A variable to hold one character at a time.
            int character;
            
            System.out.println("Copying file...");
            
            // Read from the source file character by character.
            // The read() method returns -1 when the end of the file is reached.
            while ((character = reader.read()) != -1) {
                // Write the character to the destination file.
                writer.write(character);
            }
            
            System.out.println("File copied successfully.");
            
            // Always close the streams to release resources.
            reader.close();
            writer.close();
            
        } catch (IOException e) {
            // Handle potential errors, such as the source file not being found.
            e.printStackTrace();
        }
    }
}