Skip to content

Latest commit

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Learn Java

Welcome to the comprehensive Java course. Java is a versatile, object-oriented programming language.

Table of contents

What is Java?

Java is a high-level, class-based, object-oriented programming language designed to have as few implementation dependencies as possible.

Key Characteristics

  • Platform Independent: "Write Once, Run Anywhere"
  • Object-Oriented: Everything is an object
  • Strongly Typed: Compile-time type checking
  • Garbage Collection: Automatic memory management
  • Multithreaded: Built-in support for concurrent programming
  • Secure: No pointer arithmetic

Why learn Java?

1. Enterprise Applications

Java is the language of choice for enterprise software.

2. Android Development

Java and Kotlin are primary languages for Android.

3. Web Applications

Spring framework powers millions of applications.

4. Big Data

Hadoop and Spark are built with Java.

5. Career Opportunities

High demand in job market.

Installation and Setup

JDK Installation

Download from oracle.com or use Adoptium:

java --version
javac --version

IDE Options

  • IntelliJ IDEA - Most popular
  • Eclipse - Feature-rich
  • VS Code - Lightweight with extensions
  • NetBeans - Free and open source

Creating a Project

mkdir MyProject &&cd MyProject
mkdir -p src/main/java/com/example

Running Java

javac MyClass.java
java MyClass

Maven/Gradle

<!-- pom.xml (Maven) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>

Hello World

publicclassHelloWorld {
publicstaticvoidmain(String[] args) {
System.out.println("Hello, World!");
}
}

Modern Java (14+) multiline strings:

Stringmessage = """ This is a multiline string """;

Variables and Data Types

Primitive Types

// Integersbyteb = 127; // 8-bitshorts = 32767; // 16-bitinti = 2147483647; // 32-bitlongl = 9223372036854775807L; // 64-bit// Floating pointfloatf = 3.14f; // 32-bit (suffix f)doubled = 3.14159; // 64-bit// Characterscharc = 'A';
// Booleansbooleanflag = true;

Reference Types

Stringname = "John";
Integerwrapped = 42;
Objectobj = newObject();

Type Inference (var)

varname = "John"; // Compiler infers Stringvarage = 30; // Compiler infers intvarlist = newArrayList<String>();

Constants

finaldoublePI = 3.14159;
finalintMAX_SIZE = 100;

Default Values

inti = 0; // 0booleanb = false; // falsecharc = '\u0000'; // null characterdoubled = 0.0; // 0.0Strings = null; // null

Operators

Arithmetic

inta = 10, b = 3;
System.out.println(a + b); // 13System.out.println(a - b); // 7System.out.println(a * b); // 30System.out.println(a / b); // 3 (integer division)System.out.println(a % b); // 1 (modulus)

Comparison

System.out.println(5 == 5); // trueSystem.out.println(5 != 3); // trueSystem.out.println(5 > 3); // trueSystem.out.println(5 >= 5); // trueSystem.out.println(5 < 3); // falseSystem.out.println(5 <= 5); // true

Logical

System.out.println(true && false); // falseSystem.out.println(true || false); // trueSystem.out.println(!true); // false

Bitwise

System.out.println(5 & 3); // 1System.out.println(5 | 3); // 7System.out.println(5 ^ 3); // 6System.out.println(~5); // -6System.out.println(4 << 1); // 8System.out.println(4 >> 1); // 2System.out.println(4 >>> 1); // 2

Ternary

intage = 20;
Stringstatus = age >= 18 ? "Adult" : "Minor";

Flow Control

If/Else

intscore = 85;
if (score >= 90) {
System.out.println("A grade");
} elseif (score >= 80) {
System.out.println("B grade");
} elseif (score >= 70) {
System.out.println("C grade");
} else {
System.out.println("Need improvement");
}

Switch

Stringday = "Monday";
switch (day) {
case"Monday":
case"Tuesday":
case"Wednesday":
case"Thursday":
case"Friday":
System.out.println("Weekday");
break;
case"Saturday":
case"Sunday":
System.out.println("Weekend");
break;
default:
System.out.println("Invalid day");
}

Switch Expression (Java 14+)

Stringresult = switch (day) {
case"Saturday", "Sunday" -> "Weekend";
case"Monday" -> "Start of work week";
default -> "Weekday";
};

For Loop

for (inti = 0; i < 5; i++) {
System.out.println(i);
}
// Enhanced for loopString[] fruits = {"Apple", "Banana", "Cherry"};
for (Stringfruit : fruits) {
System.out.println(fruit);
}

While Loop

intcount = 0;
while (count < 5) {
System.out.println(count);
count++;
}
// Do-whileinti = 0;
do {
System.out.println(i);
i++;
} while (i < 5);

Loop Control

for (inti = 0; i < 10; i++) {
if (i == 5)
break; // Exit loopif (i == 2)
continue; // Skip iterationSystem.out.println(i);
}

Methods

Basic Method

publicstaticStringgreet(Stringname) {
return"Hello, " + name + "!";
}

Parameters

// Variable argumentspublicstaticintsum(int... numbers) {
inttotal = 0;
for (intn : numbers) {
total += n;
}
returntotal;
}
// Method overloadingpublicstaticintadd(inta, intb) {
returna + b;
}
publicstaticdoubleadd(doublea, doubleb) {
returna + b;
}

Return Types

publicstaticbooleanisEven(intn) {
returnn % 2 == 0;
}
publicstaticvoidprintMessage(Stringmsg) {
System.out.println(msg);
}

Recursion

publicstaticintfactorial(intn) {
if (n <= 1) return1;
returnn * factorial(n - 1);
}

Static vs Instance

publicclassMathHelper {
publicstaticintadd(inta, intb) { // Staticreturna + b;
}
publicintmultiply(inta, intb) { // Instancereturna * b;
}
}
// Usageintsum = MathHelper.add(1, 2);
MathHelperhelper = newMathHelper();
intproduct = helper.multiply(3, 4);

Strings

Creating Strings

Strings1 = "Hello";
Strings2 = newString("Hello");
Strings3 = """ Multi-line string """;

String Methods

Strings = " Hello, World! ";
s.trim() // "Hello, World!"s.strip() // "Hello, World!" (Unicode aware)s.toUpperCase() // " HELLO, WORLD! "s.toLowerCase() // " hello, world! "s.replace("World", "Java")
s.replaceAll("\\s+", " ") // Regex replaces.split(",") // [" Hello", " World! "]s.contains("Hello") // trues.startsWith(" H") // trues.endsWith("! ") // trues.indexOf("World") // 9s.substring(2, 7) // "Hello"s.charAt(0) // ' 's.length() // 16

StringBuilder

StringBuildersb = newStringBuilder();
sb.append("Hello");
sb.append(" World");
sb.insert(5, " there");
sb.delete(5, 11);
sb.replace(0, 5, "Hi");
sb.reverse();
sb.setLength(0);
Stringresult = sb.toString();

String Formatting

Stringname = "John";
intage = 30;
// printfSystem.out.printf("Name: %s, Age: %d%n", name, age);
// formattedStrings = String.format("Name: %s, Age: %d", name, age);
// Text blocks (Java 15+)Stringjson = """ { "name": "John", "age": 30 } """;

String Pool

Strings1 = "Hello"; // Uses string poolStrings2 = "Hello"; // Same referenceStrings3 = newString("Hello"); // New objectSystem.out.println(s1 == s2); // trueSystem.out.println(s1 == s3); // falseSystem.out.println(s1.equals(s3)); // true

Arrays

Creating Arrays

int[] numbers = {1, 2, 3, 4, 5};
int[] zeros = newint[5]; // All zerosString[] names = newString[]{"John", "Jane"};
// Multi-dimensionalint[][] matrix = {
{1, 2, 3},
{4, 5, 6}
};
int[][][] cube = newint[2][3][4];

Array Methods

int[] arr = {5, 2, 8, 1, 9};
Arrays.sort(arr);
Arrays.sort(arr, 1, 4); // Partial sortArrays.fill(arr, 0); // Fill allArrays.copyOf(arr, 10); // Copy with new sizeArrays.equals(arr1, arr2);
Arrays.binarySearch(arr, 5);
intidx = Arrays.binarySearch(arr, 5);

Arrays Utility

importjava.util.Arrays;
String[] names = {"Charlie", "Alice", "Bob"};
Arrays.sort(names);
Arrays.sort(names, Collections.reverseOrder());
int[][] matrix = newint[3][4];
Arrays.fill(matrix, 0);

ArrayList

Creating ArrayList

importjava.util.ArrayList;
ArrayList<String> list = newArrayList<>();
ArrayList<String> list2 = newArrayList<>(20);
ArrayList<String> list3 = newArrayList<>(Arrays.asList("A", "B", "C"));

ArrayList Methods

ArrayList<String> list = newArrayList<>();
list.add("Apple"); // Add to endlist.add(0, "Banana"); // Insert at indexlist.addAll(Arrays.asList("Cherry", "Date"));
list.set(0, "Blueberry"); // UpdateStringfirst = list.get(0);
list.remove(0); // Remove at indexlist.remove("Apple"); // Remove by valuelist.clear(); // Remove allbooleanexists = list.contains("Date");
intidx = list.indexOf("Cherry");
intsize = list.size();
booleanempty = list.isEmpty();
list.sort(Comparator.naturalOrder());
list.sort(Comparator.reverseOrder());

Converting

ArrayList<String> list = newArrayList<>(Arrays.asList("A", "B", "C"));
// To arrayString[] arr = list.toArray(newString[0]);
String[] arr2 = list.toArray(String[]::new);
// To collectionList<String> list2 = newArrayList<>(list);

LinkedList

Creating LinkedList

importjava.util.LinkedList;
LinkedList<String> list = newLinkedList<>();
LinkedList<Integer> numbers = newLinkedList<>();

LinkedList Methods

LinkedList<String> list = newLinkedList<>();
list.add("First");
list.addFirst("Start");
list.addLast("End");
list.offer("Offered"); // Add at endlist.push("Pushed"); // Add at frontStringfirst = list.getFirst();
Stringlast = list.getLast();
Stringremoved = list.removeFirst();
Stringpolled = list.poll(); // Remove and return null if emptyStringpeeked = list.peek(); // View without removing

ArrayList vs LinkedList

// ArrayList - Fast random access, slow insertions/removalsArrayList<String> arrayList = newArrayList<>();
// LinkedList - Fast insertions/removals, slow random accessLinkedList<String> linkedList = newLinkedList<>();

HashMap

Creating HashMap

importjava.util.HashMap;
HashMap<String, Integer> map = newHashMap<>();
HashMap<String, Integer> map2 = newHashMap<>(16, 0.75f);
HashMap<String, Integer> map3 = newHashMap<>(Map.of("A", 1, "B", 2));

HashMap Methods

HashMap<String, Integer> map = newHashMap<>();
map.put("One", 1);
map.putIfAbsent("Two", 2);
map.putAll(Map.of("Three", 3, "Four", 4));
Integervalue = map.get("One");
IntegervalueOrDefault = map.getOrDefault("Five", 0);
map.remove("One");
map.clear();
booleanexists = map.containsKey("Two");
booleanhasValue = map.containsValue(2);
intsize = map.size();
booleanempty = map.isEmpty();
map.replace("Two", 2, 3); // Conditional replace

Iterating

HashMap<String, Integer> map = newHashMap<>();
map.put("A", 1);
map.put("B", 2);
// Keysfor (Stringkey : map.keySet()) {
System.out.println(key);
}
// Valuesfor (Integerval : map.values()) {
System.out.println(val);
}
// Entriesfor (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Lambdamap.forEach((k, v) -> System.out.println(k + ": " + v));

HashSet

Creating HashSet

importjava.util.HashSet;
HashSet<String> set = newHashSet<>();
HashSet<Integer> numbers = newHashSet<>(Arrays.asList(1, 2, 3));

HashSet Methods

HashSet<String> set = newHashSet<>();
set.add("Apple");
set.addAll(Arrays.asList("Banana", "Cherry"));
set.remove("Apple");
set.clear();
booleanexists = set.contains("Banana");
intsize = set.size();
booleanempty = set.isEmpty();

Set Operations

HashSet<Integer> a = newHashSet<>(Arrays.asList(1, 2, 3, 4));
HashSet<Integer> b = newHashSet<>(Arrays.asList(3, 4, 5, 6));
a.addAll(b); // Uniona.retainAll(b); // Intersectiona.removeAll(b); // Difference// New setsSet<Integer> union = newHashSet<>(a);
union.addAll(b);
Set<Integer> intersection = newHashSet<>(a);
intersection.retainAll(b);
Set<Integer> difference = newHashSet<>(a);
difference.removeAll(b);

Classes and Objects

Basic Class

publicclassPerson {
// FieldsprivateStringname;
privateintage;
// ConstructorpublicPerson(Stringname, intage) {
this.name = name;
this.age = age;
}
// Getters and SetterspublicStringgetName() { returnname; }
publicvoidsetName(Stringname) { this.name = name; }
publicintgetAge() { returnage; }
publicvoidsetAge(intage) { this.age = age; }
// MethodpublicStringgreet() {
return"Hello, I'm " + name;
}
// toString@OverridepublicStringtoString() {
return"Person{name='" + name + "', age=" + age + "}";
}
}
// UsagePersonp = newPerson("John", 30);
p.greet();

Records (Java 16+)

publicrecordPerson(Stringname, intage) {
// Auto-generates:// - All fields// - Canonical constructor// - toString, equals, hashCode// - getter methods (name(), age())// Custom compact constructorpublicPerson {
if (age < 0) thrownewIllegalArgumentException();
}
}
// UsagePersonp = newPerson("John", 30);
p.name(); // "John"p.age(); // 30

Encapsulation

publicclassBankAccount {
privatedoublebalance;
publicdoublegetBalance() { returnbalance; }
publicvoiddeposit(doubleamount) {
if (amount > 0) balance += amount;
}
publicbooleanwithdraw(doubleamount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
returntrue;
}
returnfalse;
}
}

Static Members

publicclassMathUtils {
publicstaticfinaldoublePI = 3.14159;
publicstaticintadd(inta, intb) {
returna + b;
}
static {
// Static initializer
}
}
// Usageintsum = MathUtils.add(1, 2);
doublepi = MathUtils.PI;

Nested Classes

publicclassOuter {
privateStringouterField = "Outer";
publicclassInner {
privateStringinnerField = "Inner";
publicvoiddisplay() {
System.out.println(outerField); // Can access outer
}
}
publicstaticclassStaticNested {
// Cannot access outer instance
}
}

Inheritance

Basic Inheritance

publicclassAnimal {
protectedStringname;
publicAnimal(Stringname) {
this.name = name;
}
publicvoidspeak() {
System.out.println("...");
}
}
publicclassDogextendsAnimal {
privateStringbreed;
publicDog(Stringname, Stringbreed) {
super(name); // Call parent constructorthis.breed = breed;
}
@Overridepublicvoidspeak() {
System.out.println("Woof!");
}
}

super Keyword

publicclassChildextendsParent {
publicChild() {
super(); // Call parent constructor
}
publicvoidmethod() {
super.parentMethod(); // Call parent method
}
}

Method Overriding

publicclassParent {
publicvoiddisplay() { }
}
publicclassChildextendsParent {
@Overridepublicvoiddisplay() { } // Must have same signature@Overridepublicfinalvoidfixed() { } // Cannot override
}

Sealed Classes (Java 17+)

publicsealedclassShape permits Circle, Rectangle, Square {
}
publicfinalclassCircleextendsShape { }
publicsealedclassRectangleextendsShape permits ColoredRectangle { }
publicnon-sealedclassSquareextendsShape { }

Interfaces

Basic Interface

publicinterfaceDrawable {
voiddraw(); // Abstract method// Java 8+: Default methoddefaultvoidprint() {
System.out.println("Printing...");
}
// Java 8+: Static methodstaticvoidreset() {
System.out.println("Reset");
}
}

Implementing Interface

publicclassCircleimplementsDrawable {
@Overridepublicvoiddraw() {
System.out.println("Drawing circle");
}
}
// Multiple interfacespublicclassButtonimplementsClickable, Focusable {
@Overridepublicvoidclick() { }
@Overridepublicvoidfocus() { }
}

Functional Interface

@FunctionalInterfacepublicinterfaceConverter<T, R> {
Rconvert(Tinput);
// Can have default methodsdefaultvoidlog(Stringmsg) {
System.out.println(msg);
}
}
// Usage with lambdaConverter<String, Integer> converter = Integer::parseInt;

Interface Inheritance

publicinterfaceA {
voidmethodA();
}
publicinterfaceBextendsA {
voidmethodB();
}

Abstract Classes

Basic Abstract Class

publicabstractclassShape {
protectedStringcolor;
publicShape(Stringcolor) {
this.color = color;
}
// Abstract method - must be implementedpublicabstractdoublegetArea();
// Concrete methodpublicStringgetColor() {
returncolor;
}
}
publicclassCircleextendsShape {
privatedoubleradius;
publicCircle(Stringcolor, doubleradius) {
super(color);
this.radius = radius;
}
@OverridepublicdoublegetArea() {
returnMath.PI * radius * radius;
}
}

Abstract vs Interface

// Use abstract class when:// - Sharing code/state between related classes// - Need constructors// - Non-static fields// Use interface when:// - Define capabilities/contracts// - Multiple inheritance needed// - Lambda expressions (functional interfaces)

Records

Basic Record

publicrecordPerson(Stringname, intage) { }
// Auto-generates:// - private final fields// - Canonical constructor// - toString(), equals(), hashCode()// - name(), age() getter methodsPersonp = newPerson("John", 30);
p.name(); // "John"p.age(); // 30

Record with Validation

publicrecordPerson(Stringname, intage) {
publicPerson {
if (age < 0) thrownewIllegalArgumentException();
name = name.strip();
}
}

Record with Methods

publicrecordRange(intstart, intend) {
publicRange {
if (start > end) {
thrownewIllegalArgumentException();
}
}
publicintgetSize() {
returnend - start;
}
publicbooleancontains(intvalue) {
returnvalue >= start && value <= end;
}
}

Enums

Basic Enum

publicenumDay {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
// UsageDaytoday = Day.MONDAY;
Stringname = today.name();
intordinal = today.ordinal();

Enum with Values

publicenumStatus {
SUCCESS(200, "Success"),
ERROR(500, "Error"),
NOT_FOUND(404, "Not Found");
privatefinalintcode;
privatefinalStringmessage;
Status(intcode, Stringmessage) {
this.code = code;
this.message = message;
}
publicintgetCode() { returncode; }
publicStringgetMessage() { returnmessage; }
publicstaticStatusfromCode(intcode) {
for (Statuss : values()) {
if (s.code == code) returns;
}
returnnull;
}
}

Enum Methods

enumSeason {
SPRING, SUMMER, AUTUMN, WINTER;
publicbooleanisWarm() {
returnthis == SUMMER || this == SPRING;
}
}

Exception Handling

Try/Catch/Finally

try {
intresult = 10 / 0;
} catch (ArithmeticExceptione) {
System.out.println("Cannot divide by zero: " + e.getMessage());
} catch (Exceptione) {
System.out.println("Error: " + e);
} finally {
System.out.println("Always executes");
}

Try with Resources (Java 7+)

try (FileReaderreader = newFileReader("file.txt");
BufferedReaderbr = newBufferedReader(reader)) {
Stringline;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} // Auto-closes resources

Throwing Exceptions

publicvoidvalidateAge(intage) throwsIllegalArgumentException {
if (age < 0) {
thrownewIllegalArgumentException("Age cannot be negative");
}
}

Custom Exceptions

publicclassValidationExceptionextendsException {
privatefinalStringfield;
publicValidationException(Stringfield, Stringmessage) {
super(message);
this.field = field;
}
publicStringgetField() { returnfield; }
}

Exception Hierarchy

Throwable
├── Error (system errors)
│ ├── OutOfMemoryError
│ └── StackOverflowError
└── Exception
├── RuntimeException (unchecked)
│ ├── NullPointerException
│ ├── IllegalArgumentException
│ └── IndexOutOfBoundsException
└── IOException, SQLException (checked)

File Handling

Reading Files

importjava.nio.file.*;
importjava.io.*;
try (BufferedReaderreader = Files.newBufferedReader(Paths.get("file.txt"))) {
Stringline;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}

Writing Files

importjava.nio.file.*;
Stringcontent = "Hello, World!";
Files.writeString(Paths.get("output.txt"), content);
List<String> lines = Arrays.asList("Line 1", "Line 2");
Files.write(Paths.get("output.txt"), lines);

File Operations

Pathpath = Paths.get("document.pdf");
booleanexists = Files.exists(path);
booleanisFile = Files.isRegularFile(path);
booleanisDir = Files.isDirectory(path);
longsize = Files.size(path);
FileTimecreated = Files.getAttribute(path, "creationTime");
FileTimemodified = Files.getLastModifiedTime(path);
Files.copy(from, to);
Files.move(from, to);
Files.delete(path);
Files.createDirectory(path);
Files.walk(path).forEach(System.out::println);

Lambda Expressions

Basic Syntax

// TraditionalComparator<String> comp = newComparator<>() {
@Overridepublicintcompare(Stringa, Stringb) {
returna.compareTo(b);
}
};
// LambdaComparator<String> comp = (a, b) -> a.compareTo(b);
// Single parameter, can omit parenthesesFunction<String, Integer> parser = s -> Integer.parseInt(s);
// Block bodyFunction<String, Integer> parser = s -> {
intresult = Integer.parseInt(s);
returnresult;
};

Method Reference

// Static methodFunction<String, Integer> parser = Integer::parseInt;
// Instance methodStringstr = "hello";
Supplier<Integer> len = str::length;
// Arbitrary instance methodFunction<String, String> upper = String::toUpperCase;
// ConstructorSupplier<ArrayList<String>> listFactory = ArrayList::new;
Function<Integer, String[]> arrayFactory = String[]::new;

Common Functional Interfaces

Predicate<String> isEmpty = s -> s.isEmpty();
Function<String, Integer> length = String::length;
Consumer<String> printer = System.out::println;
Supplier<String> supplier = () -> "default";
UnaryOperator<String> upper = String::toUpperCase;
BinaryOperator<Integer> add = Integer::sum;

Streams API

Creating Streams

importjava.util.stream.*;
// From collectionlist.stream();
list.parallelStream();
// From arrayArrays.stream(array);
// From valuesStream.of("a", "b", "c");
// Infinite streamStream.iterate(0, n -> n + 2).limit(10);
Stream.generate(() -> Math.random()).limit(5);

Intermediate Operations

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n % 2 == 0) // Filter
.map(n -> n * 2) // Transform
.distinct() // Remove duplicates
.sorted() // Sort
.sorted(Comparator.reverseOrder())
.limit(3) // Take first n
.skip(2) // Skip first n
.peek(System.out::println) // Debug

Terminal Operations

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.forEach(System.out::println) // Execute for each
.collect(Collectors.toList()) // To collection
.toArray() // To array
.reduce(0, Integer::sum) // Reduce to single value
.count() // Count elements
.anyMatch(n -> n > 3) // Any match
.allMatch(n -> n > 0) // All match
.noneMatch(n -> n < 0) // None match
.findFirst() // First element
.findAny() // Any element
.min(Comparator.naturalOrder()) // Minimum
.max(Comparator.naturalOrder()) // Maximum

Collectors

.collect(Collectors.toList())
.collect(Collectors.toSet())
.collect(Collectors.toMap(k, v))
.collect(Collectors.toCollection(TreeSet::new))
.collect(Collectors.joining(", "))
.collect(Collectors.counting())
.collect(Collectors.summingInt(n -> n))
.collect(Collectors.averagingInt(n -> n))
.collect(Collectors.groupingBy(Function.identity()))
.collect(Collectors.partitioningBy(predicate))
.collect(Collectors.mapping(mapper, downstream))

Optional

Creating Optional

Optional<String> empty = Optional.empty();
Optional<String> of = Optional.of("value");
Optional<String> nullable = Optional.ofNullable(null);

Optional Methods

Optional<String> opt = Optional.of("hello");
opt.isPresent(); // trueopt.isEmpty(); // falseopt.get(); // "hello"opt.orElse("default"); // "hello"opt.orElseGet(() -> "computed"); // Lazy defaultopt.orElseThrow(); // Throw NoSuchElementExceptionopt.ifPresent(System.out::println);
opt.ifPresentOrElse(
System.out::println,
() -> System.out.println("Empty")
);
// Transformopt.map(String::toUpperCase);
opt.filter(s -> s.length() > 3);
opt.flatMap(opt -> Optional.of(opt.toLowerCase()));

Optional in Streams

list.stream()
.filter(Objects::nonNull)
.findFirst()
.orElse("default");

Generics

Generic Class

publicclassBox<T> {
privateTcontent;
publicvoidset(Tcontent) { this.content = content; }
publicTget() { returncontent; }
}
Box<Integer> intBox = newBox<>();
intBox.set(42);
Integervalue = intBox.get();

Generic Method

publicstatic <T> voidprintArray(T[] array) {
for (Telement : array) {
System.out.println(element);
}
}
Integer[] nums = {1, 2, 3};
String[] names = {"A", "B"};
printArray(nums);
printArray(names);

Generic Constraints

// Must be Comparablepublicstatic <TextendsComparable<T>> Tmax(Ta, Tb) {
returna.compareTo(b) > 0 ? a : b;
}
// Must be Number or subclasspublicstaticdoublesum(List<? extendsNumber> list) {
returnlist.stream()
.mapToDouble(Number::doubleValue)
.sum();
}
// Producer extends, consumer super (PECS)publicvoidaddAll(List<? extendsE> from, List<? superE> to) {
to.addAll(from);
}

Wildcards

List<?> anyList = newArrayList<String>(); // UnknownList<? extendsNumber> numbers = newArrayList<Integer>(); // Upper boundList<? superInteger> integers = newArrayList<Number>(); // Lower bound

Annotations

Built-in Annotations

@Override// Override from superclass/interface@Deprecated// Mark as deprecated@SuppressWarnings// Suppress compiler warnings@FunctionalInterface// Must be single abstract method@SafeVarargs// Varargs are safe

Custom Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Author {
Stringname();
Stringdate();
Stringversion() default"1.0";
}
@Author(name = "John", date = "2024-01-01")
publicclassMyClass { }

Reflection with Annotations

Method[] methods = MyClass.class.getMethods();
for (Methodm : methods) {
if (m.isAnnotationPresent(Author.class)) {
Authorauthor = m.getAnnotation(Author.class);
System.out.println(author.name());
}
}

Multithreading

Creating Threads

// Extend ThreadclassMyThreadextendsThread {
@Overridepublicvoidrun() {
System.out.println("Running in thread");
}
}
MyThreadt = newMyThread();
t.start();
// Implement RunnableRunnabler = () -> System.out.println("Running via Runnable");
newThread(r).start();

ExecutorService

ExecutorServiceexecutor = Executors.newFixedThreadPool(4);
Future<Integer> future = executor.submit(() -> {
// Taskreturn42;
});
Integerresult = future.get(); // Blockingexecutor.shutdown();

Synchronization

// Synchronized methodpublicsynchronizedvoidincrement() { count++; }
// Synchronized blockpublicvoidincrement() {
synchronized (this) {
count++;
}
}
// ReentrantLockprivatefinalReentrantLocklock = newReentrantLock();
publicvoidincrement() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}

CompletableFuture

CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenApply(String::toUpperCase);
Stringresult = future.join();

Modules

Module Declaration

// module-info.javamodulecom.example.myapp {
requiresjava.base;
requirestransitiveorg.apache.commons.lang3;
exportscom.example.myapp.api;
exportscom.example.myapp.model;
openscom.example.myapp.internaltocom.example.other;
}

Using Modules

modulecom.example.myapp {
requirescom.example.library;
usescom.example.library.Service; // Service lookup
}

Next Steps

Now that you know Java fundamentals:

  • Learn Spring Framework for web development
  • Explore Spring Boot for quick application setup
  • Build REST APIs with Spring MVC
  • Learn Hibernate for database operations
  • Explore microservices with Spring Cloud
  • Study design patterns

References

About

A Comprehensive Java course

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors