答案:Java具有简单性、面向对象、平台无关性等特点。
实操:创建一个简单的Java程序,演示面向对象的封装特性。
// 定义一个学生类,封装姓名和年龄属性
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 提供公共的访问方法
public String getName() { return name; }
public int getAge() { return age; }
}
public class Main {
public static void main(String[] args) {
Student student = new Student("张三", 20);
System.out.println(student.getName() + " 年龄: " + student.getAge());
}
}
答案:JVM是执行字节码的虚拟计算机,实现了“一次编写,到处运行”。
实操:使用javap
命令查看字节码。
# 编译Java文件
javac Main.java
# 查看字节码
javap -c Main
答案:static修饰的成员属于类,而非实例。
实操:创建静态工具类计算圆的面积。
public class MathUtils {
// 静态常量
public static final double PI = 3.14159;
// 静态方法
public static double calculateArea(double radius) {
return PI * radius * radius;
}
}
// 使用静态成员
double area = MathUtils.calculateArea(5.0);
答案:基本数据类型和引用数据类型。
实操:演示自动装箱与拆箱。
Integer numObj = 10; // 自动装箱
int num = numObj; // 自动拆箱
System.out.println(num + 5); // 输出15
答案:覆盖发生在父子类,重载在同一类中。
实操:实现方法覆盖与重载。
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
class Dog extends Animal {
@Override
public void makeSound() { // 方法覆盖
System.out.println("汪汪汪");
}
public void makeSound(int times) { // 方法重载
for (int i = 0; i < times; i++) {
System.out.print("汪 ");
}
}
}
答案:构造方法用于初始化对象。
实操:创建带参数的构造方法。
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getInfo() {
return name + ",年龄:" + age;
}
}
Person p = new Person("李四", 25);
System.out.println(p.getInfo());
答案:Java类不支持多继承,但接口可以多实现。
实操:实现多接口。
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() { System.out.println("鸭子飞"); }
@Override
public void swim() { System.out.println("鸭子游"); }
}
答案:Java中基本类型是值传递,对象是引用传递。
实操:验证引用传递。
class Point {
int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
public class Main {
public static void main(String[] args) {
Point p = new Point(10, 20);
modify(p);
System.out.println("x=" + p.x + ", y=" + p.y); // 输出x=100, y=200
}
public static void modify(Point pt) {
pt.x = 100;
pt.y = 200;
}
}
答案:进程是资源分配单位,线程是执行单元。
实操:使用jconsole
监控Java进程与线程。
# 启动示例程序
java -cp . Main
# 启动监控工具
jconsole
答案:继承Thread类、实现Runnable接口等。
实操:使用ExecutorService创建线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("执行任务: " + taskId + ",线程: " + Thread.currentThread().getName());
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
});
}
executor.shutdown();
}
}
答案:使用synchronized
关键字或ReentrantLock
。
实操:使用synchronized
实现线程安全的计数器。
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
答案:多个线程访问共享资源时不会导致数据不一致。
实操:对比ArrayList
与Vector
的线程安全性。
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class ThreadSafetyDemo {
public static void main(String[] args) throws InterruptedException {
// 使用非线程安全的ArrayList
List<Integer> arrayList = new ArrayList<>();
// 使用线程安全的Vector
List<Integer> vector = new Vector<>();
// 启动多个线程添加元素
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
arrayList.add(i);
vector.add(i);
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
arrayList.add(i);
vector.add(i);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("ArrayList size: " + arrayList.size()); // 可能小于2000
System.out.println("Vector size: " + vector.size()); // 总是2000
}
}
答案:Java提供synchronized
和Lock
接口实现锁机制。
实操:使用ReentrantLock
实现可重入锁。
import java.util.concurrent.locks.ReentrantLock;
class Resource {
private final ReentrantLock lock = new ReentrantLock();
public void accessResource() {
lock.lock();
try {
// 执行临界区代码
System.out.println(Thread.currentThread().getName() + " 获取锁");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + " 释放锁");
}
}
}
答案:死锁是两个或多个线程互相等待对方释放资源的情况。
实操:模拟死锁并分析。
public class DeadlockDemo {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("线程1获取锁1");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("线程1获取锁2");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("线程2获取锁2");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("线程2获取锁1");
}
}
});
t1.start();
t2.start();
}
}
答案:保证变量的可见性,禁止指令重排序。
实操:使用volatile实现线程间通信。
public class VolatileDemo {
private static volatile boolean flag = false;
public static void main(String[] args) {
new Thread(() -> {
while (!flag) {
// 等待flag变为true
}
System.out.println("线程收到通知,flag已变为true");
}).start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("主线程已设置flag为true");
}
}
答案:用于线程间的协作,必须在synchronized
块中调用。
实操:使用生产者-消费者模型演示。
class SharedResource {
private int data;
private boolean available = false;
public synchronized void produce(int value) {
while (available) {
try { wait(); } catch (InterruptedException e) {}
}
data = value;
available = true;
notifyAll();
}
public synchronized int consume() {
while (!available) {
try { wait(); } catch (InterruptedException e) {}
}
available = false;
notifyAll();
return data;
}
}
答案:线程池管理线程的创建和复用,提高性能。
实操:使用Executors
工厂类创建不同类型的线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 创建固定大小的线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);
// 创建缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();
// 创建单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();
// 执行任务
fixedPool.submit(() -> System.out.println("任务执行"));
// 关闭线程池
fixedPool.shutdown();
}
}
答案:Callable有返回值,Future用于获取异步结果。
实操:使用Callable和Future实现异步计算。
import java.util.concurrent.*;
public class CallableFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
Thread.sleep(2000);
return 100;
};
Future<Integer> future = executor.submit(task);
System.out.println("等待结果...");
System.out.println("结果: " + future.get());
executor.shutdown();
}
}
答案:不可中断的操作,Java提供了Atomic
类实现原子操作。
实操:使用AtomicInteger
实现无锁计数器。
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicDemo {
private static AtomicInteger counter = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.incrementAndGet();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.incrementAndGet();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("计数器值: " + counter.get()); // 输出2000
}
}
答案:线程安全的集合,如ConcurrentHashMap
、CopyOnWriteArrayList
等。
实操:使用ConcurrentHashMap
统计单词频率。
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentCollectionDemo {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> wordCount = new ConcurrentHashMap<>();
String[] words = {"apple", "banana", "apple", "cherry", "banana"};
for (String word : words) {
wordCount.compute(word, (k, v) -> (v == null) ? 1 : v + 1);
}
System.out.println(wordCount); // 输出 {apple=2, banana=2, cherry=1}
}
}
答案:主要接口包括Collection
、List
、Set
、Map
等。
实操:创建不同类型的集合。
import java.util.*;
public class CollectionFrameworkDemo {
public static void main(String[] args) {
// List示例
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// Set示例
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(2); // 重复元素,不会被添加
// Map示例
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
}
}
答案:ArrayList基于数组,LinkedList基于链表。
实操:对比两种列表的插入性能。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListPerformanceDemo {
public static void main(String[] args) {
int size = 100000;
// 测试ArrayList插入性能
List<Integer> arrayList = new ArrayList<>();
long startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
arrayList.add(0, i); // 在头部插入
}
long endTime = System.currentTimeMillis();
System.out.println("ArrayList插入时间: " + (endTime - startTime) + "ms");
// 测试LinkedList插入性能
List<Integer> linkedList = new LinkedList<>();
startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
linkedList.add(0, i); // 在头部插入
}
endTime = System.currentTimeMillis();
System.out.println("LinkedList插入时间: " + (endTime - startTime) + "ms");
}
}
答案:HashMap非线程安全,Hashtable线程安全。
实操:对比HashMap和Hashtable的使用。
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class MapDifferenceDemo {
public static void main(String[] args) {
// HashMap允许null键和null值
Map<String, String> hashMap = new HashMap<>();
hashMap.put(null, "value");
hashMap.put("key", null);
// Hashtable不允许null键和null值
Map<String, String> hashtable = new Hashtable<>();
// hashtable.put(null, "value"); // 抛出NullPointerException
// hashtable.put("key", null); // 抛出NullPointerException
}
}
答案:使用Collections.sort()
或Stream.sorted()
。
实操:对自定义对象列表进行排序。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Student implements Comparable<Student> {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student other) {
return Integer.compare(this.score, other.score);
}
@Override
public String toString() {
return name + ": " + score;
}
}
public class SortingDemo {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("张三", 85));
students.add(new Student("李四", 72));
students.add(new Student("王五", 90));
Collections.sort(students);
System.out.println(students); // 按分数升序排列
}
}
答案:用于遍历集合的接口,支持元素的删除操作。
实操:使用迭代器遍历并删除元素。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
if (element.equals("B")) {
iterator.remove(); // 安全删除元素
}
}
System.out.println(list); // 输出 [A, C]
}
}
答案:用于处理集合的流式操作,支持过滤、映射、聚合等。
实操:使用Stream API进行数据处理。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 过滤偶数并计算平方和
int sum = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println("偶数的平方和: " + sum); // 输出 220
}
}
答案:基于红黑树实现,元素按自然顺序或指定比较器排序。
实操:使用TreeSet存储自定义对象。
import java.util.TreeSet;
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return name + ": " + age;
}
}
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Person> people = new TreeSet<>();
people.add(new Person("张三", 25));
people.add(new Person("李四", 20));
people.add(new Person("王五", 30));
System.out.println(people); // 按年龄升序排列
}
}
答案:写时复制的线程安全列表,适用于读多写少的场景。
实操:多线程环境下使用CopyOnWriteArrayList。
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListDemo {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
// 线程1添加元素
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
list.add("元素" + i);
}
});
// 线程2遍历元素
Thread t2 = new Thread(() -> {
for (String element : list) {
System.out.println(element);
}
});
t1.start();
t2.start();
}
}
答案:维护插入顺序或访问顺序的HashMap。
实操:使用LinkedHashMap实现LRU缓存。
import java.util.LinkedHashMap;
import java.util.Map;
public class LRUCacheDemo extends LinkedHashMap<Integer, Integer> {
private final int capacity;
public LRUCacheDemo(int capacity) {
super(capacity, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
};
this.capacity = capacity;
}
public static void main(String[] args) {
LRUCacheDemo cache = new LRUCacheDemo(3);
cache.put(1, 1);
cache.put(2, 2);
cache.put(3, 3);
cache.get(1); // 访问元素1,使其变为最近使用
cache.put(4, 4); // 超出容量,移除最久未使用的元素2
System.out.println(cache); // 输出 {3=3, 1=1, 4=4}
}
}
答案:可以使用keySet()、entrySet()或forEach()方法。
实操:演示三种遍历Map的方式。
import java.util.HashMap;
import java.util.Map;
public class MapTraversalDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
// 方式1:使用keySet()
for (String key : map.keySet()) {
System.out.println(key + " : " + map.get(key));
}
// 方式2:使用entrySet()
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
// 方式3:使用forEach()
map.forEach((key, value) -> System.out.println(key + " : " + value));
}
}
答案:通过try-catch-finally和throws关键字实现。
实操:捕获并处理异常。
public class ExceptionHandlingDemo {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("结果: " + result);
} catch (ArithmeticException e) {
System.out.println("捕获到异常: " + e.getMessage());
} finally {
System.out.println("执行finally块");
}
}
public static int divide(int a, int b) {
return a / b; // 会抛出ArithmeticException
}
}
答案:检查型异常必须被捕获或声明抛出,非检查型异常不强制。
实操:演示两种异常的区别。
import java.io.FileInputStream;
import java.io.IOException;
public class ExceptionTypeDemo {
public static void main(String[] args) {
// 检查型异常,必须处理
try {
FileInputStream fis = new FileInputStream("file.txt");
} catch (IOException e) {
e.printStackTrace();
}
// 非检查型异常,不强制处理
int[] arr = new int[5];
System.out.println(arr[10]); // 抛出ArrayIndexOutOfBoundsException
}
}
答案:throw用于手动抛出异常,throws用于声明方法可能抛出的异常。
实操:自定义异常并使用throw和throws。
class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
public class ThrowThrowsDemo {
public static void main(String[] args) {
try {
validateAge(-5);
} catch (CustomException e) {
System.out.println(e.getMessage());
}
}
public static void validateAge(int age) throws CustomException {
if (age < 0) {
throw new CustomException("年龄不能为负数");
}
}
}
答案:无论是否发生异常,finally块中的代码总会执行。
实操:演示finally块的执行。
public class FinallyDemo {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("捕获到除零异常");
} finally {
System.out.println("执行finally块");
}
}
}
答案:用户自定义的异常类,继承自Exception或其子类。
实操:创建自定义异常类。
class InvalidEmailException extends Exception {
public InvalidEmailException(String message) {
super(message);
}
}
public class CustomExceptionDemo {
public static void main(String[] args) {
try {
validateEmail("invalid_email");
} catch (InvalidEmailException e) {
System.out.println(e.getMessage());
}
}
public static void validateEmail(String email) throws InvalidEmailException {
if (!email.contains("@")) {
throw new InvalidEmailException("无效的邮箱地址");
}
}
}
答案:自动关闭实现了AutoCloseable接口的资源。
实操:使用try-with-resources读取文件。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesDemo {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案:将一个异常包装在另一个异常中,保留原始异常信息。
实操:实现异常链。
class DatabaseException extends Exception {
public DatabaseException(String message, Throwable cause) {
super(message, cause);
}
}
public class ExceptionChainingDemo {
public static void main(String[] args) {
try {
connectToDatabase();
} catch (DatabaseException e) {
System.out.println("数据库连接失败: " + e.getMessage());
System.out.println("原始异常: " + e.getCause());
}
}
public static void connectToDatabase() throws DatabaseException {
try {
// 模拟数据库连接失败
throw new RuntimeException("连接超时");
} catch (RuntimeException e) {
throw new DatabaseException("无法连接数据库", e);
}
}
}
答案:通过实现Thread.UncaughtExceptionHandler接口。
实操:设置全局异常处理器。
public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程 " + t.getName() + " 抛出异常: " + e.getMessage());
// 可以添加日志记录或其他处理逻辑
}
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());
Thread t = new Thread(() -> {
throw new RuntimeException("测试异常");
});
t.start();
}
}
答案:用于调试的机制,验证程序中的假设。
实操:使用断言检查参数。
public class AssertionDemo {
public static void main(String[] args) {
int age = -5;
assert age >= 0 : "年龄不能为负数";
System.out.println("年龄: " + age);
}
}
// 启用断言运行程序
// java -ea AssertionDemo
答案:Error表示系统级错误,无法恢复;Exception表示可处理的异常情况。
实操:演示StackOverflowError。
public class ErrorDemo {
public static void main(String[] args) {
recursiveMethod();
}
public static void recursiveMethod() {
recursiveMethod(); // 无限递归,会导致StackOverflowError
}
}
答案:字节流和字符流,分别对应InputStream/OutputStream和Reader/Writer。
实操:使用字节流复制文件。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt")) {
int byteRead;
while ((byteRead = fis.read()) != -1) {
fos.write(byteRead);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案:非阻塞IO,基于通道(Channel)和缓冲区(Buffer)。
实操:使用NIO复制文件。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class NioDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案:NIO中用于存储数据的对象,有position、limit和capacity属性。
实操:使用ByteBuffer读写数据。
import java.nio.ByteBuffer;
public class BufferDemo {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(10);
// 写入数据
buffer.put((byte) 'A');
buffer.put((byte) 'B');
buffer.put((byte) 'C');
// 切换到读模式
buffer.flip();
// 读取数据
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get() + " ");
}
// 清空缓冲区
buffer.clear();
}
}
答案:NIO中用于与数据源交互的双向通道。
实操:使用FileChannel读取文件。
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ChannelDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt");
FileChannel channel = fis.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = channel.read(buffer);
while (bytesRead != -1) {
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear();
bytesRead = channel.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案:NIO中用于多路复用的选择器,可监控多个通道的IO事件。
实操:简单的Selector示例。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;
public class SelectorDemo {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int readyChannels = selector.select();
if (readyChannels == 0) continue;
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
// 处理连接事件
} else if (key.isReadable()) {
// 处理读取事件
}
keyIterator.remove();
}
}
}
}
答案:字节流处理原始字节,字符流处理字符数据。
实操:使用字符流写入文件。
import java.io.FileWriter;
import java.io.IOException;
public class CharacterStreamDemo {
public static void main(String[] args) {
try (FileWriter writer = new FileWriter("output.txt")) {
writer.write("Hello, World!\n");
writer.write("这是一个字符流示例。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案:将对象转换为字节流和从字节流恢复对象的过程。
实操:实现对象的序列化和反序列化。
import java.io.*;
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ", " + age + "岁";
}
}
public class SerializationDemo {
public static void main(String[] args) {
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
Person person = new Person("张三", 25);
oos.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person restoredPerson = (Person) ois.readObject();
System.out.println(restoredPerson);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
答案:通过实现writeObject()和readObject()方法。
实操:自定义序列化示例。
import java.io.*;
class CustomSerializable implements Serializable {
private static final long serialVersionUID = 1L;
private int value;
public CustomSerializable(int value) {
this.value = value;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeInt(value * 2); // 自定义序列化逻辑
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
value = in.readInt() / 2; // 自定义反序列化逻辑
}
public int getValue() {
return value;
}
}
答案:用于过滤文件的接口,实现FilenameFilter或FileFilter。
实操:使用文件过滤器列出所有txt文件。
import java.io.File;
import java.io.FilenameFilter;
public class FileFilterDemo {
public static void main(String[] args) {
File dir = new File(".");
FilenameFilter filter = (dir1, name) -> name.endsWith(".txt");
File[] txtFiles = dir.listFiles(filter);
if (txtFiles != null) {
for (File file : txtFiles) {
System.out.println(file.getName());
}
}
}
}
答案:使用Java Cryptography Architecture (JCA)。
实操:使用AES加密文件。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.*;
import java.security.NoSuchAlgorithmException;
public class FileEncryptionDemo {
public static void main(String[] args) throws Exception {
// 生成密钥
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
// 加密文件
encryptFile("plain.txt", "encrypted.bin", secretKey);
// 解密文件
decryptFile("encrypted.bin", "decrypted.txt", secretKey);
}
public static void encryptFile(String inputFile, String outputFile, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
try (FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
cos.write(buffer, 0, bytesRead);
}
}
}
public static void decryptFile(String inputFile, String outputFile, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
try (FileInputStream fis = new FileInputStream(inputFile);
CipherInputStream cis = new CipherInputStream(fis, cipher);
FileOutputStream fos = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = cis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
}
}
答案:运行时动态获取类的信息并操作类的机制。
实操:使用反射创建对象并调用方法。
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class MyClass {
private String message;
public MyClass(String message) {
this.message = message;
}
public void printMessage() {
System.out.println("Message: " + message);
}
}
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
// 获取Class对象
Class<?> clazz = Class.forName("MyClass");
// 创建对象
Constructor<?> constructor = clazz.getConstructor(String.class);
Object obj = constructor.newInstance("Hello, Reflection!");
// 调用方法
Method method = clazz.getMethod("printMessage");
method.invoke(obj);
}
}
答案:三种方式:Class.forName()
、类名.class
、对象.getClass()
。
实操:演示三种获取Class对象的方式。
public class GetClassDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1:使用Class.forName()
Class<?> clazz1 = Class.forName("java.util.ArrayList");
// 方式2:使用类名.class
Class<?> clazz2 = ArrayList.class;
// 方式3:使用对象.getClass()
ArrayList<String> list = new ArrayList<>();
Class<?> clazz3 = list.getClass();
System.out.println(clazz1 == clazz2); // 输出true
System.out.println(clazz2 == clazz3); // 输出true
}
}
答案:为程序元素(类、方法等)添加元数据的机制。
实操:定义和使用自定义注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
String value() default "default";
int count() default 1;
}
// 使用注解
class MyClass {
@MyAnnotation(value = "Hello", count = 3)
public void doSomething() {
System.out.println("执行方法");
}
}
答案:用于定义注解的注解,如@Retention
、@Target
等。
实操:演示元注解的使用。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyTypeAnnotation {
String value();
}
@MyTypeAnnotation("这是一个类注解")
class MyAnnotatedClass {
// 类定义
}
答案:使用getAnnotation()
方法。
实操:通过反射读取注解信息。
import java.lang.reflect.Method;
@interface MyAnnotation {
String value();
}
class MyClass {
@MyAnnotation("测试注解")
public void myMethod() {}
}
public class AnnotationReflectionDemo {
public static void main(String[] args) throws Exception {
Method method = MyClass.class.getMethod("myMethod");
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
if (annotation != null) {
System.out.println("注解值: " + annotation.value());
}
}
}
答案:运行时创建代理类的机制,实现AOP等功能。
实操:使用动态代理记录方法调用时间。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Calculator {
int add(int a, int b);
}
class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
}
class TimeHandler implements InvocationHandler {
private final Object target;
public TimeHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + " 执行时间: " + (endTime - startTime) + "ms");
return result;
}
}
public class DynamicProxyDemo {
public static void main(String[] args) {
Calculator target = new CalculatorImpl();
Calculator proxy = (Calculator) Proxy.newProxyInstance(
Calculator.class.getClassLoader(),
new Class<?>[]{Calculator.class},
new TimeHandler(target)
);
int result = proxy.add(3, 5);
System.out.println("结果: " + result);
}
}
答案:Java 9引入的模块化系统,使用module-info.java定义模块。
实操:创建简单的模块化项目。
// module-info.java
module mymodule {
exports com.example.mypackage;
requires java.base;
requires java.sql;
}
// com/example/mypackage/MyClass.java
package com.example.mypackage;
public class MyClass {
public static void sayHello() {
System.out.println("Hello from module!");
}
}
答案:简化Lambda表达式的语法,直接引用已有方法。
实操:使用方法引用。
import java.util.Arrays;
import java.util.List;
public class MethodReferenceDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 使用方法引用
names.forEach(System.out::println);
// 等价的Lambda表达式
names.forEach(name -> System.out.println(name));
}
}
答案:只包含一个抽象方法的接口,可用@FunctionalInterface注解。
实操:定义和使用函数式接口。
@FunctionalInterface
interface MyFunction {
int apply(int a, int b);
}
public class FunctionalInterfaceDemo {
public static void main(String[] args) {
// 使用Lambda表达式实现函数式接口
MyFunction add = (a, b) -> a + b;
int result = add.apply(3, 5);
System.out.println("结果: " + result);
}
}
答案:用其他语言(如C、C++)实现的Java方法。
实操:声明本地方法。
public class NativeMethodDemo {
// 声明本地方法
public native void nativeMethod();
// 加载本地库
static {
System.loadLibrary("mylib");
}
public static void main(String[] args) {
new NativeMethodDemo().nativeMethod();
}
}
答案:使用JDBC API。
实操:连接MySQL数据库并查询数据。
import java.sql.*;
public class JdbcDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "password";
try (Connection conn = DriverManager.getConnection(url, username, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
while (rs.next()) {
System.out.println(rs.getInt("id") + ", " + rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
答案:Java Database Connectivity,用于与数据库交互的API。
实操:使用PreparedStatement插入数据。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JdbcPreparedStatementDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "password";
String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
try (Connection conn = DriverManager.getConnection(url, username, password);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "李四");
pstmt.setInt(2, 30);
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
答案:管理数据库连接的技术,提高性能和资源利用率。
实操:使用HikariCP连接池。
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class ConnectionPoolDemo {
public static void main(String[] args) {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(10);
HikariDataSource dataSource = new HikariDataSource(config);
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
while (rs.next()) {
System.out.println(rs.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案:一组不可分割的数据库操作序列。
实操:使用JDBC管理事务。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TransactionDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "password";
try (Connection conn = DriverManager.getConnection(url, username, password)) {
conn.setAutoCommit(false);
try (PreparedStatement pstmt1 = conn.prepareStatement("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
PreparedStatement pstmt2 = conn.prepareStatement("UPDATE accounts SET balance = balance + 100 WHERE id = 2")) {
pstmt1.executeUpdate();
pstmt2.executeUpdate();
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
答案:通过构造恶意SQL语句攻击数据库,使用PreparedStatement防止。
实操:演示SQL注入及防范。
// 不安全的代码(存在SQL注入风险)
String username = "' OR '1'='1";
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
// 安全的代码
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE username = ?");
pstmt.setString(1, username);
答案:对象关系映射,将对象模型映射到数据库表。
实操:使用Hibernate实现ORM。
import javax.persistence.*;
@Entity
@Table(name = "users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
private String username;
// getters and setters
}
答案:将ResultSet转换为Stream。
实操:将数据库查询结果转换为Stream。
import java.sql.*;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class JdbcStreamDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "password";
try (Connection conn = DriverManager.getConnection(url, username, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
Stream<ResultSet> stream = streamResultSet(rs);
stream.forEach(row -> {
try {
System.out.println(row.getString("username"));
} catch (SQLException e) {
e.printStackTrace();
}
});
} catch (SQLException e) {
e.printStackTrace();
}
}
private static Stream<ResultSet> streamResultSet(ResultSet rs) {
Spliterator<ResultSet> spliterator = Spliterators.spliteratorUnknownSize(
new ResultSetIterator(rs), Spliterator.ORDERED);
return StreamSupport.stream(spliterator, false);
}
static class ResultSetIterator implements java.util.Iterator<ResultSet> {
private final ResultSet resultSet;
private boolean hasNext;
ResultSetIterator(ResultSet resultSet) {
this.resultSet = resultSet;
try {
this.hasNext = resultSet.next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean hasNext() {
return hasNext;
}
@Override
public ResultSet next() {
if (!hasNext) {
throw new java.util.NoSuchElementException();
}
try {
ResultSet current = resultSet;
hasNext = resultSet.next();
return current;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
答案:提高数据库查询效率的数据结构。
实操:创建数据库索引。
// 使用JDBC创建索引
Statement stmt = conn.createStatement();
stmt.executeUpdate("CREATE INDEX idx_username ON users (username)");
答案:预编译的数据库程序,使用CallableStatement调用。
实操:调用存储过程。
try (Connection conn = DriverManager.getConnection(url, username, password);
CallableStatement cstmt = conn.prepareCall("{call get_user_count(?)}")) {
cstmt.registerOutParameter(1, Types.INTEGER);
cstmt.execute();
int count = cstmt.getInt(1);
System.out.println("用户数量: " + count);
}
答案:使用索引、优化查询语句、分页等。
实操:分页查询示例。
int pageSize = 10;
int pageNumber = 2;
int offset = (pageNumber - 1) * pageSize;
String sql = "SELECT * FROM users LIMIT ? OFFSET ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, pageSize);
pstmt.setInt(2, offset);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
// 处理结果
}
}
}
答案:使用套接字实现网络通信的编程方式。
实操:实现简单的TCP客户端-服务器。
// 服务器端
try (ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println("服务器收到: " + inputLine);
}
}
// 客户端
try (Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("服务器响应: " + in.readLine());
}
}
答案:表示统一资源定位符的类。
实操:使用URL读取网页内容。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class URLDemo {
public static void main(String[] args) {
try {
URL url = new URL("https://www.example.com");
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案:用于发送HTTP请求的客户端。
实操:使用Java 11的HttpClient发送请求。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpClientDemo {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
}
}
答案:异步IO,基于回调机制。
实操:使用AsynchronousSocketChannel实现异步服务器。
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
public class AIODemo {
public static void main(String[] args) throws Exception {
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open()
.bind(new InetSocketAddress(8080));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
@Override
public void completed(AsynchronousSocketChannel client, Void attachment) {
server.accept(null, this); // 继续接受下一个连接
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer buffer) {
buffer.flip();
// 处理数据
buffer.clear();
client.read(buffer, buffer, this);
}
@Override
public void failed(Throwable exc, ByteBuffer buffer) {
try {
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
}
});
Thread.sleep(1000000); // 保持服务器运行
}
}
答案:双向通信的网络协议。
实操:使用Java API实现WebSocket客户端。
import javax.websocket.*;
import java.net.URI;
@ClientEndpoint
public class WebSocketClient {
private Session session;
public WebSocketClient(String uri) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
session = container.connectToServer(this, URI.create(uri));
} catch (Exception e) {
e.printStackTrace();
}
}
@OnOpen
public void onOpen(Session session) {
System.out.println("连接打开: " + session.getId());
}
@OnMessage
public void onMessage(String message) {
System.out.println("收到消息: " + message);
}
@OnClose
public void onClose(Session session, CloseReason reason) {
System.out.println("连接关闭: " + reason);
}
public void sendMessage(String message) {
session.getAsyncRemote().sendText(message);
}
}
答案:网络安全设备,控制网络流量。
实操:配置简单的防火墙规则。
# 使用iptables阻止外部访问8080端口
iptables -A INPUT -p tcp --dport 8080 -j DROP
答案:位于客户端和服务器之间的中间服务器。
实操:通过代理服务器发送HTTP请求。
import java.net.*;
import java.io.*;
public class ProxyDemo {
public static void main(String[] args) {
try {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080));
URL url = new URL("https://www.example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案:网络通信的规则和标准。
实操:实现简单的UDP通信。
// 发送方
try (DatagramSocket socket = new DatagramSocket()) {
String message = "Hello, UDP!";
byte[] buffer = message.getBytes();
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 8888);
socket.send(packet);
}
// 接收方
try (DatagramSocket socket = new DatagramSocket(8888)) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println("收到: " + message);
}
答案:基于HTTP协议的API设计风格。
实操:使用Spring Boot创建简单的REST API。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class RestApiDemo {
public static void main(String[] args) {
SpringApplication.run(RestApiDemo.class, args);
}
@GetMapping("/hello/{name}")
public String sayHello(@PathVariable String name) {
return "Hello, " + name + "!";
}
}
答案:轻量级数据交换格式,使用Jackson等库处理。
实操:使用Jackson解析JSON。
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonDemo {
public static void main(String[] args) {
String json = "{\"name\":\"张三\",\"age\":30}";
try {
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(json, Person.class);
System.out.println(person.getName() + ", " + person.getAge());
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Person {
private String name;
private int age;
// getters and setters
}
答案:确保一个类只有一个实例。
实操:实现线程安全的单例模式。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
答案:定义创建对象的接口,由子类决定实例化哪个类。
实操:实现简单工厂模式。
interface Shape {
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
class ShapeFactory {
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
答案:对象间一对多的依赖关系。
实操:实现简单的观察者模式。
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String message);
}
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String message);
}
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
答案:动态地给对象添加额外职责。
实操:实现咖啡装饰器。
interface Beverage {
String getDescription();
double cost();
}
class Espresso implements Beverage {
@Override
public String getDescription() {
return "浓缩咖啡";
}
@Override
public double cost() {
return 1.99;
}
}
abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 牛奶";
}
@Override
public double cost() {
return beverage.cost() + 0.3;
}
}
答案:定义一系列算法并封装,使它们可以互相替换。
实操:实现支付策略。
interface PaymentStrategy {
void pay(double amount);
}
class CreditCardStrategy implements PaymentStrategy {
private String cardNumber;
private String cvv;
public CreditCardStrategy(String cardNumber, String cvv) {
this.cardNumber = cardNumber;
this.cvv = cvv;
}
@Override
public void pay(double amount) {
System.out.println("使用信用卡支付: " + amount);
}
}
class PayPalStrategy implements PaymentStrategy {
private String email;
public PayPalStrategy(String email) {
this.email = email;
}
@Override
public void pay(double amount) {
System.out.println("使用PayPal支付: " + amount);
}
}
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(double amount) {
paymentStrategy.pay(amount);
}
}
答案:将一个类的接口转换成客户希望的另一个接口。
实操:实现电源适配器。
interface EuropeanPlug {
void plugInEuropeanSocket();
}
class EuropeanDevice implements EuropeanPlug {
@Override
public void plugInEuropeanSocket() {
System.out.println("欧洲设备插入欧洲插座");
}
}
interface USAPlug {
void plugInUSASocket();
}
class USADevice implements USAPlug {
@Override
public void plugInUSASocket() {
System.out.println("美国设备插入美国插座");
}
}
class PlugAdapter implements EuropeanPlug {
private USAPlug usaPlug;
public PlugAdapter(USAPlug usaPlug) {
this.usaPlug = usaPlug;
}
@Override
public void plugInEuropeanSocket() {
usaPlug.plugInUSASocket();
System.out.println("使用适配器转换为欧洲插头");
}
}
答案:定义算法骨架,将一些步骤延迟到子类实现。
实操:实现烹饪模板。
abstract class CookingRecipe {
public final void cook() {
prepareIngredients();
cookIngredients();
serve();
}
protected abstract void prepareIngredients();
protected abstract void cookIngredients();
protected void serve() {
System.out.println("上菜");
}
}
class PastaRecipe extends CookingRecipe {
@Override
protected void prepareIngredients() {
System.out.println("准备意大利面和酱料");
}
@Override
protected void cookIngredients() {
System.out.println("煮意大利面,加热酱料");
}
}
答案:将请求的发送者和接收者解耦。
实操:实现请假审批链。
abstract class Approver {
protected Approver successor;
public void setSuccessor(Approver successor) {
this.successor = successor;
}
public abstract void processRequest(int days);
}
class TeamLeader extends Approver {
@Override
public void processRequest(int days) {
if (days <= 3) {
System.out.println("团队领导批准请假 " + days + " 天");
} else if (successor != null) {
successor.processRequest(days);
}
}
}
class DepartmentManager extends Approver {
@Override
public void processRequest(int days) {
if (days <= 7) {
System.out.println("部门经理批准请假 " + days + " 天");
} else if (successor != null) {
successor.processRequest(days);
}
}
}
答案:允许对象在内部状态改变时改变它的行为。
实操:实现电梯状态。
interface ElevatorState {
void openDoor();
void closeDoor();
void goUp();
void goDown();
}
class IdleState implements ElevatorState {
private Elevator elevator;
public IdleState(Elevator elevator) {
this.elevator = elevator;
}
@Override
public void openDoor() {
System.out.println("电梯门打开");
elevator.setState(elevator.getDoorOpenState());
}
@Override
public void closeDoor() {
System.out.println("电梯门已关闭");
}
@Override
public void goUp() {
System.out.println("电梯上升");
elevator.setState(elevator.getMovingUpState());
}
@Override
public void goDown() {
System.out.println("电梯下降");
elevator.setState(elevator.getMovingDownState());
}
}
class Elevator {
private ElevatorState doorOpenState;
private ElevatorState doorClosedState;
private ElevatorState movingUpState;
private ElevatorState movingDownState;
private ElevatorState currentState;
public Elevator() {
doorOpenState = new DoorOpenState(this);
doorClosedState = new DoorClosedState(this);
movingUpState = new MovingUpState(this);
movingDownState = new MovingDownState(this);
currentState = doorClosedState;
}
// getters and setters
}
答案:将一个复杂对象的构建与表示分离。
实操:实现电脑建造者。
class Computer {
private String cpu;
private String ram;
private String storage;
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void setRam(String ram) {
this.ram = ram;
}
public void setStorage(String storage) {
this.storage = storage;
}
@Override
public String toString() {
return "CPU: " + cpu + ", RAM: " + ram + ", Storage: " + storage;
}
}
interface ComputerBuilder {
void buildCpu();
void buildRam();
void buildStorage();
Computer getComputer();
}
class GamingComputerBuilder implements ComputerBuilder {
private Computer computer;
public GamingComputerBuilder() {
this.computer = new Computer();
}
@Override
public void buildCpu() {
computer.setCpu("Intel i9");
}
@Override
public void buildRam() {
computer.setRam("32GB");
}
@Override
public void buildStorage() {
computer.setStorage("1TB SSD");
}
@Override
public Computer getComputer() {
return computer;
}
}
class ComputerDirector {
private ComputerBuilder builder;
public ComputerDirector(ComputerBuilder builder) {
this.builder = builder;
}
public Computer constructComputer() {
builder.buildCpu();
builder.buildRam();
builder.buildStorage();
return builder.getComputer();
}
}
答案:从代码、JVM参数、数据库等多方面优化。
实操:使用StringBuilder替代String拼接。
// 优化前
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // 会创建大量临时对象
}
// 优化后
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i); // 性能更好
}
String result = sb.toString();
答案:调整JVM参数以提高性能。
实操:设置堆内存大小。
java -Xms512m -Xmx1024m MyApp
答案:自动回收不再使用的内存。
实操:监控GC情况。
java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps MyApp
答案:使用工具如VisualVM、MAT等。
实操:使用jstat监控堆内存使用。
jstat -gc <pid> 1000 10
答案:重用对象以减少创建和销毁开销。
实操:实现简单的对象池。
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ObjectPool<T> {
private ConcurrentLinkedQueue<T> pool;
private ScheduledExecutorService executorService;
public ObjectPool(final int minObjects) {
// 初始化对象池
initialize(minObjects);
}
public ObjectPool(final int minObjects, final int maxObjects, final long validationInterval) {
// 初始化对象池
initialize(minObjects);
// 定时检查,维持对象池最小大小
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(() -> {
int size = pool.size();
if (size < minObjects) {
int sizeToBeAdded = minObjects - size;
for (int i = 0; i < sizeToBeAdded; i++) {
pool.add(createObject());
}
} else if (size > maxObjects) {
int sizeToBeRemoved = size - maxObjects;
for (int i = 0; i < sizeToBeRemoved; i++) {
pool.poll();
}
}
}, validationInterval, validationInterval, TimeUnit.SECONDS);
}
public T borrowObject() {
T object;
if ((object = pool.poll()) == null) {
object = createObject();
}
return object;
}
public void returnObject(T object) {
if (object == null) {
return;
}
this.pool.offer(object);
}
public void shutdown() {
if (executorService != null) {
executorService.shutdown();
}
}
private void initialize(final int minObjects) {
pool = new ConcurrentLinkedQueue<>();
for (int i = 0; i < minObjects; i++) {
pool.add(createObject());
}
}
protected T createObject() {
// 由子类实现创建对象的逻辑
return null;
}
}
答案:管理线程的创建和复用。
实操:自定义线程池。
import java.util.concurrent.*;
public class CustomThreadPoolDemo {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
10, // 最大线程数
60, // 线程空闲时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 任务队列
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务
for (int i = 0; i < 20; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("执行任务: " + taskId + ", 线程: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
答案:使用索引、优化SQL语句、避免N+1查询等。
实操:使用EXPLAIN分析查询。
EXPLAIN SELECT * FROM users WHERE age > 30;
答案:临时存储数据以提高访问速度。
实操:使用Guava Cache实现本地缓存。
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
public class CacheDemo {
private static Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
public static String getData(String key) {
String data = cache.getIfPresent(key);
if (data == null) {
data = fetchFromDatabase(key);
cache.put(key, data);
}
return data;
}
private static String fetchFromDatabase(String key) {
// 从数据库获取数据
return "Data for " + key;
}
}
答案:延迟加载数据直到需要使用。
实操:实现懒加载单例。
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
答案:使用工具如JProfiler、YourKit等。
实操:使用Java Mission Control进行性能分析。
jcmd <pid> JFR.start duration=60s filename=recording.jfr
答案:通过构造恶意SQL语句攻击数据库。
实操:使用PreparedStatement防止SQL注入。
// 不安全的代码
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
// 安全的代码
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?");
pstmt.setString(1, username);
pstmt.setString(2, password);
答案:跨站脚本攻击,注入恶意脚本。
实操:对用户输入进行转义。
import org.owasp.encoder.Encode;
public class XSSPrevention {
public static String escapeHTML(String input) {
return Encode.forHtml(input);
}
}
答案:跨站请求伪造,冒充合法用户。
实操:使用CSRF令牌。
// 生成CSRF令牌
String token = UUID.randomUUID().toString();
session.setAttribute("csrfToken", token);
// 在表单中包含令牌
<form>
<input type="hidden" name="csrfToken" value="${csrfToken}">
<!-- 其他表单字段 -->
</form>
// 验证令牌
if (!token.equals(session.getAttribute("csrfToken"))) {
throw new SecurityException("Invalid CSRF token");
}
答案:使用哈希算法加随机盐。
实操:使用BCrypt加密密码。
import org.mindrot.jbcrypt.BCrypt;
public class PasswordHashing {
public static String hashPassword(String password) {
return BCrypt.hashpw(password, BCrypt.gensalt());
}
public static boolean checkPassword(String password, String hashedPassword) {
return BCrypt.checkpw(password, hashedPassword);
}
}
答案:HTTP的安全版本,使用SSL/TLS加密。
实操:配置Spring Boot应用使用HTTPS。
server:
port: 8443
ssl:
key-store: classpath:keystore.p12
key-store-password: yourpassword
key-store-type: PKCS12
key-alias: tomcat
答案:JSON Web Token,用于安全传输信息。
实操:生成和验证JWT。
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "yoursecretkey";
private static final long EXPIRATION_TIME = 86400000; // 24小时
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static String validateToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJ
---