Java编程实战:从核心概念到现代特性,精选代码示例与深入解析246

 

作为一名专业的程序员,我深知Java语言在软件开发领域的地位举足轻重。它以其“一次编写,到处运行”的跨平台特性、强大的面向对象能力、丰富的生态系统和卓越的性能,成为了企业级应用、大数据、Android开发乃至科学计算等多个领域的首选。本篇文章将通过一系列精选的Java示范代码,从基础概念入手,逐步深入到面向对象编程、集合框架、异常处理、文件I/O以及现代Java(Java 8+)的Stream API等核心特性,旨在为您提供一份全面且实用的Java编程实践指南。

1. Java基础:Hello World与基本数据类型

任何编程语言的学习都从“Hello World”开始,Java也不例外。它展示了Java程序的基本结构。public class HelloWorld {
public static void main(String[] args) {
// 打印字符串到控制台
("Hello, Java World!");
// 基本数据类型示例
int age = 30; // 整型
double salary = 50000.50; // 双精度浮点型
boolean isActive = true; // 布尔型
char initial = 'J'; // 字符型
String name = "Alice"; // 字符串(非基本类型,但常用)
("姓名: " + name + ", 年龄: " + age + ", 薪水: " + salary);
}
}


这段代码定义了一个名为`HelloWorld`的公共类,其中包含一个`main`方法。`main`方法是Java程序的入口点,`()`用于向控制台输出信息。随后,我们展示了Java的几种基本数据类型及其使用。

2. 面向对象编程 (OOP) 核心

Java是一种纯粹的面向对象语言。理解类、对象、封装、继承和多态是掌握Java的关键。

2.1 类与对象 (Class & Object)


类是对象的蓝图,对象是类的实例。以下是一个简单的`Car`类及其对象的创建。public class Car {
// 属性(成员变量)
String brand;
String model;
int year;
String color;
// 构造方法:用于创建对象时初始化属性
public Car(String brand, String model, int year, String color) {
= brand;
= model;
= year;
= color;
}
// 方法(行为)
public void startEngine() {
(brand + " " + model + " 的引擎启动了!");
}
public void displayInfo() {
("品牌: " + brand + ", 型号: " + model + ", 年份: " + year + ", 颜色: " + color);
}
public static void main(String[] args) {
// 创建Car类的对象(实例化)
Car myCar = new Car("Toyota", "Camry", 2022, "蓝色");
();
();
Car yourCar = new Car("Honda", "Civic", 2020, "红色");
();
}
}


`Car`类定义了汽车的属性(`brand`, `model`, `year`, `color`)和行为(`startEngine`, `displayInfo`)。通过`new Car(...)`,我们创建了两个不同的`Car`对象。

2.2 继承 (Inheritance)


继承允许一个类(子类)从另一个类(父类)继承属性和方法,实现代码复用。public class ElectricCar extends Car { // ElectricCar 继承自 Car
private int batteryCapacity; // 电动车特有的属性
public ElectricCar(String brand, String model, int year, String color, int batteryCapacity) {
super(brand, model, year, color); // 调用父类的构造方法
= batteryCapacity;
}
// 重写父类的方法
@Override
public void startEngine() {
(brand + " " + model + " 的电机启动了,悄无声息!");
}
// 电动车特有的方法
public void charge() {
(brand + " " + model + " 正在充电,电池容量:" + batteryCapacity + " kWh.");
}
public static void main(String[] args) {
ElectricCar tesla = new ElectricCar("Tesla", "Model 3", 2023, "白色", 75);
(); // 调用父类方法
(); // 调用子类重写的方法
(); // 调用子类特有方法
Car genericCar = new Car("Ford", "Focus", 2021, "银色");
(); // 调用父类方法
}
}


`ElectricCar`继承了`Car`的所有属性和非私有方法,并添加了自己的特有属性`batteryCapacity`和方法`charge`。它还通过`@Override`注解重写了`startEngine`方法,展示了子类可以修改父类行为的能力。

2.3 多态 (Polymorphism)


多态允许将子类对象当作父类对象处理,提高代码的灵活性和可扩展性。public class VehicleShowroom {
public static void main(String[] args) {
Car myCar = new Car("BMW", "X5", 2023, "黑色");
ElectricCar myElectricCar = new ElectricCar("BYD", "汉", 2024, "灰色", 80);
// 使用父类类型引用指向子类对象,这就是多态
Car car1 = myCar;
Car car2 = myElectricCar; // 多态:Car类型的引用指向ElectricCar对象
("展示第一辆车:");
();
(); // 调用Car类的startEngine方法
("展示第二辆车(电动车):");
();
(); // 调用ElectricCar重写的startEngine方法 (运行时多态)
// 也可以将所有车辆放入一个数组或列表中
Car[] cars = new Car[3];
cars[0] = new Car("大众", "高尔夫", 2022, "白色");
cars[1] = new ElectricCar("蔚来", "ET7", 2023, "蓝色", 100);
cars[2] = new Car("奥迪", "A4", 2021, "银色");
("展示所有车辆:");
for (Car car : cars) {
();
();
// 如果要调用ElectricCar特有的方法,需要进行类型转换
if (car instanceof ElectricCar) {
((ElectricCar) car).charge();
}
("-----");
}
}
}


在`VehicleShowroom`中,`Car car2 = myElectricCar;`是多态的典型应用。尽管`car2`是`Car`类型,但它实际引用的是`ElectricCar`对象。当调用`()`时,Java虚拟机(JVM)会根据实际对象的类型(`ElectricCar`)来执行其重写的方法,这就是运行时多态(或动态绑定)。

2.4 接口 (Interface) 与抽象类 (Abstract Class)


接口和抽象类是实现抽象和多态的重要机制。/* 接口定义 */
interface Drivable {
void drive(); // 接口方法默认是 public abstract
void stop();
// Java 8 之后,接口可以有 default 方法和 static 方法
default void honk() {
("发出喇叭声!");
}
}
/* 抽象类定义 */
abstract class Shape {
private String name;
public Shape(String name) {
= name;
}
public String getName() {
return name;
}
// 抽象方法:没有方法体,必须由子类实现
public abstract double calculateArea();
// 普通方法
public void displayShapeName() {
("这是一个 " + name);
}
}
/* 实现接口的类 */
class SportsCar extends Car implements Drivable {
public SportsCar(String brand, String model, int year, String color) {
super(brand, model, year, color);
}
@Override
public void drive() {
(brand + " " + model + " 正在高速驾驶!");
}
@Override
public void stop() {
(brand + " " + model + " 紧急制动。");
}
}
/* 继承抽象类的具体实现 */
class Circle extends Shape {
private double radius;
public Circle(double radius) {
super("圆形");
= radius;
}
@Override
public double calculateArea() {
return * radius * radius;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
super("矩形");
= width;
= height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class AbstractionDemo {
public static void main(String[] args) {
// 使用接口
SportsCar ferrari = new SportsCar("Ferrari", "488", 2023, "红色");
();
();
(); // 调用接口的default方法
();
("--------------------");
// 使用抽象类
Shape circle = new Circle(5.0);
Shape rectangle = new Rectangle(4.0, 6.0);
();
(() + " 的面积是: " + ());
();
(() + " 的面积是: " + ());
// 抽象类不能直接实例化
// Shape s = new Shape("Generic"); // 编译错误
}
}


`Drivable`接口定义了驾驶相关的行为,`SportsCar`类实现了它。`Shape`抽象类定义了所有形状的通用属性和计算面积的抽象方法,`Circle`和`Rectangle`类继承并实现了它。

3. 集合框架 (Collections Framework)

Java集合框架提供了一套高性能、可复用的数据结构,用于存储和操作对象。

3.1 List (ArrayList)


`List`是有序的集合,允许重复元素,`ArrayList`是其常用实现。import ;
import ;
public class ListDemo {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>(); // 创建一个字符串列表
("Apple");
("Banana");
("Orange");
("Apple"); // List允许重复元素
("原始列表: " + fruits);
// 访问元素
("第一个水果: " + (0));
// 修改元素
(1, "Grape");
("修改后的列表: " + fruits);
// 删除元素
("Apple"); // 删除第一个匹配的"Apple"
("删除一个Apple后: " + fruits);
(0); // 删除索引为0的元素 (现在的第一个是Grape)
("删除索引0后: " + fruits);
// 遍历列表
("遍历列表:");
for (String fruit : fruits) {
("- " + fruit);
}
("列表大小: " + ());
("是否包含Orange: " + ("Orange"));
("是否为空: " + ());
(); // 清空列表
("清空后列表: " + fruits);
}
}


`ArrayList`提供了动态数组的功能,可以方便地添加、删除、访问和修改元素。

3.2 Set (HashSet)


`Set`是无序的集合,不允许重复元素,`HashSet`是其常用实现。import ;
import ;
public class SetDemo {
public static void main(String[] args) {
Set<Integer> numbers = new HashSet<>(); // 创建一个整数集合
(10);
(20);
(30);
(20); // 重复元素不会被添加
("集合中的元素: " + numbers); // 顺序可能与添加顺序不同
// 尝试添加已存在的元素
boolean added = (10);
("尝试再次添加10,是否成功: " + added); // false
("集合中的元素 (未变): " + numbers);
// 删除元素
(30);
("删除30后: " + numbers);
// 检查元素是否存在
("是否包含20: " + (20)); // true
("是否包含50: " + (50)); // false
// 遍历集合
("遍历集合:");
for (Integer num : numbers) {
("- " + num);
}
}
}


`HashSet`通过哈希表实现,提供了快速的查找、添加和删除操作,并确保元素的唯一性。

3.3 Map (HashMap)


`Map`存储键值对,键是唯一的,值可以重复,`HashMap`是其常用实现。import ;
import ;
public class MapDemo {
public static void main(String[] args) {
Map<String, String> capitals = new HashMap<>(); // 创建一个键值对映射
// 添加键值对
("Japan", "Tokyo");
("France", "Paris");
("Germany", "Berlin");
("Japan", "Kyoto"); // 键已存在,会覆盖旧值
("国家与首都映射: " + capitals);
// 获取值
("法国的首都: " + ("France"));
("日本的首都: " + ("Japan")); // 被覆盖后的值
// 检查键或值是否存在
("是否包含键 Spain: " + ("Spain"));
("是否包含值 Berlin: " + ("Berlin"));
// 删除键值对
("Germany");
("删除德国后: " + capitals);
// 遍历Map
("遍历所有国家和首都:");
for (<String, String> entry : ()) {
("国家: " + () + ", 首都: " + ());
}
("只遍历键:");
for (String country : ()) {
("国家: " + country);
}
("只遍历值:");
for (String capital : ()) {
("首都: " + capital);
}
}
}


`HashMap`提供了基于哈希表的键值对存储,允许通过键快速查找对应的值。

4. 异常处理 (Exception Handling)

异常是程序运行时发生的非正常事件。Java通过`try-catch-finally`块来优雅地处理异常,增强程序的健壮性。import ;
import ;
import ;
public class ExceptionHandlingDemo {
public static void main(String[] args) {
// 示例1: 算术异常 (ArithmeticException)
try {
int result = 10 / 0; // 试图除以零
("结果: " + result); // 这行代码不会被执行
} catch (ArithmeticException e) {
("捕获到算术异常: " + ());
// (); // 打印完整的堆栈跟踪
} finally {
("算术异常处理的 finally 块总是执行。");
}
("--------------------");
// 示例2: 数组越界异常 (ArrayIndexOutOfBoundsException)
int[] numbers = {1, 2, 3};
try {
("尝试访问索引3的元素: " + numbers[3]);
} catch (ArrayIndexOutOfBoundsException e) {
("捕获到数组越界异常: " + ());
}
("--------------------");
// 示例3: 文件读取异常 (IOException) - 使用 try-with-resources (Java 7+)
// 假设有一个名为 "" 的文件不存在
String filePath = "";
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = ()) != null) {
("读取到行: " + line);
}
} catch (IOException e) {
("文件读取错误: " + ());
("请确保文件 '" + filePath + "' 存在并可读。");
} finally {
("文件操作的 finally 块总是执行 (即使在try-with-resources中,此块依然会执行)。");
}
("--------------------");
// 示例4: 自定义异常 (Custom Exception)
try {
validateAge(5);
validateAge(25);
} catch (InvalidAgeException e) {
("自定义异常捕获: " + ());
}
}
// 自定义异常类
static class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
// 抛出自定义异常的方法
public static void validateAge(int age) throws InvalidAgeException {
if (age < 18 || age > 60) {
throw new InvalidAgeException("年龄必须在 18 到 60 之间,当前年龄: " + age);
}
("年龄 " + age + " 有效。");
}
}


这个例子展示了如何处理不同类型的异常,包括运行时异常(`ArithmeticException`)、检查型异常(`IOException`,通过`try-with-resources`自动关闭资源),以及如何定义和抛出自定义异常。`finally`块确保无论是否发生异常,其中的代码都会被执行。

5. 文件I/O (File Input/Output)

文件I/O是程序与外部数据交互的重要方式。我们将演示如何读写文本文件。import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class FileIODemo {
private static final String FILE_NAME = "";
private static final String NEW_FILE_NAME = "";
public static void main(String[] args) {
// 写入文件
writeTextToFile(FILE_NAME, "这是第一行文本。");
appendTextToFile(FILE_NAME, "这是追加的第二行文本。");
appendTextToFile(FILE_NAME, "这是第三行。");
// 读取文件
readTextFromFile(FILE_NAME);
("--------------------");
// Java Nio.2 (Java 7+) 更简洁的文件操作
Path path = (NEW_FILE_NAME);
try {
// 写入多行
List<String> lines = ("Hello from NIO!", "This is the second line.", "End of file.");
(path, lines);
("文件 '" + NEW_FILE_NAME + "' 写入成功 (使用NIO.2)。");
// 读取所有行
("读取文件 '" + NEW_FILE_NAME + "' 内容 (使用NIO.2):");
List<String> readLines = (path);
for (String line : readLines) {
(line);
}
// 删除文件
(path);
("文件 '" + NEW_FILE_NAME + "' 已删除。");
} catch (IOException e) {
("NIO.2文件操作错误: " + ());
}
}
// 使用 BufferedWriter 写入文件 (覆盖)
public static void writeTextToFile(String fileName, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
(content);
("内容已写入文件: " + fileName);
} catch (IOException e) {
("写入文件错误: " + ());
}
}
// 使用 BufferedWriter 追加内容到文件
public static void appendTextToFile(String fileName, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName, true))) { // true 表示追加模式
(content);
("内容已追加到文件: " + fileName);
} catch (IOException e) {
("追加内容到文件错误: " + ());
}
}
// 使用 BufferedReader 读取文件
public static void readTextFromFile(String fileName) {
("正在读取文件: " + fileName);
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = ()) != null) {
(">> " + line);
}
("文件读取完毕。");
} catch (IOException e) {
("读取文件错误: " + ());
}
}
}


此示例演示了传统的`BufferedReader`和`BufferedWriter`进行文件读写,以及Java 7引入的NIO.2 `Files`工具类,后者提供了更简洁、更强大的文件操作功能。`try-with-resources`确保文件流被正确关闭。

6. Java 8+ 新特性:Stream API

Stream API是Java 8引入的一项重大特性,它提供了函数式编程风格来处理集合数据,使得集合操作更加简洁、高效。import ;
import ;
import ;
import ;
class Person {
private String name;
private int age;
private String city;
public Person(String name, int age, String city) {
= name;
= age;
= city;
}
public String getName() { return name; }
public int getAge() { return age; }
public String getCity() { return city; }
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + ", city='" + city + '\'' + '}';
}
}
public class StreamAPIDemo {
public static void main(String[] args) {
List<Person> people = (
new Person("Alice", 30, "New York"),
new Person("Bob", 25, "London"),
new Person("Charlie", 35, "New York"),
new Person("David", 20, "Paris"),
new Person("Eve", 30, "London")
);
("原始数据: " + people);
// 示例1: 过滤 (filter) - 找出所有年龄大于25的人
List<Person> adults = ()
.filter(p -> () > 25)
.collect(());
("年龄大于25的人: " + adults);
// 示例2: 映射 (map) - 获取所有人的姓名,并转换为大写
List<String> namesUpperCase = ()
.map(p -> ().toUpperCase())
.collect(());
("所有人大写姓名: " + namesUpperCase);
// 示例3: 排序 (sorted) - 按年龄升序排序
List<Person> sortedByAge = ()
.sorted((p1, p2) -> ((), ()))
.collect(());
("按年龄排序: " + sortedByAge);
// 示例4: 聚合 (reduce/sum/count/average) - 计算所有人的平均年龄
double averageAge = ()
.mapToInt(Person::getAge) // 转换为 IntStream 以便使用 average()
.average()
.orElse(0.0); // 如果流为空,则返回0.0
("平均年龄: " + averageAge);
// 示例5: 分组 (groupingBy) - 按城市分组
Map<String, List<Person>> peopleByCity = ()
.collect((Person::getCity));
("按城市分组: " + peopleByCity);
// 示例6: 链式操作 - 找出New York地区年龄大于28的人的姓名,并去重
List<String> uniqueNamesInNY = ()
.filter(p -> "New York".equals(()))
.filter(p -> () > 28)
.map(Person::getName)
.distinct() // 去除重复
.collect(());
("纽约地区年龄大于28且去重后的姓名: " + uniqueNamesInNY);
}
}


Stream API通过`filter`、`map`、`sorted`、`collect`等中间操作和终止操作,提供了强大的数据处理能力。它使代码更具可读性、表达力和并行性。

本文从Java的基础“Hello World”出发,逐步深入探讨了面向对象编程的核心概念(类、对象、继承、多态、接口、抽象类),接着介绍了Java集合框架(List、Set、Map)的使用,以及异常处理和文件I/O的最佳实践。最后,我们领略了Java 8引入的Stream API如何以函数式风格简化数据处理。这些示范代码覆盖了Java开发中的大多数基础和常用场景,希望能帮助您更好地理解和应用Java语言。

学习编程是一个持续实践的过程。建议您亲手运行这些代码,修改参数,甚至尝试实现自己的小功能。通过不断的探索和练习,您将能够更熟练地驾驭Java这门强大而灵活的语言,构建出高质量的软件应用。

2025-11-03


上一篇:Java与大数据:从核心到实战的深度解析与未来展望

下一篇:Java数据持久化与查询深度解析:从JDBC到Spring Data的实践指南