引言

Java作为一种广泛使用的编程语言,自1995年由Sun Microsystems(现为Oracle公司)发布以来,已经发展成为企业级应用、移动开发(Android)、大数据处理和云计算等领域的首选语言之一。Java的“一次编写,到处运行”(Write Once, Run Anywhere)特性得益于其Java虚拟机(JVM),使得Java程序可以在任何支持JVM的平台上运行。本指南旨在为初学者提供一个从基础语法到高级概念,再到实际项目实战的全面学习路径,帮助读者逐步掌握Java编程的核心技能。

第一部分:Java基础语法

1.1 环境搭建与第一个程序

在开始编写Java代码之前,需要安装Java开发工具包(JDK)和一个集成开发环境(IDE),如IntelliJ IDEA或Eclipse。JDK包含了编译和运行Java程序所需的所有工具。

安装步骤:

  1. 访问Oracle官网或OpenJDK项目下载适合您操作系统的JDK版本(推荐JDK 17或更高版本)。
  2. 安装JDK并配置环境变量(JAVA_HOME和PATH)。
  3. 下载并安装IntelliJ IDEA Community Edition(免费版)。

第一个Java程序:Hello World

创建一个名为HelloWorld.java的文件,内容如下:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

代码解释:

  • public class HelloWorld:定义一个公共类,类名必须与文件名一致。
  • public static void main(String[] args):这是Java程序的入口方法。public表示可访问,static表示静态方法,void表示无返回值,String[] args是命令行参数。
  • System.out.println("Hello, World!");:在控制台输出一行文本。

编译与运行:

  • 在命令行中,进入文件所在目录,执行javac HelloWorld.java编译代码,生成HelloWorld.class字节码文件。
  • 执行java HelloWorld运行程序,输出”Hello, World!“。

1.2 数据类型与变量

Java是强类型语言,变量在使用前必须声明其类型。Java的数据类型分为基本数据类型和引用数据类型。

基本数据类型:

  • 整数类型:byte(1字节)、short(2字节)、int(4字节)、long(8字节,后缀L)。
  • 浮点类型:float(4字节,后缀F)、double(8字节,后缀D)。
  • 字符类型:char(2字节,用于存储Unicode字符)。
  • 布尔类型:boolean(true或false)。

变量声明与初始化:

int age = 25;          // 整数变量
double salary = 5000.50; // 浮点变量
char grade = 'A';      // 字符变量
boolean isStudent = true; // 布尔变量

常量: 使用final关键字声明常量,值不可更改。

final double PI = 3.14159;

1.3 运算符与表达式

Java支持多种运算符,包括算术、关系、逻辑、位运算符等。

算术运算符:

int a = 10, b = 3;
int sum = a + b;      // 13
int difference = a - b; // 7
int product = a * b;  // 30
int quotient = a / b; // 3(整数除法)
double remainder = a % b; // 1.0(取余)

关系运算符:

boolean isEqual = (a == b); // false
boolean isGreater = (a > b); // true

逻辑运算符:

boolean condition1 = true;
boolean condition2 = false;
boolean andResult = condition1 && condition2; // false
boolean orResult = condition1 || condition2;  // true
boolean notResult = !condition1;             // false

三元运算符:

int max = (a > b) ? a : b; // 如果a大于b,返回a,否则返回b

1.4 控制流语句

控制流语句用于控制程序的执行顺序。

条件语句:

  • if-else语句:
int score = 85;
if (score >= 90) {
    System.out.println("优秀");
} else if (score >= 80) {
    System.out.println("良好");
} else {
    System.out.println("及格");
}
  • switch语句(Java 12+支持增强型switch):
int dayOfWeek = 3;
String dayName = switch (dayOfWeek) {
    case 1 -> "星期一";
    case 2 -> "星期二";
    case 3 -> "星期三";
    case 4 -> "星期四";
    case 5 -> "星期五";
    case 6 -> "星期六";
    case 7 -> "星期日";
    default -> "无效";
};
System.out.println(dayName); // 输出:星期三

循环语句:

  • for循环:
// 打印1到10的数字
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}
  • while循环:
int count = 1;
while (count <= 10) {
    System.out.println(count);
    count++;
}
  • do-while循环(至少执行一次):
int num = 1;
do {
    System.out.println(num);
    num++;
} while (num <= 10);

跳转语句:

  • break:跳出循环或switch语句。
  • continue:跳过当前循环的剩余部分,进入下一次迭代。

1.5 数组

数组是固定大小的同类型元素的集合。

一维数组:

int[] numbers = new int[5]; // 声明并分配内存
numbers[0] = 10;
numbers[1] = 20;
// 或者直接初始化
int[] scores = {90, 85, 78, 92, 88};

二维数组:

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6}
};

数组遍历:

// 使用增强for循环
for (int score : scores) {
    System.out.println(score);
}

1.6 字符串处理

Java中的String类是不可变的,用于处理文本。

创建字符串:

String str1 = "Hello"; // 字面量
String str2 = new String("World"); // 使用构造函数

常用方法:

String text = "Java Programming";
System.out.println(text.length()); // 17
System.out.println(text.charAt(0)); // 'J'
System.out.println(text.substring(5, 14)); // "Programming"
System.out.println(text.toUpperCase()); // "JAVA PROGRAMMING"
System.out.println(text.contains("Java")); // true

字符串拼接:

String firstName = "John";
String lastName = "Doe";
String fullName = firstName + " " + lastName; // "John Doe"

字符串格式化:

String name = "Alice";
int age = 30;
String message = String.format("Name: %s, Age: %d", name, age);
System.out.println(message); // "Name: Alice, Age: 30"

第二部分:面向对象编程(OOP)核心概念

2.1 类与对象

类是对象的蓝图,对象是类的实例。

定义类:

public class Person {
    // 字段(属性)
    private String name;
    private int age;
    
    // 构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 方法
    public void introduce() {
        System.out.println("我叫" + name + ",今年" + age + "岁。");
    }
    
    // Getter和Setter方法
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
}

创建对象:

public class Main {
    public static void main(String[] args) {
        Person person = new Person("张三", 25);
        person.introduce(); // 输出:我叫张三,今年25岁。
        
        // 修改属性
        person.setAge(26);
        System.out.println("新的年龄:" + person.getAge()); // 26
    }
}

2.2 封装

封装是将数据(字段)和操作数据的方法绑定在一起,并隐藏内部实现细节。通过访问修饰符(privateprotectedpublic)控制访问权限。

示例:

public class BankAccount {
    private double balance; // 私有字段,外部无法直接访问
    
    public BankAccount(double initialBalance) {
        if (initialBalance >= 0) {
            this.balance = initialBalance;
        }
    }
    
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("存款成功,当前余额:" + balance);
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("取款成功,当前余额:" + balance);
        } else {
            System.out.println("取款失败,余额不足或金额无效");
        }
    }
    
    public double getBalance() {
        return balance;
    }
}

2.3 继承

继承允许子类继承父类的属性和方法,实现代码复用。Java中使用extends关键字实现继承。

示例:

// 父类
class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
    
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
}

// 子类
class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类构造方法
    }
    
    public void bark() {
        System.out.println(name + "汪汪叫");
    }
    
    @Override
    public void eat() {
        System.out.println(name + "正在吃狗粮");
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财");
        dog.eat();   // 旺财正在吃狗粮(重写后的方法)
        dog.sleep(); // 旺财正在睡觉(继承自父类)
        dog.bark();  // 旺财汪汪叫(子类特有方法)
    }
}

注意: Java只支持单继承(一个类只能有一个直接父类),但可以通过接口实现多重继承的效果。

2.4 多态

多态是指同一个接口或父类引用指向不同的子类对象,从而表现出不同的行为。多态通过方法重写和接口实现来实现。

示例:

// 接口
interface Shape {
    double area();
}

// 实现类
class Circle implements Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

class Rectangle implements Shape {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double area() {
        return width * height;
    }
}

// 使用多态
public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(5.0);
        Shape rectangle = new Rectangle(4.0, 6.0);
        
        System.out.println("圆的面积:" + circle.area()); // 78.5398...
        System.out.println("矩形的面积:" + rectangle.area()); // 24.0
    }
}

2.5 抽象类与接口

抽象类: 抽象类不能被实例化,可以包含抽象方法(没有实现的方法)和具体方法。子类必须实现所有抽象方法。

abstract class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    // 抽象方法,没有方法体
    public abstract void makeSound();
    
    // 具体方法
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
}

class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + "喵喵叫");
    }
}

接口: 接口是完全抽象的,只能包含常量、抽象方法、默认方法(Java 8+)和静态方法。接口用于定义行为规范。

interface Flyable {
    void fly(); // 抽象方法
    
    default void takeoff() {
        System.out.println("起飞");
    }
    
    static void showInfo() {
        System.out.println("这是一个飞行接口");
    }
}

class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("鸟在飞翔");
    }
}

2.6 包与导入

包用于组织类,避免命名冲突。使用package关键字声明包,import关键字导入其他包的类。

示例:

// 文件路径:com/example/utils/MathUtils.java
package com.example.utils;

public class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }
}

// 文件路径:com/example/Main.java
package com.example;

import com.example.utils.MathUtils;

public class Main {
    public static void main(String[] args) {
        int result = MathUtils.add(5, 3);
        System.out.println("5 + 3 = " + result);
    }
}

第三部分:高级Java特性

3.1 集合框架

Java集合框架(Collections Framework)提供了一套接口和类,用于存储和操作数据。主要接口包括CollectionListSetMap等。

List(有序、可重复):

import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
        
        // 遍历
        for (String name : names) {
            System.out.println(name);
        }
        
        // 获取元素
        String first = names.get(0); // "Alice"
        
        // 修改元素
        names.set(1, "Bobby");
        
        // 删除元素
        names.remove(2);
    }
}

Set(无序、不可重复):

import java.util.HashSet;
import java.util.Set;

public class SetExample {
    public static void main(String[] args) {
        Set<Integer> numbers = new HashSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(10); // 重复元素不会被添加
        
        System.out.println(numbers.size()); // 2
        System.out.println(numbers.contains(10)); // true
    }
}

Map(键值对):

import java.util.HashMap;
import java.util.Map;

public class MapExample {
    public static void main(String[] args) {
        Map<String, Integer> scores = new HashMap<>();
        scores.put("Alice", 95);
        scores.put("Bob", 88);
        scores.put("Charlie", 92);
        
        // 获取值
        Integer aliceScore = scores.get("Alice"); // 95
        
        // 遍历
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

3.2 异常处理

异常处理用于处理程序运行时的错误,避免程序崩溃。

异常类型:

  • 检查型异常(Checked Exception):编译时必须处理,如IOException
  • 非检查型异常(Unchecked Exception):运行时异常,如NullPointerExceptionArrayIndexOutOfBoundsException

try-catch-finally:

public class ExceptionExample {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[5]); // 数组越界
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组索引越界:" + e.getMessage());
        } finally {
            System.out.println("无论是否发生异常,都会执行finally块");
        }
    }
}

自定义异常:

class InsufficientFundsException extends Exception {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

class BankAccount {
    private double balance;
    
    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException("余额不足,当前余额:" + balance);
        }
        balance -= amount;
    }
}

3.3 泛型

泛型允许在定义类、接口和方法时使用类型参数,提高代码的类型安全性和复用性。

泛型类:

public class Box<T> {
    private T content;
    
    public void setContent(T content) {
        this.content = content;
    }
    
    public T getContent() {
        return content;
    }
}

// 使用
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");
System.out.println(stringBox.getContent()); // Hello

Box<Integer> intBox = new Box<>();
intBox.setContent(123);
System.out.println(intBox.getContent()); // 123

泛型方法:

public static <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}

// 使用
String[] names = {"Alice", "Bob", "Charlie"};
Integer[] numbers = {1, 2, 3};
printArray(names);
printArray(numbers);

3.4 多线程

Java支持多线程编程,允许程序同时执行多个任务。

创建线程的两种方式:

  1. 继承Thread类:
class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " - " + i);
        }
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.start(); // 启动线程
        thread2.start();
    }
}
  1. 实现Runnable接口(推荐):
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " - " + i);
        }
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();
    }
}

线程同步: 当多个线程访问共享资源时,需要同步以避免数据不一致。

class Counter {
    private int count = 0;
    
    public synchronized void increment() {
        count++;
    }
    
    public int getCount() {
        return count;
    }
}

public class SynchronizedExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread[] threads = new Thread[10];
        
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    counter.increment();
                }
            });
            threads[i].start();
        }
        
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("最终计数:" + counter.getCount()); // 10000
    }
}

3.5 输入输出(I/O)

Java I/O库提供了一系列类来处理字节流和字符流。

字节流(处理二进制数据):

import java.io.*;

public class ByteStreamExample {
    public static void main(String[] args) {
        // 写入文件
        try (FileOutputStream fos = new FileOutputStream("data.bin")) {
            byte[] data = {65, 66, 67}; // ASCII: A, B, C
            fos.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 读取文件
        try (FileInputStream fis = new FileInputStream("data.bin")) {
            int byteData;
            while ((byteData = fis.read()) != -1) {
                System.out.print((char) byteData); // ABC
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字符流(处理文本数据):

import java.io.*;

public class CharStreamExample {
    public static void main(String[] args) {
        // 写入文件
        try (FileWriter writer = new FileWriter("text.txt")) {
            writer.write("Hello, Java I/O!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 读取文件
        try (BufferedReader reader = new BufferedReader(new FileReader("text.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.6 反射机制

反射允许程序在运行时检查和修改类、接口、字段和方法的信息。

示例:

import java.lang.reflect.*;

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<?> clazz = Class.forName("java.lang.String");
        
        // 获取构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        
        // 获取方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        
        // 创建实例
        String str = (String) clazz.newInstance(); // 已过时,推荐使用getConstructor
        System.out.println(str);
    }
}

第四部分:项目实战案例

4.1 案例一:学生管理系统(控制台应用)

需求: 实现一个简单的学生管理系统,支持添加、删除、修改、查询学生信息。

步骤:

  1. 定义学生类(Student):
public class Student {
    private String id;
    private String name;
    private int age;
    private String major;
    
    public Student(String id, String name, int age, String major) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.major = major;
    }
    
    // Getter和Setter方法(省略)
    
    @Override
    public String toString() {
        return "学号:" + id + ",姓名:" + name + ",年龄:" + age + ",专业:" + major;
    }
}
  1. 定义管理类(StudentManager):
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class StudentManager {
    private List<Student> students = new ArrayList<>();
    
    public void addStudent() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入学号:");
        String id = scanner.nextLine();
        System.out.println("请输入姓名:");
        String name = scanner.nextLine();
        System.out.println("请输入年龄:");
        int age = scanner.nextInt();
        scanner.nextLine(); // 消耗换行符
        System.out.println("请输入专业:");
        String major = scanner.nextLine();
        
        Student student = new Student(id, name, age, major);
        students.add(student);
        System.out.println("学生添加成功!");
    }
    
    public void deleteStudent() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要删除的学生学号:");
        String id = scanner.nextLine();
        
        boolean found = false;
        for (int i = 0; i < students.size(); i++) {
            if (students.get(i).getId().equals(id)) {
                students.remove(i);
                found = true;
                System.out.println("学生删除成功!");
                break;
            }
        }
        
        if (!found) {
            System.out.println("未找到该学生!");
        }
    }
    
    public void updateStudent() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要修改的学生学号:");
        String id = scanner.nextLine();
        
        boolean found = false;
        for (Student student : students) {
            if (student.getId().equals(id)) {
                System.out.println("请输入新姓名:");
                String name = scanner.nextLine();
                System.out.println("请输入新年龄:");
                int age = scanner.nextInt();
                scanner.nextLine();
                System.out.println("请输入新专业:");
                String major = scanner.nextLine();
                
                student.setName(name);
                student.setAge(age);
                student.setMajor(major);
                found = true;
                System.out.println("学生信息修改成功!");
                break;
            }
        }
        
        if (!found) {
            System.out.println("未找到该学生!");
        }
    }
    
    public void queryStudent() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要查询的学生学号:");
        String id = scanner.nextLine();
        
        boolean found = false;
        for (Student student : students) {
            if (student.getId().equals(id)) {
                System.out.println(student);
                found = true;
                break;
            }
        }
        
        if (!found) {
            System.out.println("未找到该学生!");
        }
    }
    
    public void showAllStudents() {
        if (students.isEmpty()) {
            System.out.println("暂无学生信息!");
        } else {
            for (Student student : students) {
                System.out.println(student);
            }
        }
    }
}
  1. 主程序(Main):
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
        Scanner scanner = new Scanner(System.in);
        
        while (true) {
            System.out.println("\n===== 学生管理系统 =====");
            System.out.println("1. 添加学生");
            System.out.println("2. 删除学生");
            System.out.println("3. 修改学生");
            System.out.println("4. 查询学生");
            System.out.println("5. 显示所有学生");
            System.out.println("0. 退出");
            System.out.print("请选择操作:");
            
            int choice = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符
            
            switch (choice) {
                case 1:
                    manager.addStudent();
                    break;
                case 2:
                    manager.deleteStudent();
                    break;
                case 3:
                    manager.updateStudent();
                    break;
                case 4:
                    manager.queryStudent();
                    break;
                case 5:
                    manager.showAllStudents();
                    break;
                case 0:
                    System.out.println("感谢使用,再见!");
                    return;
                default:
                    System.out.println("无效选择,请重新输入!");
            }
        }
    }
}

运行结果示例:

===== 学生管理系统 =====
1. 添加学生
2. 删除学生
3. 修改学生
4. 查询学生
5. 显示所有学生
0. 退出
请选择操作:1
请输入学号:2023001
请输入姓名:张三
请输入年龄:20
请输入专业:计算机科学
学生添加成功!

4.2 案例二:简易银行账户系统(GUI应用,使用Java Swing)

需求: 创建一个图形界面的银行账户系统,支持开户、存款、取款、查询余额和转账功能。

步骤:

  1. 定义账户类(Account):
public class Account {
    private String accountNumber;
    private String accountHolder;
    private double balance;
    
    public Account(String accountNumber, String accountHolder, double balance) {
        this.accountNumber = accountNumber;
        this.accountHolder = accountHolder;
        this.balance = balance;
    }
    
    // Getter和Setter方法
    public String getAccountNumber() { return accountNumber; }
    public String getAccountHolder() { return accountHolder; }
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
    
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
    
    public boolean withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            return true;
        }
        return false;
    }
}
  1. 定义银行类(Bank):
import java.util.HashMap;
import java.util.Map;

public class Bank {
    private Map<String, Account> accounts = new HashMap<>();
    
    public Account createAccount(String accountNumber, String accountHolder, double initialBalance) {
        if (accounts.containsKey(accountNumber)) {
            return null; // 账户已存在
        }
        Account account = new Account(accountNumber, accountHolder, initialBalance);
        accounts.put(accountNumber, account);
        return account;
    }
    
    public Account getAccount(String accountNumber) {
        return accounts.get(accountNumber);
    }
    
    public boolean transfer(String fromAccount, String toAccount, double amount) {
        Account from = accounts.get(fromAccount);
        Account to = accounts.get(toAccount);
        
        if (from == null || to == null) {
            return false;
        }
        
        if (from.withdraw(amount)) {
            to.deposit(amount);
            return true;
        }
        return false;
    }
}
  1. 创建GUI界面(使用Java Swing):
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class BankGUI extends JFrame {
    private Bank bank = new Bank();
    private JTextField accountNumberField;
    private JTextField accountHolderField;
    private JTextField amountField;
    private JTextArea outputArea;
    
    public BankGUI() {
        setTitle("简易银行系统");
        setSize(600, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        
        // 创建面板
        JPanel inputPanel = new JPanel(new GridLayout(5, 2, 5, 5));
        inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        
        // 账户号码
        inputPanel.add(new JLabel("账户号码:"));
        accountNumberField = new JTextField();
        inputPanel.add(accountNumberField);
        
        // 账户持有人
        inputPanel.add(new JLabel("账户持有人:"));
        accountHolderField = new JTextField();
        inputPanel.add(accountHolderField);
        
        // 金额
        inputPanel.add(new JLabel("金额:"));
        amountField = new JTextField();
        inputPanel.add(amountField);
        
        // 按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout());
        
        JButton createButton = new JButton("开户");
        JButton depositButton = new JButton("存款");
        JButton withdrawButton = new JButton("取款");
        JButton transferButton = new JButton("转账");
        JButton queryButton = new JButton("查询余额");
        
        buttonPanel.add(createButton);
        buttonPanel.add(depositButton);
        buttonPanel.add(withdrawButton);
        buttonPanel.add(transferButton);
        buttonPanel.add(queryButton);
        
        // 输出区域
        outputArea = new JTextArea(10, 40);
        outputArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(outputArea);
        
        // 添加组件到主窗口
        add(inputPanel, BorderLayout.NORTH);
        add(buttonPanel, BorderLayout.CENTER);
        add(scrollPane, BorderLayout.SOUTH);
        
        // 添加事件监听器
        createButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String accountNumber = accountNumberField.getText();
                String accountHolder = accountHolderField.getText();
                String amountText = amountField.getText();
                
                if (accountNumber.isEmpty() || accountHolder.isEmpty() || amountText.isEmpty()) {
                    outputArea.append("请填写所有字段!\n");
                    return;
                }
                
                try {
                    double initialBalance = Double.parseDouble(amountText);
                    Account account = bank.createAccount(accountNumber, accountHolder, initialBalance);
                    if (account != null) {
                        outputArea.append("账户创建成功!账户号码:" + accountNumber + "\n");
                    } else {
                        outputArea.append("账户已存在!\n");
                    }
                } catch (NumberFormatException ex) {
                    outputArea.append("金额格式错误!\n");
                }
            }
        });
        
        depositButton.addActionListener(e -> {
            String accountNumber = accountNumberField.getText();
            String amountText = amountField.getText();
            
            if (accountNumber.isEmpty() || amountText.isEmpty()) {
                outputArea.append("请填写账户号码和金额!\n");
                return;
            }
            
            try {
                double amount = Double.parseDouble(amountText);
                Account account = bank.getAccount(accountNumber);
                if (account != null) {
                    account.deposit(amount);
                    outputArea.append("存款成功!当前余额:" + account.getBalance() + "\n");
                } else {
                    outputArea.append("账户不存在!\n");
                }
            } catch (NumberFormatException ex) {
                outputArea.append("金额格式错误!\n");
            }
        });
        
        withdrawButton.addActionListener(e -> {
            String accountNumber = accountNumberField.getText();
            String amountText = amountField.getText();
            
            if (accountNumber.isEmpty() || amountText.isEmpty()) {
                outputArea.append("请填写账户号码和金额!\n");
                return;
            }
            
            try {
                double amount = Double.parseDouble(amountText);
                Account account = bank.getAccount(accountNumber);
                if (account != null) {
                    if (account.withdraw(amount)) {
                        outputArea.append("取款成功!当前余额:" + account.getBalance() + "\n");
                    } else {
                        outputArea.append("取款失败!余额不足或金额无效!\n");
                    }
                } else {
                    outputArea.append("账户不存在!\n");
                }
            } catch (NumberFormatException ex) {
                outputArea.append("金额格式错误!\n");
            }
        });
        
        transferButton.addActionListener(e -> {
            String fromAccount = accountNumberField.getText();
            String toAccount = JOptionPane.showInputDialog("请输入目标账户号码:");
            String amountText = amountField.getText();
            
            if (fromAccount.isEmpty() || toAccount == null || toAccount.isEmpty() || amountText.isEmpty()) {
                outputArea.append("请填写所有字段!\n");
                return;
            }
            
            try {
                double amount = Double.parseDouble(amountText);
                boolean success = bank.transfer(fromAccount, toAccount, amount);
                if (success) {
                    outputArea.append("转账成功!\n");
                } else {
                    outputArea.append("转账失败!请检查账户和余额!\n");
                }
            } catch (NumberFormatException ex) {
                outputArea.append("金额格式错误!\n");
            }
        });
        
        queryButton.addActionListener(e -> {
            String accountNumber = accountNumberField.getText();
            if (accountNumber.isEmpty()) {
                outputArea.append("请输入账户号码!\n");
                return;
            }
            
            Account account = bank.getAccount(accountNumber);
            if (account != null) {
                outputArea.append("账户信息:\n");
                outputArea.append("账户号码:" + account.getAccountNumber() + "\n");
                outputArea.append("账户持有人:" + account.getAccountHolder() + "\n");
                outputArea.append("余额:" + account.getBalance() + "\n");
            } else {
                outputArea.append("账户不存在!\n");
            }
        });
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            BankGUI gui = new BankGUI();
            gui.setVisible(true);
        });
    }
}

运行说明:

  • 编译并运行BankGUI.java,将打开一个图形界面窗口。
  • 用户可以通过界面输入账户信息、金额,并执行开户、存款、取款、转账和查询操作。
  • 输出区域会显示操作结果。

4.3 案例三:简易图书管理系统(使用JDBC连接数据库)

需求: 创建一个图书管理系统,支持添加、删除、修改、查询图书信息,并将数据存储到MySQL数据库中。

步骤:

  1. 数据库准备:
    • 安装MySQL数据库,创建数据库library_db,并创建表books
CREATE DATABASE library_db;
USE library_db;

CREATE TABLE books (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(100) NOT NULL,
    author VARCHAR(100) NOT NULL,
    isbn VARCHAR(20) UNIQUE,
    publish_year INT,
    price DECIMAL(10, 2)
);
  1. 添加JDBC驱动:

    • 下载MySQL JDBC驱动(mysql-connector-java.jar),并将其添加到项目的类路径中。
  2. 定义图书类(Book):

public class Book {
    private int id;
    private String title;
    private String author;
    private String isbn;
    private int publishYear;
    private double price;
    
    // 构造方法、Getter和Setter方法(省略)
    
    @Override
    public String toString() {
        return "ID: " + id + ", 标题: " + title + ", 作者: " + author + 
               ", ISBN: " + isbn + ", 出版年份: " + publishYear + ", 价格: " + price;
    }
}
  1. 定义数据库操作类(BookDAO):
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BookDAO {
    private static final String URL = "jdbc:mysql://localhost:3306/library_db?useSSL=false&serverTimezone=UTC";
    private static final String USER = "root"; // 替换为你的数据库用户名
    private static final String PASSWORD = "password"; // 替换为你的数据库密码
    
    private Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USER, PASSWORD);
    }
    
    public void addBook(Book book) {
        String sql = "INSERT INTO books (title, author, isbn, publish_year, price) VALUES (?, ?, ?, ?, ?)";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, book.getTitle());
            pstmt.setString(2, book.getAuthor());
            pstmt.setString(3, book.getIsbn());
            pstmt.setInt(4, book.getPublishYear());
            pstmt.setDouble(5, book.getPrice());
            
            int rows = pstmt.executeUpdate();
            if (rows > 0) {
                System.out.println("图书添加成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    public void deleteBook(int id) {
        String sql = "DELETE FROM books WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setInt(1, id);
            int rows = pstmt.executeUpdate();
            if (rows > 0) {
                System.out.println("图书删除成功!");
            } else {
                System.out.println("未找到该图书!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    public void updateBook(Book book) {
        String sql = "UPDATE books SET title = ?, author = ?, isbn = ?, publish_year = ?, price = ? WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, book.getTitle());
            pstmt.setString(2, book.getAuthor());
            pstmt.setString(3, book.getIsbn());
            pstmt.setInt(4, book.getPublishYear());
            pstmt.setDouble(5, book.getPrice());
            pstmt.setInt(6, book.getId());
            
            int rows = pstmt.executeUpdate();
            if (rows > 0) {
                System.out.println("图书信息更新成功!");
            } else {
                System.out.println("未找到该图书!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    public Book getBookById(int id) {
        String sql = "SELECT * FROM books WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setInt(1, id);
            ResultSet rs = pstmt.executeQuery();
            
            if (rs.next()) {
                Book book = new Book();
                book.setId(rs.getInt("id"));
                book.setTitle(rs.getString("title"));
                book.setAuthor(rs.getString("author"));
                book.setIsbn(rs.getString("isbn"));
                book.setPublishYear(rs.getInt("publish_year"));
                book.setPrice(rs.getDouble("price"));
                return book;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public List<Book> getAllBooks() {
        List<Book> books = new ArrayList<>();
        String sql = "SELECT * FROM books";
        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            
            while (rs.next()) {
                Book book = new Book();
                book.setId(rs.getInt("id"));
                book.setTitle(rs.getString("title"));
                book.setAuthor(rs.getString("author"));
                book.setIsbn(rs.getString("isbn"));
                book.setPublishYear(rs.getInt("publish_year"));
                book.setPrice(rs.getDouble("price"));
                books.add(book);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return books;
    }
    
    public List<Book> searchBooks(String keyword) {
        List<Book> books = new ArrayList<>();
        String sql = "SELECT * FROM books WHERE title LIKE ? OR author LIKE ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, "%" + keyword + "%");
            pstmt.setString(2, "%" + keyword + "%");
            ResultSet rs = pstmt.executeQuery();
            
            while (rs.next()) {
                Book book = new Book();
                book.setId(rs.getInt("id"));
                book.setTitle(rs.getString("title"));
                book.setAuthor(rs.getString("author"));
                book.setIsbn(rs.getString("isbn"));
                book.setPublishYear(rs.getInt("publish_year"));
                book.setPrice(rs.getDouble("price"));
                books.add(book);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return books;
    }
}
  1. 主程序(控制台应用):
import java.util.List;
import java.util.Scanner;

public class LibrarySystem {
    private static BookDAO bookDAO = new BookDAO();
    private static Scanner scanner = new Scanner(System.in);
    
    public static void main(String[] args) {
        while (true) {
            System.out.println("\n===== 图书管理系统 =====");
            System.out.println("1. 添加图书");
            System.out.println("2. 删除图书");
            System.out.println("3. 修改图书");
            System.out.println("4. 查询图书(按ID)");
            System.out.println("5. 显示所有图书");
            System.out.println("6. 搜索图书(按标题或作者)");
            System.out.println("0. 退出");
            System.out.print("请选择操作:");
            
            int choice = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符
            
            switch (choice) {
                case 1:
                    addBook();
                    break;
                case 2:
                    deleteBook();
                    break;
                case 3:
                    updateBook();
                    break;
                case 4:
                    queryBookById();
                    break;
                case 5:
                    showAllBooks();
                    break;
                case 6:
                    searchBooks();
                    break;
                case 0:
                    System.out.println("感谢使用,再见!");
                    return;
                default:
                    System.out.println("无效选择,请重新输入!");
            }
        }
    }
    
    private static void addBook() {
        System.out.println("请输入图书标题:");
        String title = scanner.nextLine();
        System.out.println("请输入作者:");
        String author = scanner.nextLine();
        System.out.println("请输入ISBN:");
        String isbn = scanner.nextLine();
        System.out.println("请输入出版年份:");
        int publishYear = scanner.nextInt();
        scanner.nextLine();
        System.out.println("请输入价格:");
        double price = scanner.nextDouble();
        scanner.nextLine();
        
        Book book = new Book();
        book.setTitle(title);
        book.setAuthor(author);
        book.setIsbn(isbn);
        book.setPublishYear(publishYear);
        book.setPrice(price);
        
        bookDAO.addBook(book);
    }
    
    private static void deleteBook() {
        System.out.println("请输入要删除的图书ID:");
        int id = scanner.nextInt();
        scanner.nextLine();
        bookDAO.deleteBook(id);
    }
    
    private static void updateBook() {
        System.out.println("请输入要修改的图书ID:");
        int id = scanner.nextInt();
        scanner.nextLine();
        
        Book existingBook = bookDAO.getBookById(id);
        if (existingBook == null) {
            System.out.println("未找到该图书!");
            return;
        }
        
        System.out.println("请输入新标题(原:" + existingBook.getTitle() + "):");
        String title = scanner.nextLine();
        System.out.println("请输入新作者(原:" + existingBook.getAuthor() + "):");
        String author = scanner.nextLine();
        System.out.println("请输入新ISBN(原:" + existingBook.getIsbn() + "):");
        String isbn = scanner.nextLine();
        System.out.println("请输入新出版年份(原:" + existingBook.getPublishYear() + "):");
        int publishYear = scanner.nextInt();
        scanner.nextLine();
        System.out.println("请输入新价格(原:" + existingBook.getPrice() + "):");
        double price = scanner.nextDouble();
        scanner.nextLine();
        
        Book updatedBook = new Book();
        updatedBook.setId(id);
        updatedBook.setTitle(title);
        updatedBook.setAuthor(author);
        updatedBook.setIsbn(isbn);
        updatedBook.setPublishYear(publishYear);
        updatedBook.setPrice(price);
        
        bookDAO.updateBook(updatedBook);
    }
    
    private static void queryBookById() {
        System.out.println("请输入要查询的图书ID:");
        int id = scanner.nextInt();
        scanner.nextLine();
        
        Book book = bookDAO.getBookById(id);
        if (book != null) {
            System.out.println(book);
        } else {
            System.out.println("未找到该图书!");
        }
    }
    
    private static void showAllBooks() {
        List<Book> books = bookDAO.getAllBooks();
        if (books.isEmpty()) {
            System.out.println("暂无图书信息!");
        } else {
            for (Book book : books) {
                System.out.println(book);
            }
        }
    }
    
    private static void searchBooks() {
        System.out.println("请输入搜索关键词(标题或作者):");
        String keyword = scanner.nextLine();
        
        List<Book> books = bookDAO.searchBooks(keyword);
        if (books.isEmpty()) {
            System.out.println("未找到匹配的图书!");
        } else {
            for (Book book : books) {
                System.out.println(book);
            }
        }
    }
}

运行说明:

  1. 确保MySQL数据库已启动,并创建了library_db数据库和books表。
  2. mysql-connector-java.jar添加到项目的类路径中。
  3. 修改BookDAO类中的数据库连接信息(URL、USER、PASSWORD)。
  4. 编译并运行LibrarySystem.java,根据菜单提示操作。

第五部分:学习建议与进阶方向

5.1 学习建议

  1. 动手实践: 编程是实践性很强的技能,多写代码,多调试。从简单的控制台程序开始,逐步过渡到图形界面和Web应用。
  2. 阅读源码: Java标准库(如java.util包)的源码是学习的绝佳资源。通过阅读源码,可以深入理解类的设计和实现。
  3. 参与开源项目: 在GitHub上寻找感兴趣的Java开源项目,阅读代码、提交Issue或贡献代码。
  4. 学习设计模式: 设计模式是解决常见问题的成熟方案。学习单例、工厂、观察者等模式,提升代码质量。
  5. 关注Java新特性: Java 8引入了Lambda表达式、Stream API等重要特性,Java 17是长期支持版本(LTS)。保持对新特性的学习。

5.2 进阶方向

  1. Java Web开发: 学习Spring Boot、Spring MVC、MyBatis等框架,构建Web应用。
  2. Android开发: 使用Java或Kotlin开发Android应用。
  3. 大数据处理: 学习Hadoop、Spark等大数据框架,使用Java进行数据处理。
  4. 微服务架构: 学习Spring Cloud、Dubbo等微服务框架。
  5. 性能优化: 深入学习JVM原理、垃圾回收机制、性能调优等。

结语

Java编程的学习是一个循序渐进的过程,从基础语法到面向对象编程,再到高级特性和项目实战,每一步都需要扎实的练习和思考。本指南提供了从入门到精通的完整路径,涵盖了核心概念和实战案例。希望读者能够通过本指南的学习,掌握Java编程的精髓,并在实际项目中应用所学知识,成为一名优秀的Java开发者。记住,编程之路没有捷径,唯有不断实践和探索,才能不断进步。祝你学习顺利!