OOP_REV
OOP_REV
Learning Objectives
By the end of this lesson, you will be able to:
• Define Object-Oriented Programming (OOP) and understand its core concepts.
• Compare and contrast procedural programming and OOP.
• Explain the benefits of using abstract data types (ADTs).
• Understand the basic structure of a Java program.
• Identify the installation requirements for Java.
• Define and use literals, identifiers, primitive data types, and variables in Java.
• Write and evaluate expressions in Java, including understanding operator precedence.
• Explain reference types and type casting in Java.
• Utilize input and output (I/O) statements in Java (using methods such as print, println, printf
and Scanner methods).
• Utilize the Java Math API library for common mathematical functions.
• Comment code effectively for readability and maintenance.
Key Terms
• Object-Oriented Programming (OOP): A programming paradigm that organizes software design
around objects—entities that encapsulate data and behavior.
• Procedural Programming: A programming paradigm where code is organized into procedures or
functions that operate on data, with a focus on sequential execution.
• Abstract Data Types (ADTs): Data types defined by the operations that can be performed on them,
without specifying how these operations are implemented.
• Class: A blueprint or template that defines the structure (attributes) and behavior (methods) of
objects.
• Object: An instance of a class that holds state (data) and can perform actions (methods).
• Encapsulation: The practice of bundling data and methods that operate on that data within a class,
restricting direct access from outside.
• Inheritance: A mechanism by which one class (child) derives attributes and methods from another
class (parent), promoting code reuse.
• Polymorphism: The ability of different objects to respond uniquely to the same method call,
typically achieved via method overriding.
• Abstraction: The process of hiding complex implementation details and exposing only the essential
features of an object.
• Java Virtual Machine (JVM): The runtime environment that executes Java bytecode, allowing Java
programs to run on any platform.
• Literals: Fixed values explicitly written in the code (e.g., numbers, characters, strings).
• Identifiers: Names given to program elements such as variables, methods, and classes.
• Primitive Data Types: Basic data types provided by Java (e.g., int, boolean, char, double) that store
simple values.
• Variables: Named storage locations in memory that hold data which may change during program
execution.
• Operators: Symbols that perform operations on one or more operands (e.g., arithmetic, relational,
logical operators).
• Reference Types: Data types that refer to objects (such as instances of classes or arrays) rather
than containing their own values.
• Type Casting: Converting a value from one data type to another, either implicitly or explicitly.
• Input/Output Statements: Constructs that allow programs to receive input (e.g., via the Scanner
class) and produce output (e.g., via System.out methods).
• Java Math API Library: A collection of methods in Java’s Math class for performing mathematical
operations such as square roots, powers, and random number generation.
• Comments: Non-executable annotations in code used to explain and document the logic for
human readers.
• Java History: The timeline of Java’s development, starting with its creation in 1995 by Sun
Microsystems.
• Java Editions: Variants of Java such as Java SE (Standard Edition), Java EE (Enterprise Edition), and
Java ME (Micro Edition) tailored for different types of applications.
1. Introduction to Object-Oriented Programming (OOP)
1.1 Procedural vs. Object-Oriented Programming
• Procedural Programming: Organizes code into procedures or functions that manipulate data; data
and functions are kept separate. For example, languages like C and Pascal follow this approach.
• Object-Oriented Programming (OOP): Organizes code around objects that encapsulate both data
(attributes) and behaviors (methods). This design reflects real-world entities and is central to
languages such as Java and C++.
Example:
public class MathExample {
public static void main(String[] args) {
double squareRoot = Math.sqrt(16); // 4.0
double power = Math.pow(2, 3); // 8.0
double randomValue = Math.random(); // Random value between 0.0 and 1.0
5. Comments in Java
Comments help make code easier to understand. Java supports:
• Single-line comments: Begin with //.
• Multi-line comments: Enclosed between /* and */.
Example:
public class CommentsExample {
public static void main(String[] args) {
// This is a single-line comment
• Java was developed by a team led by James Gosling at Sun Microsystems. Originally called Oak,
Java was designed in 1991 for use in embedded chips in consumer electronic appliances.
• Java was introduced in 1995 by Sun Microsystems as a platform-independent language.
• Its design was influenced by the need for a language that could be used on a variety of devices—
from embedded systems to large-scale enterprise applications.
• Over time, Java has evolved through multiple editions, each adding new features while maintaining
backward compatibility.
• Sun Microsystems was purchased by Oracle in 2010.
• Java SE (Standard Edition): The core Java platform for developing and running desktop applications
and simple server-side applications.
• Java EE (Enterprise Edition): Built on Java SE, this edition includes additional libraries and tools for
developing large-scale, multi-tiered, and web-based enterprise applications.
• Java ME (Micro Edition): A subset of Java designed for mobile and embedded devices.
• JVM (Java Virtual Machine): The runtime engine that executes Java bytecode and provides platform
independence.
• JDK (Java Development Kit): A toolkit that includes the JRE, compilers, and tools needed to
develop Java applications.
• JRE (Java Runtime Environment): Provides the libraries and JVM necessary to run Java programs.
• Bytecode: The intermediate representation of Java code that is executed by the JVM.
Conclusion
In this lesson, we laid a comprehensive foundation in Java programming and object-oriented principles.
We explored:
• OOP Fundamentals: The differences between procedural and object-oriented programming, the
benefits of ADTs, and core OOP concepts such as abstraction, encapsulation, inheritance, and
polymorphism.
• Java Basics: The structure of a Java program, installation requirements (JDK, JVM, IDE), and
essential language elements like literals, identifiers, primitive data types, variables, expressions,
and operators.
• I/O Operations & Math API: How to perform input and output using Scanner and System.out
methods, and how to use Java’s Math API for common mathematical functions.
• Java History and Editions: An overview of Java’s history, its evolution since 1995, and the key
editions (Java SE, Java EE, Java ME) along with essential terminology like JVM, JDK, and JRE.
This comprehensive introduction prepares you for advanced topics in Java programming while grounding
you in the core concepts and historical context that have shaped the language. As you continue your
journey, practice these concepts through hands-on projects and further study to build robust,
maintainable applications.
Java Interpreter vs. Other Compilers
Overview:
Java uses a unique execution model compared to traditionally compiled languages like C or C++. In Java,
source code is first compiled into an intermediate form called bytecode by the Java compiler (javac). This
bytecode is then executed by the Java Virtual Machine (JVM), which functions as an interpreter and, in
many modern implementations, a Just-In-Time (JIT) compiler.
Key Differences:
• Compilation Process:
o Java:
▪ Step 1: Source code (.java) is compiled into platform-independent bytecode (.class
files).
▪ Step 2: The JVM interprets (or JIT-compiles) this bytecode at runtime, allowing Java
applications to run on any platform that has a compatible JVM.
o Other Compilers (e.g., C/C++):
▪ Source code is directly compiled into native machine code specific to a target
operating system and hardware, resulting in an executable file that runs directly on
that system.
• Platform Independence:
o Java:
▪ Bytecode is platform-independent, meaning the same compiled code can run on
different systems without modification.
o Other Compilers:
▪ Native machine code is platform-specific and requires recompilation for different
environments.
• Runtime Performance:
o Java:
▪ The JVM’s interpreter can introduce overhead, but modern JVMs use JIT compilation
to optimize performance by compiling frequently executed code paths into native
code at runtime.
o Other Compilers:
▪ Compiled directly to native code, which often results in faster startup and execution
times since there is no additional interpretation layer.
Conclusion:
Java’s two-step compilation and execution process provides platform independence and added security,
while modern optimizations like JIT compilation help improve performance. In contrast, traditional
compilers generate native code directly, often yielding faster execution in certain scenarios but lacking the
cross-platform flexibility of Java.
Week 02-03 - Lesson: Selection and Looping Statements in Java
Learning Objectives
By the end of this lesson, you should be able to:
• Discuss the usage of boolean variables, literals, and expressions in Java.
• Identify and use relational (==, !=, >, <, >=, <=) and logical operators (&&, ||, !, ^).
• Implement selection control using various if statements:
o One-way if statement
o Two-way if–else statement
o Nested if statements
o Multi-way if–else chains
• Utilize switch statements for multi-conditional selection.
• Implement loops using:
o The while loop
o The do-while loop
o The for loop
• Employ nested loops for complex iterative tasks.
• Use break and continue statements effectively to control loop execution.
Key Terms
• Boolean literals: The values true and false.
• Boolean expressions: Expressions that evaluate to a boolean value.
• Boolean variables: Variables that store boolean values.
• Relational operators: Operators used to compare values (e.g., ==, !=, >, <, >=, <=).
• Logical operators: Operators used to combine boolean expressions (e.g., &&, ||, !, ^).
• if statement: A selection control statement that executes code if a condition is true.
• if–else statement: Executes one block of code if a condition is true and another block if it is false.
• Nested if statement: An if statement placed within another if statement.
• Multi-way if–else statement: A chain of if–else statements to test multiple conditions.
• switch statement: A multi-branch selection statement that selects execution paths based on a
variable’s value.
• while loop: Repeats a block of code as long as a condition is true (pre-test loop).
• do–while loop: Executes a block of code at least once and then repeats it while a condition is true
(post-test loop).
• for loop: A control structure that provides initialization, condition checking, and update in one line.
• Nested loop: A loop placed inside the body of another loop.
• break statement: Exits the closest loop or switch block immediately.
• continue statement: Skips the remaining part of the current loop iteration and proceeds with the
next iteration.
1. Selection Statements
Selection statements allow your program to choose different execution paths based on conditions.
1.1 Boolean Literals, Expressions, and Variables
• Boolean literals: true and false are used directly.
• Boolean expressions: Formed using relational and logical operators; they evaluate to true or false.
Example:
boolean isJavaFun = true; // boolean variable
int a = 5, b = 10;
boolean comparison = (a < b); // evaluates to true
Example:
if ((a < b) && (b != 0)) {
System.out.println("a is less than b and b is not zero.");
}
1.3 One-Way if Statement
Executes a block of code only if the condition is true.
Syntax:
if (condition) {
// Code to execute if condition is true
}
Example:
if (a < b) {
System.out.println("a is less than b.");
}
Example:
if (a < b) {
System.out.println("a is less than b.");
} else {
System.out.println("a is not less than b.");
}
Example:
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Another day");
}
2. Looping Statements
Loops allow the repeated execution of a block of code until a condition is met.
Example:
int i = 1;
while (i <= 5) {
System.out.println("i = " + i);
i++;
}
Example:
for (int k = 1; k <= 5; k++) {
System.out.println("k = " + k);
}
Example:
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 3; col++) {
System.out.print("[" + row + "," + col + "] ");
}
System.out.println(); // Move to next line after each row
}
Conclusion
In this lesson, we explored how Java enables decision-making and repetitive tasks through selection and
looping statements. We learned that:
• Selection Statements:
o Boolean variables, expressions, and literals form the basis of decision making.
o Relational and logical operators help combine and compare values.
o The if statement (in its one-way, two-way, nested, and multi-way forms) and switch
statement allow you to execute code based on conditions.
• Looping Statements:
o The while, do–while, and for loops help repeat actions, with each suited for different
scenarios.
o Nested loops are valuable for processing multi-dimensional data or creating patterns.
o The break and continue statements give you fine-grained control over loop execution.
Mastering these constructs is essential for developing efficient, clear, and maintainable Java programs. As
you progress, practice by writing small programs that incorporate these selection and looping statements.
Week 04 - Lesson: Methods in Java
Learning Objectives
By the end of this lesson, you will be able to:
• Define what a method is and explain its purpose in Java.
• Differentiate between parameters and arguments.
• Discuss the different return types of methods (void and value-returning methods).
• Understand the concept of variable scope within methods.
• Define and use method overloading to write cleaner and more modular code.
Lesson Content
1. What Are Methods?
Methods in Java are self-contained blocks of code that perform specific tasks. They allow you to break
complex problems into smaller, manageable parts, increase code reusability, and improve readability.
Rather than writing the same code multiple times, you can call a method whenever you need to perform
that task.
Example
public class Calculator {
// 'a' and 'b' are parameters
public static int add(int a, int b) {
return a + b;
}
Example
public class HelloWorld {
public static void main(String[] args) {
sayHello(); // method invocation
}
// Method definition
public static void sayHello() {
System.out.println("Hello, World!");
}
}
3. Method Return Types (void vs. Value-Returning Methods)
A method’s return type indicates whether the method returns a value:
• void methods do not return any value.
• Value-returning methods specify a return type (e.g., int, double) and use the return statement to
pass a value back to the caller.
Example
Void method:
public static void printMessage() {
System.out.println("This method does not return a value.");
}
Value-returning method:
public static int multiply(int x, int y) {
return x * y; // returns an integer value
}
4. Scope of Variables
The scope of a variable is the part of the program where it can be accessed:
• Local variables: Declared within a method, only accessible within that method.
• Parameters: Considered local variables whose scope is limited to the method body.
Example
public class ScopeDemo {
public static void main(String[] args) {
int result = add(3, 4);
System.out.println("Result: " + result);
// 'x' and 'y' are not accessible here because they are local to the add method.
}
5. Method Overloading
Method overloading allows you to define multiple methods with the same name in the same class, as long
as they have different parameter lists (different number or types of parameters). This enhances code
readability and usability by providing different ways to perform similar tasks.
Example
public class OverloadExample {
// Overloaded method: two int parameters
public static int add(int a, int b) {
return a + b;
}
• Methods allow you to encapsulate code for specific tasks, promoting modularity and reusability.
• Parameters vs. Arguments: Parameters are placeholders in method definitions, while arguments
are the actual values passed when the method is invoked.
• Return Types: Methods can either return a value (e.g., int, double) or be declared with void to
indicate they do not return any value.
• Variable Scope: Variables declared within a method (including parameters) are only accessible
within that method.
• Method Overloading: You can define multiple methods with the same name as long as they have
different parameter lists, making your code more flexible and easier to understand.
Understanding these concepts is essential for writing well-structured, maintainable, and reusable Java
programs. As you continue learning, practice writing methods to perform common tasks and explore more
advanced topics such as recursion and passing objects as parameters.
Week 05 - Lesson: Objects and Classes in Java
Learning Objectives
By the end of this lesson, you will be able to:
• Discuss the concepts of objects and classes and understand their roles in Java.
• Create classes and objects to model real-world entities.
• Understand and use access modifiers (public, private, protected) to control visibility.
• Define and use methods and attributes (data fields) within classes.
• Implement constructors to initialize objects at creation time.
• Discuss deconstructors and garbage collection, noting that Java handles memory cleanup
automatically.
• Define and use class methods and class variables (static members) that belong to the class
rather than any instance.
Lesson Content
Example
public class Car {
// Attributes (fields)
String color;
String model;
// Methods
void drive() {
System.out.println("The " + this.color + " " + this.model + " is driving.");
}
}
Here, Car is a class, and individual cars created from it are objects.
1.2 Creating Classes and Objects
• Creating a Class: Use the class keyword to define a class, and inside, declare attributes and
methods.
• Creating an Object: Use the new keyword to instantiate a class.
Example
public class Main {
public static void main(String[] args) {
// Creating an object (instance) of the Car class
Car myCar = new Car();
myCar.color = "red";
myCar.model = "Toyota";
myCar.drive(); // Output: The red Toyota is driving.
}
}
2. Access Modifiers
Access modifiers control the visibility of classes, methods, and attributes:
• public: Accessible from any class.
• private: Accessible only within the same class.
• protected: Accessible within the same class, subclasses, and classes in the same package.
Example
public class Person {
public String name; // Accessible anywhere
private int age; // Accessible only within Person
protected String address; // Accessible within package and subclasses
Example
public class Calculator {
// Attribute
int lastResult;
Example
public class Book {
String title;
String author;
Key Point: While you cannot force garbage collection, you can suggest it by calling System.gc(), though
this is generally not recommended in production code.
Example
public class MathUtil {
// Class variable: shared by all instances
public static final double PI = 3.14159;
• Objects and Classes: We learned that classes serve as blueprints for objects, encapsulating state
and behavior.
• Access Modifiers: We discussed how public, private, and protected keywords control the visibility
of class members.
• Methods and Attributes: Methods define behavior, while attributes represent the state of an
object.
• Deconstructors and Garbage Collection: Java automatically reclaims memory via garbage
collection, so explicit deconstructors are not required.
• Class Methods and Class Variables: Static members belong to the class rather than individual
objects, enabling shared behavior and data.
Mastering these concepts is essential for building well-structured, maintainable, and reusable Java
applications. As you continue learning, practice by designing classes that model real-world scenarios and
experimenting with various access levels, constructors, and static members.
Week 06 - Lesson: Object-Oriented Thinking and Class Relationships in Java
Learning Objectives
By the end of this lesson, you will be able to:
• Understand the concept of object-oriented thinking.
• Learn the differences between the procedural paradigm and the object-oriented paradigm.
• Explore common relationships among classes: association, aggregation, and composition.
• Design classes use object-oriented principles such as abstraction and encapsulation.
Key Terms
• Class Abstraction: The separation of a class’s implementation details from the way it is used. It
allows the user to interact with a class solely through its public interface.
• Class Encapsulation: The practice of hiding the internal state and implementation details of a
class, exposing only what is necessary through public methods.
• Abstract Data Type (ADT): A data type defined by its behavior (the operations that can be
performed) rather than its implementation.
• Association: A general relationship between two classes that indicates they interact with each
other. It is a broad term for any connection between objects.
• Aggregation: A specialized form of association that represents an “owns-a” relationship, where one
object (the whole) contains another object, but both can exist independently.
• Composition: A strong form of aggregation where the lifetime of the contained object is strictly
dependent on the lifetime of the container object.
Lesson Content
1. Object-Oriented Thinking
Object-oriented thinking is a paradigm that models real-world entities as objects—each having state
(attributes) and behavior (methods). This approach focuses on designing software by modeling
interactions among these objects. In Java, everything (except primitive types) is an object, and classes
serve as blueprints for these objects.
Key idea: Rather than writing step-by-step instructions (as in procedural programming), you design objects
that interact with one another to accomplish tasks.
• Object-Oriented Paradigm: In OOP, data and functions are bundled together within objects. This
design facilitates reuse, scalability, and maintainability by emphasizing real-world modeling.
Comparison: While procedural programming separates functions from data, OOP couples them,
promoting encapsulation and modular design. This shift enhances software reusability and
maintainability.
3. Class Relationships
Understanding how classes interact is crucial in object-oriented design. Three common types of
relationships are:
• Association: A general relationship where two classes are connected because they interact. For
example, a Teacher class might be associated with a Student class.
• Composition:
A stronger form of aggregation where the lifetime of the contained object is tied to the container. For
example, a House class is composed of Room objects; if the house is destroyed, the rooms cease
to exist.
4. Designing Classes Using OOP Principles
When designing classes, keep in mind the following principles:
• Class Abstraction: Design your class so that users interact with it through a well-defined interface
without knowing the internal workings.
• Class Encapsulation: Hide the internal state of the class and expose only necessary functionalities
through public methods. Use access modifiers (public, private, protected) to control visibility.
Example:
Consider a class Car that aggregates Engine objects. In an aggregation relationship, the engine may be
replaced or exist outside the context of the car. In a composition relationship (e.g., a House composed of
Room objects), rooms do not exist independently of the house.
Conclusion
In this lesson, we explored the fundamentals of object-oriented thinking and examined key class
relationships in Java. We learned that:
• Object-Oriented Thinking centers around modeling real-world entities as objects with attributes
and behaviors.
• The procedural paradigm focuses on functions and sequences of steps, while the object-oriented
paradigm integrates data and behavior for more modular and maintainable code.
• Core design principles such as class abstraction and encapsulation are essential for creating
robust and reusable classes.
By understanding these concepts, you will be able to design and implement classes that model real-world
scenarios effectively and build maintainable Java applications.
Week 06 - Lesson: Inheritance, Polymorphism, and Dynamic Binding in Java
Learning Objectives
By the end of this lesson, you will be able to:
• Understand the concept of inheritance and its benefits in object-oriented programming.
• Learn about superclasses and subclasses and their roles in the inheritance hierarchy.
• Use the super keyword to invoke superclass constructors and methods.
• Understand method overriding and its importance for achieving polymorphism.
• Learn about polymorphism and how it allows objects to take on many forms.
• Understand dynamic binding and how the JVM determines which method to call at runtime.
Key Terms
• Inheritance: A mechanism that allows you to create a new class (subclass) based on an existing
class (superclass), inheriting its attributes and behaviors.
• Superclass: The existing (parent) class from which properties and methods are inherited.
• Subclass: The new (child) class that inherits from a superclass and can add its own attributes and
methods.
• Method Overriding: When a subclass provides its own implementation of a method that is already
defined in its superclass. This enables runtime polymorphism.
• Polymorphism: The ability of a variable of a supertype to refer to objects of different subtypes,
allowing the same method call to behave differently based on the actual object type.
• Dynamic Binding: The process by which the Java Virtual Machine (JVM) determines at runtime
which overridden method to call, based on the actual object’s type rather than the reference type.
• super Keyword: Used in a subclass to call a constructor or method of its superclass, allowing
access to overridden or hidden members.
Lesson Content
1. Inheritance
Inheritance is a cornerstone of object-oriented programming. It allows you to create new classes that are
built upon existing classes. This not only promotes code reuse by allowing subclasses to inherit common
functionality from a superclass but also helps in building a logical hierarchy that models real-world
relationships.
Example
// Superclass (Parent)
public class Animal {
public void makeSound() {
System.out.println("Some generic animal sound");
}
}
In this example, Dog inherits from Animal and overrides the makeSound() method to provide a specific
behavior.
• Superclass:
The parent class that defines common attributes and methods.
• Subclass:
The child class that inherits from the superclass and can add its own properties or override inherited
methods.
Using the super Keyword: The super keyword is used within a subclass to:
• Invoke the superclass constructor.
• Call a method from the superclass that has been overridden in the subclass.
Example
public class Animal {
String name;
Method Overriding: When a subclass provides its own implementation of a method already defined in its
superclass, it is known as method overriding. This allows the subclass to offer specific behavior while
preserving the method’s signature.
Example
public class Bird extends Animal {
@Override
public void makeSound() {
System.out.println("Chirp!");
}
}
Polymorphism: Polymorphism allows you to use a superclass reference to objects of a subclass. This
means you can write code that works on the superclass level, but the actual behavior at runtime is
determined by the subclass.
Example
public class TestPolymorphism {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // Dog is an Animal
myAnimal.makeSound(); // Outputs "Bark!" due to dynamic binding
Example:
Here, even though the variable myAnimal is of type Animal, it can hold objects of subclasses (Dog, Cat).
The actual method called is determined at runtime (dynamic binding), demonstrating polymorphism.
4. Dynamic Binding
Dynamic binding (or late binding) is the process by which the JVM determines at runtime which method
implementation to invoke when a method is overridden in a subclass. This means that the method call is
resolved based on the actual object type, not the reference type.
Example
Animal animalRef = new Dog();
animalRef.makeSound(); // JVM dynamically binds the Dog's implementation of makeSound()
Conclusion
Inheritance, polymorphism, and dynamic binding form the backbone of object-oriented programming in
Java. In this lesson, we learned that:
• Inheritance allows you to define new classes based on existing classes, promoting code reuse and
reducing redundancy.
• Superclasses and subclasses define a hierarchy where subclasses inherit common behavior from
superclasses and can extend or override that behavior.
• The super keyword provides a way to invoke superclass constructors and methods, ensuring that
inherited behaviors are accessible.
• Method overriding is a key feature that enables polymorphism by allowing subclasses to provide
specialized implementations.
• Polymorphism lets a single reference variable refer to objects of different subclasses, while
dynamic binding ensures that the appropriate method is called at runtime.
By mastering these concepts, you will be able to design and implement robust, flexible, and maintainable
object-oriented applications in Java. These principles not only help in creating efficient code but also in
modeling real-world problems in a clear and organized way.
Week 07 - Lesson: The Java String Class
Learning Objectives
By the end of this lesson, you will be able to:
• Discuss the Java String class and its purpose.
• Declare and instantiate String objects.
• Perform String concatenation, determine String length, and compare String objects.
• Format Strings using printf.
• Manipulate Strings using methods like substring, indexOf, and lastIndexOf.
Key Terms
• String: A sequence of characters; in Java, it is an immutable object from the java.lang package.
• String concatenation: The process of combining two or more strings into one.
• String length: The total number of characters in a String, determined using the length() method.
• String comparison: Checking whether two strings have the same sequence of characters (using
methods like equals and compareTo).
• String formatting: Creating formatted text output with methods such as printf and format
specifiers.
• String manipulation: Altering or extracting portions of a string using methods like substring,
indexOf, and lastIndexOf.
1.1 Overview
A String in Java represents a sequence of characters. The String class is fundamental because it offers
built-in methods to create, compare, and manipulate text. Strings are immutable, meaning once created
their content cannot change.
Example
String greeting = "Welcome to Java";
Example
String message = new String("Welcome to Java");
Example
String s1 = "Welcome ";
String s2 = "to ";
String s3 = "Java";
String s4 = s1.concat(s2).concat(s3); // "Welcome to Java"
The + operator:
String s5 = s1 + s2 + s3; // Also "Welcome to Java"
Example
String message = "Welcome to Java";
int length = message.length(); // length is 15
1.5 String Comparison
There are two common ways to compare strings:
• Using equals: Checks if two strings have the same content.
Example
String s1 = "Welcome to Java";
String s2 = "Welcome to Java";
boolean isEqual = s1.equals(s2); // returns true
Example
String s3 = "Welcome to C++";
int comparison = s1.compareTo(s3); // returns a positive value if s1 > s3 lexicographically
Example
String name = "John";
int age = 30;
System.out.printf("My name is %s and I am %d years old.\n", name, age);
Example
String text = "Welcome to Java";
String sub = text.substring(8); // "to Java"
Example
int index = text.indexOf("Java"); // index where "Java" starts
Example
int lastIndex = text.lastIndexOf("a"); // last occurrence of 'a'
2. Conclusion
In this lesson, we examined the Java String class, a fundamental part of Java programming for working with
text. We learned how to:
• Concatenate strings using both the + operator and the concat method.
Understanding these concepts and methods is essential for writing efficient, readable, and maintainable
Java programs. As you practice, try experimenting with these methods in various scenarios to deepen your
familiarity with string handling in Java.
Lesson: Arrays and Vectors in Java
Learning Objectives
By the end of this lesson, you will be able to:
• Discuss the use of arrays for storing collections of elements.
• Declare and instantiate arrays of various data types.
• Access and modify elements in arrays.
• Traverse through arrays using loops and iterators.
• Search for elements in arrays using linear and binary search.
• Explain the concept of vectors and how they differ from arrays.
• Create and manipulate one-dimensional, two-dimensional, and multi-dimensional vectors.
• Perform operations on vectors such as adding, removing, and searching for elements.
1. Arrays
Example
// Declaration and instantiation of an array of 10 integers
int[] numbers = new int[10];
Example
numbers[0] = 5; // Assigns 5 to the first element
int firstPrime = primes[0]; // Retrieves the first element (2)
System.out.println("First prime: " + firstPrime);
1.4 Traversing Arrays
Arrays can be traversed using loops such as the classic for-loop, enhanced for-loop (for-each), or even
iterators (if converting to collections).
Example
for (int i = 0; i < numbers.length; i++) {
System.out.println("Element at index " + i + ": " + numbers[i]);
}
Example
int target = 7;
boolean found = false;
for (int num : primes) {
if (num == target) {
found = true;
break;
}
}
System.out.println("Target found: " + found);
• Binary Search: Requires a sorted array and repeatedly divides the search interval in half.
(Java’s Arrays.binarySearch() method can be used for this purpose.)
Example
import java.util.Arrays;
2. Vectors
A vector is a dynamic array provided by Java in the java.util package. Unlike arrays, vectors can grow or
shrink dynamically as elements are added or removed. Vectors are synchronized (thread-safe) but have
more overhead compared to other dynamic array classes like ArrayList.
Example
import java.util.Vector;
Example
numbersVector.add(5);
numbersVector.add(10);
numbersVector.add(15);
Accessing Elements:
Example
int firstElement = numbersVector.get(0);
System.out.println("First element: " + firstElement);
Traversing with a for-loop:
Example
for (int i = 0; i < numbersVector.size(); i++) {
System.out.println("Element at index " + i + ": " + numbersVector.get(i));
}
Example
if (numbersVector.contains(10)) {
System.out.println("Vector contains 10 at index: " + numbersVector.indexOf(10));
}
3. Multi-Dimensional Arrays
3.1 Overview
Java supports multi-dimensional arrays, which are essentially arrays of arrays. A two-dimensional array
can be thought of as a table with rows and columns.
Example
// Declaration and instantiation of a 5x5 matrix of integers
int[][] matrix = new int[5][5];
Example
matrix[0][0] = 1; // Assigns 1 to the element in the first row and first column
System.out.println("Element at (0,0): " + matrix[0][0]);
2D Array: The following example demonstrates how to traverse a 2D array (matrix) using nested loops:
Example
public class TwoDArrayExample {
public static void main(String[] args) {
// A 3x4 matrix of integers
int[][] matrix = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
Example
public class ThreeDArrayExample {
public static void main(String[] args) {
// Declaration and instantiation of a 3D array (2 blocks x 3 rows x 4 columns)
int[][][] threeDArray = {
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
},
{
{ 13, 14, 15, 16 },
{ 17, 18, 19, 20 },
{ 21, 22, 23, 24 }
}
};
System.out.println("3D Array:");
// Traverse the 3D array with three nested loops
for (int i = 0; i < threeDArray.length; i++) { // For each block
System.out.println("Block " + (i + 1) + ":");
for (int j = 0; j < threeDArray[i].length; j++) { // For each row in the block
for (int k = 0; k < threeDArray[i][j].length; k++) { // For each element in the row
System.out.print(threeDArray[i][j][k] + " ");
}
System.out.println(); // New line after each row
}
System.out.println(); // Extra line between blocks
}
}
}
4. Conclusion
In this lesson, we explored two essential data structures in Java: arrays and vectors.
• Arrays are fixed-size, sequential data structures used to store elements of the same type. We
learned how to declare, instantiate, and initialize arrays, access and modify elements, traverse
arrays with loops, and search using linear and binary search methods.
• Vectors are dynamic arrays that can adjust their size as needed. We covered how to declare and
instantiate vectors, add and access elements, traverse vectors, and search for elements using built-
in methods.
• We also briefly discussed multi-dimensional arrays, which allow for the storage and manipulation
of data in a matrix-like format.
Understanding arrays and vectors is fundamental for writing efficient and effective Java programs that
require storing and processing collections of elements. Master these concepts through hands-on
practice, and you’ll be well prepared for more complex data structures and algorithms.
Week 08 - Lesson: The Java Collections Framework
Learning Objectives
By the end of this lesson, you will be able to:
• Understand the purpose of the Collections Framework in Java.
• Identify different types of collections: Lists, Stacks, Queues, Priority Queues, Sets, and Maps.
• Explain the characteristics and appropriate use cases of each collection type.
• Explore common methods and operations provided by each collection.
• Use iterators to traverse through collection elements.
Key Terms
• Collection: A framework that provides architecture to store and manipulate groups of objects.
• List: An ordered collection that allows duplicate elements.
• Stack: A Last-In, First-Out (LIFO) data structure used to store elements in reverse order of insertion.
• Queue: A First-In, First-Out (FIFO) data structure where the first element added is the first one
removed.
• Priority Queue: A data structure where elements are processed based on their assigned priority
rather than insertion order.
• Set: A collection that stores unique (non-duplicate) elements.
• Map: A collection that stores key-value pairs, where each key is unique.
• Iterator: An object that enables you to traverse the elements of a collection sequentially.
Lesson Content
The Java Collections Framework is a unified architecture for representing and manipulating collections.
It provides interfaces and classes for various data structures (Lists, Sets, Maps, etc.) that improve code
reusability and efficiency. All these classes reside in the java.util package.
2. Lists
A List is an ordered collection that allows duplicate elements. Two common implementations are:
• ArrayList: Uses a dynamic array. It provides fast random access but slower insertion/deletion in the
middle.
Example
import java.util.ArrayList;
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Apple");
arrayList.add("Banana");
System.out.println(arrayList); // Output: [Apple, Banana]
• LinkedList: Uses a doubly linked list. It provides efficient insertion and deletion at any position but
slower random access.
Example
import java.util.LinkedList;
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("Carrot");
linkedList.add("Date");
System.out.println(linkedList); // Output: [Carrot, Date]
3. Stacks
A Stack is a LIFO data structure. The Java Collections Framework includes the legacy Stack class (which
extends Vector) for simple stack operations.
Example
import java.util.Stack;
Stack<Integer> stack = new Stack<>();
stack.push(10);
stack.push(20);
int top = stack.pop(); // Removes 20
System.out.println("Popped element: " + top); // Output: 20
4. Queues
A Queue is a FIFO data structure. The Queue interface has several implementations; two common ones
are LinkedList and PriorityQueue.
• LinkedList as a Queue:
Example
import java.util.Queue;
import java.util.LinkedList;
Queue<String> queue = new LinkedList<>();
queue.add("First");
queue.add("Second");
String head = queue.poll(); // Retrieves and removes "First"
System.out.println("Head of queue: " + head); // Output: First
• PriorityQueue:
Example
import java.util.PriorityQueue;
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.add(30);
pq.add(10);
pq.add(20);
int highestPriority = pq.poll(); // Retrieves and removes the smallest element (10)
System.out.println("Priority element: " + highestPriority); // Output: 10
5. Sets
A Set stores unique elements without duplicates. Common implementations include:
• HashSet: Uses a hash table; fast for basic operations but does not maintain order.
Example
import java.util.HashSet;
HashSet<String> set = new HashSet<>();
set.add("Red");
set.add("Blue");
set.add("Red"); // Duplicate; ignored
System.out.println(set); // Order not guaranteed
Example
import java.util.LinkedHashSet;
Example
import java.util.TreeSet;
6. Maps
A Map stores key-value pairs, with each key unique. Common implementations include:
• HashMap: Uses a hash table; offers fast operations but no ordering.
Example
import java.util.HashMap;
HashMap<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
System.out.println("Map: " + map);
Example
import java.util.LinkedHashMap;
import java.util.Map;
Example
import java.util.TreeMap;
import java.util.Map;
7. Iterators
An Iterator allows you to traverse a collection one element at a time. It is used with most collection types
to safely remove or process elements.
Example
import java.util.ArrayList;
import java.util.Iterator;
ArrayList<String> list = new ArrayList<>();
list.add("Item1");
list.add("Item2");
Conclusion
In this lesson, we examined the Java Collections Framework, an essential toolkit for storing and
manipulating groups of objects. We discussed:
• Queues (FIFO) and Priority Queues for processing elements based on priority.
Understanding these collection types, their characteristics, and common operations will enable you to
write more efficient, maintainable, and flexible Java applications. By selecting the appropriate collection
for your specific task, you can optimize performance and code clarity.