Java 101:从零到高手课程

2025-06-09

Java 101:从零到高手课程

介绍:

你的引言引人入胜,为博客营造了友好的氛围。以下是更正后的版本,为清晰起见,进行了一些细微调整:

欢迎来到 Java 101,我将带您踏上我的 Java 学习之旅。在这篇内容全面的博文中,我们将涵盖 Java 语言所需的一切知识,从设置开发环境到深入学习面向对象编程,再到探索高级概念。

Java 是一种功能强大、用途广泛的编程语言,从构建 Web 应用程序到开发移动应用程序和企业系统,应用范围十分广泛。正因如此,它在我心中占据着特殊的地位。

那么,准备好踏上这段冒险之旅吧,因为这将是我写过的最长的博客文章之一。我的结构如下:

  1. 第 1 部分:基础知识(变量、数据类型、流控制、逻辑运算符……)
  2. 第 2 部分:面向对象编程(类和对象、继承、多态、封装、抽象、接口……)
  3. 第 3 部分:高级 Java 主题(异常、泛型、集合、函数式编程、并发、多线程)

让我们一起深入探索 Java 的世界吧!


第 1 部分 | 语言基础知识

当然!让我们以一种简单易懂的方式分解数据类型的各个部分。

原始数据类型

原始数据类型是 Java 中最基本的数据类型。它们表示没有内部结构的单个值。以下是一些常见的原始数据类型:

  • byte:表示 [-128, 127] 范围内的 1 字节整数。
  • short:表示 [-32,768, 32,767] 范围内的 2 字节整数。
  • int:表示一个 4 字节的大范围内的整数。
  • long:表示范围很广的8字节整数。
  • float:表示4字节浮点数,适用于实数的近似表示。
  • double:表示一个 8 字节的浮点数,与 float 相比提供更高的精度。
  • boolean:表示真值或假值。
  • char:表示单个字符,如“A”、“b”、“%”。

让我们看一些例子:

byte age = 25;
short population = 32000;
int distance = 150000;
long globalPopulation = 7760000000L; // Note the 'L' suffix for long literals

float temperature = 20.5f; // Note the 'f' suffix for float literals
double height = 5.9;

boolean isSunny = true;
char grade = 'A';
Enter fullscreen mode Exit fullscreen mode

在本节中,我们概述了 Java 中各种原始数据类型的大小和范围,并提供了演示其用法的示例。此外,我们还介绍了float用于表示近似精度浮点数的数据类型。

引用数据类型

引用数据类型指的是 Java 中的对象。与原始数据类型不同,它们具有复杂的结构,并且动态存储在内存中。以下是一些引用数据类型的示例:

  • 字符串:表示字符序列,如“Hello, World!”。
  • 数组:表示同一类型的元素的集合。

让我们看看如何使用它们:

String name = "Alice";
int[] numbers = {1, 2, 3, 4, 5};
Enter fullscreen mode Exit fullscreen mode

这里,name是一个存储名称“Alice”的字符串,numbers是一个整数数组。

输入阅读技巧

在 Java 中,我们可以使用该类读取用户的输入Scanner。以下是如何使用它读取整数和字符串:

import java.util.Scanner;

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

        System.out.print("Enter your age: ");
        int age = scanner.nextInt();

        System.out.print("Enter your name: ");
        String name = scanner.next();

        System.out.println("Hello, " + name + "! You are " + age + " years old.");

        scanner.close(); // Don't forget to close the scanner to release resources.
    }
}
Enter fullscreen mode Exit fullscreen mode

运行此程序时,它会提示你输入年龄和姓名。然后,它会打印一条包含你输入值的问候消息。

就是这样!以上就是 Java 数据类型的基础知识,并以简单易懂的方式进行了讲解。欢迎尝试这些示例,加深您的理解!

当然!为了更好地理解,让我们通过代码示例来分解控制流的各个概念:

比较运算符

比较运算符用于比较两个值并返回布尔值。以下是一些常见的比较运算符:

  • 等于 ( ==):如果两个值相等则返回 true。
  • 不等于(!=:如果两个值不相等,则返回 true。
  • 大于(>:如果左操作数大于右操作数,则返回 true。
  • 大于或等于(>=:如果左操作数大于或等于右操作数,则返回 true。
  • 小于(<:如果右操作数大于左操作数,则返回 true。
  • 小于或等于(<=:如果左操作数小于或等于右操作数,则返回 true。
int x = 5;
int y = 10;

System.out.println(x == y);  // Outputs: false
System.out.println(x != y);  // Outputs: true
System.out.println(x > y);   // Outputs: false
System.out.println(x < y);   // Outputs: true
System.out.println(x >= y);  // Outputs: false
System.out.println(x <= y);  // Outputs: true
Enter fullscreen mode Exit fullscreen mode

逻辑运算符

逻辑运算符用于对布尔表达式执行逻辑运算。以下是常见的逻辑运算符:

  • AND ( &&):如果两个操作数都为真,则返回真。
  • 或(||:如果至少有一个操作数为真,则返回真。
  • NOT ( !):返回操作数的布尔值的反面。
boolean isSunny = true;
boolean isWarm = false;

System.out.println(isSunny && isWarm);  // Outputs: false
System.out.println(isSunny || isWarm);  // Outputs: true
System.out.println(!isSunny);           // Outputs: false
Enter fullscreen mode Exit fullscreen mode

条件语句(if、else-if、else)

条件语句用于根据特定条件执行不同的代码块。

int age = 20;

if (age >= 18) {
    System.out.println("You are an adult.");
} else if (age >= 13) {
    System.out.println("You are a teenager.");
} else {
    System.out.println("You are a child.");
}
Enter fullscreen mode Exit fullscreen mode

三元运算符

三元运算符是编写 if-else 语句的简写方式。

int num = 10;
String result = (num % 2 == 0) ? "even" : "odd";
System.out.println(result);  // Outputs: even
Enter fullscreen mode Exit fullscreen mode

Switch 语句

Switch 语句允许我们根据变量的值执行不同的代码块。

int day = 3;
String dayName;

switch (day) {
    case 1:
        dayName = "Monday";
        break;
    case 2:
        dayName = "Tuesday";
        break;
    // ...
    default:
        dayName = "Invalid day";
}

System.out.println("Today is " + dayName);
Enter fullscreen mode Exit fullscreen mode

迭代语句

迭代语句用于重复执行一段代码。

For 循环
for (int i = 1; i <= 5; i++) {
    System.out.println("Count: " + i);
}
Enter fullscreen mode Exit fullscreen mode
增强的 For Each 循环
int[] numbers = {1, 2, 3, 4, 5};

for (int num : numbers) {
    System.out.println(num);
}
Enter fullscreen mode Exit fullscreen mode
While 循环
int i = 1;
while (i <= 5) {
    System.out.println("Count: " + i);
    i++;
}
Enter fullscreen mode Exit fullscreen mode
Do-While 循环
int j = 1;
do {
    System.out.println("Count: " + j);
    j++;
} while (j <= 5);
Enter fullscreen mode Exit fullscreen mode

锻炼

现在,我们完成了 Java 基础知识的学习,让我们把目前学到的所有知识打包成一个漂亮、简单、基本的计算器

import java.util.Scanner;

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

        System.out.println("Welcome to the Simple Calculator!");
        System.out.println("Please enter the first number:");
        double num1 = scanner.nextDouble();

        System.out.println("Please enter the second number:");
        double num2 = scanner.nextDouble();

        System.out.println("Select operation:");
        System.out.println("1. Addition (+)");
        System.out.println("2. Subtraction (-)");
        System.out.println("3. Multiplication (*)");
        System.out.println("4. Division (/)");

        int choice = scanner.nextInt();
        double result = 0;

        switch (choice) {
            case 1:
                result = num1 + num2;
                break;
            case 2:
                result = num1 - num2;
                break;
            case 3:
                result = num1 * num2;
                break;
            case 4:
                if (num2 != 0) {
                    result = num1 / num2;
                } else {
                    System.out.println("Error! Division by zero is not allowed.");
                    return;
                }
                break;
            default:
                System.out.println("Invalid choice!");
                return;
        }

        System.out.println("Result: " + result);

        scanner.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

第 2 部分 | Java 中的面向对象编程

Java 确实是一种多功能的编程语言,它支持多种编程范式,包括过程式、函数式和面向对象编程 (OOP)。然而,OOP 范式是 Java 中的主要范式,因为它专注于将现实世界的实体建模为具有属性(数据)和行为(方法)的对象。

让我们一起深入了解 Java 中 OOP 世界的不同概念和方面。

当然!让我们用简单的语言、类比和大量的代码示例来分解每个主题。

理解类和对象

可以将类想象成一张蓝图,将对象想象成基于该蓝图构建的事物。例如,“汽车”类定义了汽车是什么(包括颜色、品牌、型号等属性,以及驾驶和鸣笛等行为),而对象则是基于该蓝图构建的一辆具体的汽车。

创建和实例化类

要创建类,您需要定义其属性和行为。要创建对象,您需要使用类蓝图。以下是一个类的示例以及如何从中创建对象:

// Class definition
class Car {
    String color;
    String make;
    String model;

    void drive() {
        System.out.println("The car is driving.");
    }
}

// Creating an object
Car myCar = new Car();
Enter fullscreen mode Exit fullscreen mode

封装

封装就像把你的东西放在一个盒子里,只允许特定的人访问。在 Java 中,你可以隐藏类的内部工作原理,只允许通过特定的方法(例如 getter 和 setter 方法)进行访问。

class BankAccount {
    private double balance;

    // Getter method
    public double getBalance() {
        return balance;
    }

    // Setter method
    public void setBalance(double amount) {
        balance = amount;
    }
}
Enter fullscreen mode Exit fullscreen mode

抽象

抽象就像驾驶汽车,但无需了解引擎的工作原理。你可以通过汽车(对象)的接口(方法)与其交互,而无需了解其内部实现。

构造函数

构造函数就像一个用来创建对象的特殊配方。它们在创建对象时初始化对象的状态。以下是一个例子:

class Dog {
    String breed;

    // Constructor
    public Dog(String dogBreed) {
        breed = dogBreed;
    }
}
Enter fullscreen mode Exit fullscreen mode

多态性

多态就像一个变形器。一个对象可以根据其上下文呈现不同的形态。方法重载就是一个例子:

class MathOperations {
    // Method overloading
    public int add(int x, int y) {
        return x + y;
    }

    public double add(double x, double y) {
        return x + y;
    }
}
Enter fullscreen mode Exit fullscreen mode

遗产

继承就像将特征从父类传递给子类。子类会从其超类继承属性和行为。例如:

class Animal {
    void eat() {
        System.out.println("The animal is eating.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("The dog is barking.");
    }
}
Enter fullscreen mode Exit fullscreen mode

静态成员

静态成员就像类中所有对象共享的资源。它们属于类本身,而不是任何特定的对象。例如:

class Circle {
    static final double PI = 3.14;

    static double calculateArea(double radius) {
        return PI * radius * radius;
    }
}
Enter fullscreen mode Exit fullscreen mode

当然!让我们通过详细的解释、代码示例和类比来深入探讨 Java 继承的各个方面。

继承概述

继承就像将父母的特性传递给孩子。在 Java 中,它允许一个类(子类)从另一个类(超类)继承属性和行为。这促进了代码重用,并有助于组织和管理相关的类。

Object类及其核心方法

在 Java 中,每个类都隐式地扩展了该类ObjectObject该类提供了一些所有类都可用的核心方法。其中一些方法包括:

  • toString():返回对象的字符串表示形式。
  • equals(Object obj):表示其他对象是否“等于”该对象。
  • hashCode():返回对象的哈希码值。
class MyClass {
    int value;

    // toString method override
    @Override
    public String toString() {
        return "Value: " + value;
    }
}

MyClass obj = new MyClass();
obj.value = 10;
System.out.println(obj.toString());  // Outputs: Value: 10
Enter fullscreen mode Exit fullscreen mode

对象比较

Java 提供了equals()比较对象相等性的方法。默认情况下,它比较内存引用。但是,您可以在类中重写此方法,以提供自定义的比较逻辑。

class Person {
    String name;
    int age;

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null || getClass() != obj.getClass())
            return false;
        Person person = (Person) obj;
        return age == person.age && Objects.equals(name, person.name);
    }
}
Enter fullscreen mode Exit fullscreen mode

方法覆盖

方法重写允许子类提供其超类中已定义方法的特定实现。这对于提供特定行为非常有用。

class Animal {
    void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Dog barks");
    }
}
Enter fullscreen mode Exit fullscreen mode

抽象类

抽象类就像其他类的蓝图。它们本身不能被实例化,但可以具有必须由子类实现的抽象方法。

abstract class Shape {
    abstract double area();
}

class Circle extends Shape {
    double radius;

    @Override
    double area() {
        return Math.PI * radius * radius;
    }
}
Enter fullscreen mode Exit fullscreen mode

最终课程

Final 类就像成品一样,无法修改或扩展。您无法创建 Final 类的子类。

final class FinalClass {
    // Class definition
}

// Error: Cannot inherit from final class
class SubClass extends FinalClass {
}
Enter fullscreen mode Exit fullscreen mode

Java中的接口

可以将接口视为类必须遵循的契约或一组规则。它定义了实现类必须提供的方法列表,但本身不包含任何实现。

// Interface definition
interface Animal {
    void makeSound();
    void eat();
}

// Implementing class
class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }

    @Override
    public void eat() {
        System.out.println("Dog eats bones");
    }
}
Enter fullscreen mode Exit fullscreen mode

在这个例子中,Animal接口定义了两个方法:makeSound()eat()Dog类根据接口指定的契约来实现这些方法Animal

主要功能和使用场景

接口提供了几个关键功能,通常用于各种场景:

  • 多重继承:与类不同,Java 类可以实现多个接口。这允许类从多个来源继承行为。
interface Flyable {
    void fly();
}

class Bird implements Animal, Flyable {
    // Implement methods from both Animal and Flyable interfaces
}
Enter fullscreen mode Exit fullscreen mode
  • 多态性:接口支持多态行为,允许将对象视为其接口类型的实例。这提高了灵活性和代码可重用性。
void performAction(Animal animal) {
    animal.makeSound();
    animal.eat();
}
Enter fullscreen mode Exit fullscreen mode
  • 松耦合:接口有助于系统组件之间的松耦合。类之间通过接口而不是具体的实现进行交互,从而使系统更加模块化,更易于维护。
interface DataAccess {
    void saveData(String data);
}

class DatabaseAccess implements DataAccess {
    @Override
    public void saveData(String data) {
        // Save data to the database
    }
}

class FileAccess implements DataAccess {
    @Override
    public void saveData(String data) {
        // Save data to a file
    }
}
Enter fullscreen mode Exit fullscreen mode

在这个例子中,不同的类可以实现DataAccess接口来提供不同的数据保存方式,例如保存到数据库或文件。

接口是 Java 编程中强大的工具,它提供了定义契约、实现多态行为以及促进组件之间松散耦合的方法。接口对于构建模块化、灵活且易于维护的软件系统至关重要。

锻炼

使用我们在本节中学到的有关 Java 中的 OOP 的所有知识,让我们以面向对象的风格重建我们的计算器:

// Interface for basic calculator operations
interface Calculator {
    double calculate(double num1, double num2);
}

// Addition operation
class Addition implements Calculator {
    @Override
    public double calculate(double num1, double num2) {
        return num1 + num2;
    }
}

// Subtraction operation
class Subtraction implements Calculator {
    @Override
    public double calculate(double num1, double num2) {
        return num1 - num2;
    }
}

// Multiplication operation
class Multiplication implements Calculator {
    @Override
    public double calculate(double num1, double num2) {
        return num1 * num2;
    }
}

// Division operation
class Division implements Calculator {
    @Override
    public double calculate(double num1, double num2) {
        if (num2 != 0) {
            return num1 / num2;
        } else {
            throw new IllegalArgumentException("Error! Division by zero is not allowed.");
        }
    }
}

// Calculator class encapsulating calculator operations
class BasicCalculator {
    private Calculator calculator;

    public BasicCalculator(Calculator calculator) {
        this.calculator = calculator;
    }

    public double performCalculation(double num1, double num2) {
        return calculator.calculate(num1, num2);
    }
}

public class CalculatorApp {
    public static void main(String[] args) {
        BasicCalculator calculator = new BasicCalculator(new Addition());
        double result = calculator.performCalculation(10, 5);
        System.out.println("Addition Result: " + result);

        calculator = new BasicCalculator(new Subtraction());
        result = calculator.performCalculation(10, 5);
        System.out.println("Subtraction Result: " + result);

        calculator = new BasicCalculator(new Multiplication());
        result = calculator.performCalculation(10, 5);
        System.out.println("Multiplication Result: " + result);

        calculator = new BasicCalculator(new Division());
        result = calculator.performCalculation(10, 5);
        System.out.println("Division Result: " + result);
    }
}
Enter fullscreen mode Exit fullscreen mode

第 3 部分 | 高级 Java 主题

异常处理?

异常是指 Java 程序运行时可能发生的意外事件。就像你在玩游戏时突然发生意外事件,例如断电或控制器电池耗尽。

检查异常:

这些就像是你可以预见的警告信号。就像知道如果你在室内玩球,它可能会损坏某些东西。所以,你会通过更加小心地玩来应对。在 Java 中,你必须处理这类异常,要么捕获它们,要么声明你的方法可能会抛出它们。

未经检查的异常:

这些是你始料未及的意外惊喜。就像赤脚走路时不小心踩到乐高积木一样。哎哟!这些异常并非强制显式处理,但你仍然应该尝试处理它们,以确保程序安全。

Try-Catch 块:

想象一下你正在接一个球。你伸出双手,试图接住它,如果接不住,球就会掉到地上。在 Java 中,你会尝试try执行一些可能引发异常的操作,catch如果发生异常,你就会抛出异常,就像接住一个球以防止它掉到地上一样。

try {
    // Code that might throw an exception
} catch (ExceptionType e) {
    // Code to handle the exception
}
Enter fullscreen mode Exit fullscreen mode

最后阻止:

这就像一张安全网。无论发生什么,这段代码总是会运行。就像玩完玩具后要清理一下一样。在 Java 中,它用来finally确保某些代码无论是否发生异常都会被执行。

try {
    // Code that might throw an exception
} catch (ExceptionType e) {
    // Code to handle the exception
} finally {
    // Code that always runs
}
Enter fullscreen mode Exit fullscreen mode

投掷和投掷:

有时你想成为引发异常的人。这就像说:“我不玩了,我要把球扔回去。” 在 Java 中,你习惯于throw手动抛出异常。throws这就像把责任推卸给别人。你声明你的方法可能会抛出某种类型的异常,然后留给调用者去处理。

void myMethod() throws MyException {
    // Code that might throw MyException
}

// Somewhere else in the code
try {
    myMethod();
} catch (MyException e) {
    // Handle MyException
}
Enter fullscreen mode Exit fullscreen mode

泛型:

Java 中的泛型就像神奇的容器,可以容纳任何类型的数据。它们为您的代码提供了灵活性和类型安全性,确保您可以无缝地处理不同类型的数据。让我们深入探索泛型的神奇世界!

类中的泛型:

想象一下,一个宝箱里可以装下各种宝藏——金币、珍贵宝石或古代文物。在 Java 中,你可以使用 创建泛型类<T>,其中T表示类型参数。

public class TreasureChest<T> {
    private T treasure;

    public void store(T item) {
        this.treasure = item;
    }

    public T retrieve() {
        return this.treasure;
    }
}
Enter fullscreen mode Exit fullscreen mode

方法中的泛型:

现在,设想一根魔杖可以对任何物体施法。在 Java 中,您可以创建操作不同类型数据的泛型方法,从而增强代码的可重用性和灵活性。

public class Magic {
    public <T> void castSpell(T target) {
        // Perform magic on the target
    }
}
Enter fullscreen mode Exit fullscreen mode

通配符:

Java 泛型中的通配符就像特殊的透镜,能让你从不同的视角审视代码。让我们深入泛型的丛林,揭开通配符的秘密!

上限通配符 ( <? extends T>):

想象一下一张神奇的网,可以捕获所有具有特定特征的生物。在 Java 中,<? extends T>可以捕获所有 子类型的对象T,从而让您能够处理各种各样的数据。

public void feedHerbivores(List<? extends Animal> herbivores) {
    // Feed the herbivores
}
Enter fullscreen mode Exit fullscreen mode

下界通配符(<? super T>):

现在,想象一下一道抵御特定危险的防护屏障。在 Java 中,<? super T>为通配符指定下限,并捕获所有 的超类对象T,从而确保代码的安全。

public void protectAgainstPredators(List<? super Lion> protections) {
    // Set up protections against predators
}
Enter fullscreen mode Exit fullscreen mode

通用方法:

就像熟练的魔术师可以用一根魔杖表演各种魔术一样,Java 中的泛型方法可以对不同类型的数据进行操作,从而增强代码的灵活性和多功能性。

public <T> void performAction(T item) {
    // Perform action on the item
}
Enter fullscreen mode Exit fullscreen mode

具有多个类型参数的泛型类:

想象一下一张藏宝图,上面有多个线索,指向隐藏的宝藏。在 Java 中,你可以创建具有多个类型参数的泛型类,从而可以同时处理各种类型的数据。

public class TreasureMap<X, Y> {
    private X clue1;
    private Y clue2;

    // Constructor, getters, and setters
}
Enter fullscreen mode Exit fullscreen mode

收藏:

想象一下,你正在执行一项任务,收集散落在魔法王国的稀世珍宝。Java 集合就像你值得信赖的背包,配备了特殊的隔层来存储和整理你的珍宝。无论是闪闪发光的宝石、古老的文物还是神秘的药水,Java 中的集合都提供了一种灵活的方式来管理和操作你的数据。

集合只是接口!:

在 Java 中,集合由各种接口表示,每个接口都有其独特的特性和功能。可以把接口想象成不同类型的背包的蓝图,每个背包都有其特定的用途。

List<String> backpack = new ArrayList<>();  // A backpack for storing a list of treasures
Set<Integer> pouch = new HashSet<>();       // A pouch for storing unique treasures
Map<String, Integer> chest = new HashMap<>();// A chest for storing treasures with keys
Enter fullscreen mode Exit fullscreen mode

收藏类型:

列表:

想象一下,一串珍宝整齐地排列成一排,就像书架上的书一样。在 Java 中,列表允许你按特定顺序存储元素集合,以便于访问和操作它们。

List<String> backpack = new ArrayList<>();
backpack.add("Golden Sword");
backpack.add("Enchanted Ring");
backpack.add("Magic Potion");
Enter fullscreen mode Exit fullscreen mode
套:

现在想象一下一组独一无二的宝藏,就像一组稀有宝石。在 Java 中,集合确保每个元素都是唯一的,从而防止重复并提供快速检索。

Set<String> pouch = new HashSet<>();
pouch.add("Ruby");
pouch.add("Emerald");
pouch.add("Sapphire");
Enter fullscreen mode Exit fullscreen mode
地图:

最后,设想一张藏宝图,上面有线索指向隐藏的宝藏。在 Java 中,地图将键与值关联起来,这样你就可以根据它们的唯一标识符来检索宝藏。

Map<String, Integer> chest = new HashMap<>();
chest.put("Gold Coins", 100);
chest.put("Silver Bars", 50);
chest.put("Diamonds", 10);
Enter fullscreen mode Exit fullscreen mode

迭代集合:

就像探索王国的广阔景观一样,您可以使用迭代器遍历集合,沿途发现宝藏。

for (String treasure : backpack) {
    System.out.println("Found: " + treasure);
}
Enter fullscreen mode Exit fullscreen mode

对集合进行排序:

想象一下,你把你的宝藏按价值从低到高排列起来。在 Java 中,你可以使用比较器对集合进行排序,确保你的宝藏得到高效的整理。

Collections.sort(backpack);
Enter fullscreen mode Exit fullscreen mode

操作集合:

现在设想将两个集合合并起来,创建一个更大的宝藏集合。在 Java 中,你可以使用各种方法来操作集合,例如合并、过滤和转换。

List<String> additionalTreasures = new ArrayList<>();
additionalTreasures.add("Magic Wand");
backpack.addAll(additionalTreasures);
Enter fullscreen mode Exit fullscreen mode

函数式编程:

想象一下,你是一位魔法王国的巫师,挥舞着强大的法术,操控着自然的力量。Java 中的函数式编程就像掌握了古老的施法技艺,让你能够轻松地对数据进行强大的转换。

Lambda 表达式:

在 Java 中,lambda 表达式就像魔法咒语,允许您封装行为并将函数作为参数传递给其他方法。

// Traditional way of defining a Runnable
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, world!");
    }
};

// Using lambda expression
Runnable runnable = () -> {
    System.out.println("Hello, world!");
};
Enter fullscreen mode Exit fullscreen mode

供应商:

想象一下,一位神秘的店主,他能凭空变出你想要的任何物品。在 Java 中,供应商就像这位店主一样,提供了一种在需要时延迟生成或提供值的方法。

Supplier<Integer> randomNumber = () -> (int) (Math.random() * 100);
System.out.println(randomNumber.get());  // Output: A random number between 0 and 100
Enter fullscreen mode Exit fullscreen mode

谓词:

想象一下,你是一位睿智的巫师,一眼就能辨别真假。在 Java 中,谓词就像你的魔眼,可以让你测试条件,并根据条件过滤元素。

Predicate<Integer> isEven = num -> num % 2 == 0;
System.out.println(isEven.test(4));  // Output: true
System.out.println(isEven.test(5));  // Output: false
Enter fullscreen mode Exit fullscreen mode

消费者:

现在,想象一下一位仁慈的仙女,她会消除你的烦恼,给你留下一片宁静。在 Java 中,消费者就像这位仙女一样,接受值并执行操作,但不返回任何值。

Consumer<String> printUpperCase = str -> System.out.println(str.toUpperCase());
printUpperCase.accept("magic");  // Output: MAGIC
Enter fullscreen mode Exit fullscreen mode

功能:

最后,想象一下一位神奇的炼金术士,能将一种物质转化为另一种物质。在 Java 中,函数就像这位炼金术士,接受一个输入,并根据某种变换产生另一个输出。

Function<Integer, String> convertToString = num -> "Number: " + num;
System.out.println(convertToString.apply(42));  // Output: Number: 42
Enter fullscreen mode Exit fullscreen mode

Java 流:

在 Java 中,流是元素序列,支持各种方法来对这些元素执行操作。可以将它们想象成流经数据的神奇管道,允许你对流经的每个元素执行操作。

流中的函数式接口

流使用函数式接口来执行其工作。这些接口(例如消费者、谓词、供应商和函数)为可传递给流操作的行为提供了蓝图。

流中的消费者:

消费者就像神奇的观察者,接受单个输入并执行某些操作而不返回任何内容。在流中,消费者用于执行终端操作,即消费流中的元素。

List<String> ingredients = Arrays.asList("Eye of newt", "Wing of bat", "Tooth of wolf");

// Printing each ingredient using a consumer
ingredients.stream()
           .forEach(System.out::println);
Enter fullscreen mode Exit fullscreen mode

流中的谓词:

谓词就像神奇的过滤器,可以测试条件并返回 true 或 false。在流中,谓词用于根据特定条件过滤元素。

// Filtering ingredients that contain "bat"
ingredients.stream()
           .filter(ingredient -> ingredient.contains("bat"))
           .forEach(System.out::println);
Enter fullscreen mode Exit fullscreen mode

流中的供应商:

供应商就像神奇的提供者,在需要时惰性生成或提供值。在流中,供应商并不常用,但它们在某些流操作中发挥着作用。

// Generating a stream of random numbers using a supplier
Stream<Integer> randomNumberStream = Stream.generate(() -> (int) (Math.random() * 100));
Enter fullscreen mode Exit fullscreen mode

流中的函数:

函数就像神奇的变压器,接受一个输入,并根据某种转换产生另一个输出。在流中,函数用于将元素映射到另一种形式。

// Converting ingredients to uppercase using a function
ingredients.stream()
           .map(String::toUpperCase)
           .forEach(System.out::println);
Enter fullscreen mode Exit fullscreen mode

并发和多线程:

并发是程序同时执行多个任务的能力,允许它一次执行多个任务。

什么是线程?

线程就像船上的独立水手,每个水手负责执行一项特定的任务。在 Java 中,你可以创建和管理线程来并发执行任务。

创建线程:

在 Java 中,可以通过扩展 Thread 类或实现 Runnable 接口来创建线程。让我们创建一个打印消息的简单线程。

class MyThread extends Thread {
    public void run() {
        System.out.println("Hello from MyThread!");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // Start the thread
    }
}
Enter fullscreen mode Exit fullscreen mode

实现 Runnable:

或者,您可以实现 Runnable 接口并将其传递给 Thread 对象。

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from MyRunnable!");
    }
}

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start(); // Start the thread
    }
}
Enter fullscreen mode Exit fullscreen mode

同步:

想象一下,你的水手们试图同时访问一个共享资源,比如一个宝箱。Java 中的同步机制确保同一时间只有一个线程可以访问代码的关键部分,从而避免冲突并确保线程安全。

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}
Enter fullscreen mode Exit fullscreen mode

执行者:

可以将执行器视为管理者,负责监督一组水手(线程)并高效地为他们分配任务。执行器为管理线程和异步执行任务提供了更高级别的抽象。

ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(new MyTask());
executor.shutdown();
Enter fullscreen mode Exit fullscreen mode

结论

在本指南中,我们深入讲解了 Java 编程的基本概念,探索了面向对象编程 (OOP) 的复杂性,并深入探讨了能够充分释放 Java 潜力的高级主题。从设置开发环境到掌握控制流、类、对象、继承、接口等,您已经对 Java 的核心原理和特性有了深入的理解。

随着我们结束对 Java 101 的探索,很明显,你在成为一名熟练的 Java 程序员的道路上已经取得了长足的进步。掌握了这些知识,你将能够应对现实世界中的编码挑战,并满怀信心地开展激动人心的项目。

但旅程并未就此结束。在接下来的冒险中,我们将深入探索数据结构和算法的迷人世界——它们是计算机科学和软件开发的基石。我们将携手揭开数据组织、算法效率和问题解决技巧的奥秘,将您的编程技能提升到新的高度。

所以,敬请期待我们的下一章,我们将继续探索编程和软件开发领域的精髓。在此之前,请继续编码,继续学习,让你对 Java 的热情点燃你迈向卓越的旅程!

鏂囩珷鏉ユ簮锛�https://dev.to/louaiboumediene/java-101-zero-to-hero-course-4jna
PREV
我开发了我的第一个 JS 游戏!🎉
NEXT
追求愉快的开发者协作