引言
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程序所需的所有工具。
安装步骤:
- 访问Oracle官网或OpenJDK项目下载适合您操作系统的JDK版本(推荐JDK 17或更高版本)。
- 安装JDK并配置环境变量(JAVA_HOME和PATH)。
- 下载并安装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 封装
封装是将数据(字段)和操作数据的方法绑定在一起,并隐藏内部实现细节。通过访问修饰符(private、protected、public)控制访问权限。
示例:
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)提供了一套接口和类,用于存储和操作数据。主要接口包括Collection、List、Set、Map等。
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):运行时异常,如
NullPointerException、ArrayIndexOutOfBoundsException。
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支持多线程编程,允许程序同时执行多个任务。
创建线程的两种方式:
- 继承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();
}
}
- 实现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 案例一:学生管理系统(控制台应用)
需求: 实现一个简单的学生管理系统,支持添加、删除、修改、查询学生信息。
步骤:
- 定义学生类(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;
}
}
- 定义管理类(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);
}
}
}
}
- 主程序(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)
需求: 创建一个图形界面的银行账户系统,支持开户、存款、取款、查询余额和转账功能。
步骤:
- 定义账户类(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;
}
}
- 定义银行类(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;
}
}
- 创建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数据库中。
步骤:
- 数据库准备:
- 安装MySQL数据库,创建数据库
library_db,并创建表books:
- 安装MySQL数据库,创建数据库
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)
);
添加JDBC驱动:
- 下载MySQL JDBC驱动(
mysql-connector-java.jar),并将其添加到项目的类路径中。
- 下载MySQL JDBC驱动(
定义图书类(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;
}
}
- 定义数据库操作类(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;
}
}
- 主程序(控制台应用):
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);
}
}
}
}
运行说明:
- 确保MySQL数据库已启动,并创建了
library_db数据库和books表。 - 将
mysql-connector-java.jar添加到项目的类路径中。 - 修改
BookDAO类中的数据库连接信息(URL、USER、PASSWORD)。 - 编译并运行
LibrarySystem.java,根据菜单提示操作。
第五部分:学习建议与进阶方向
5.1 学习建议
- 动手实践: 编程是实践性很强的技能,多写代码,多调试。从简单的控制台程序开始,逐步过渡到图形界面和Web应用。
- 阅读源码: Java标准库(如
java.util包)的源码是学习的绝佳资源。通过阅读源码,可以深入理解类的设计和实现。 - 参与开源项目: 在GitHub上寻找感兴趣的Java开源项目,阅读代码、提交Issue或贡献代码。
- 学习设计模式: 设计模式是解决常见问题的成熟方案。学习单例、工厂、观察者等模式,提升代码质量。
- 关注Java新特性: Java 8引入了Lambda表达式、Stream API等重要特性,Java 17是长期支持版本(LTS)。保持对新特性的学习。
5.2 进阶方向
- Java Web开发: 学习Spring Boot、Spring MVC、MyBatis等框架,构建Web应用。
- Android开发: 使用Java或Kotlin开发Android应用。
- 大数据处理: 学习Hadoop、Spark等大数据框架,使用Java进行数据处理。
- 微服务架构: 学习Spring Cloud、Dubbo等微服务框架。
- 性能优化: 深入学习JVM原理、垃圾回收机制、性能调优等。
结语
Java编程的学习是一个循序渐进的过程,从基础语法到面向对象编程,再到高级特性和项目实战,每一步都需要扎实的练习和思考。本指南提供了从入门到精通的完整路径,涵盖了核心概念和实战案例。希望读者能够通过本指南的学习,掌握Java编程的精髓,并在实际项目中应用所学知识,成为一名优秀的Java开发者。记住,编程之路没有捷径,唯有不断实践和探索,才能不断进步。祝你学习顺利!
