温馨提示:该文章内容超长,如果电脑不行,请慢慢看,不然容易死机(别问我咋知道)
Kind reminder: The content of this article is too long. If your computer is not working, please read it slowly, otherwise it may crash (don’t ask me how I know)
由于文章篇幅过长,一些代码段可能会不完整,有疑问大家可以尽管提
文章目录
- 由于文章篇幅过长,一些代码段可能会不完整,有疑问大家可以尽管提
- Java 知识汇总
- 一、Java 基础
- 二、面向对象编程(OOP)
- 三、异常处理
- 四、Java 集合框架
- 五、Java 输入输出
- 六、Java 多线程
- 七、Java 8 新特性
- 八、Java 反射
- 九、Java 注解
- 十、Java 网络编程
- 十一、Java 数据库编程
- 十二、Java 图形用户界面(GUI)
- 十三、Java 并发工具
- 十四、Java 单元测试
- 十五、Java 序列化
- 十六、Java 内存管理
- 十七、Java 性能优化
- 十八、Java 设计模式
- 十九、Java 安全
- 二十、Java 日志
- 二十一、Java 模块系统
- 二十二、Java 微服务开发
- 二十四、Java 中的泛型
- 二十五、Java 中的并发高级特性
- 二十六、Java 中的代码质量和最佳实践
- 二十七、Java 中的资源管理
- 二十八、Java 中的动态代理
- 二十九、Java 中的脚本引擎
- 三十、Java 中的国际化(i18n)
- Due to the length of the article, some code snippets may be incomplete, so you can mention them if you have any questions
- Java Knowledge Summary
- I. Java Basics
- 2. Object-Oriented Programming (OOP)
- 3. Exception handling
- Fourth, the Java Collection Framework
- 5. Java input and output
- Sixth, Java multithreading
- 7. What's new in Java 8
- VIII. Java Reflection
- IX. Java Annotations
- 10. Java Network Programming
- 11. Java Database Programming
- 12. Java Graphical User Interface (GUI)
- XIII. Java Concurrency Tools
- XIV. Java Unit Tests
- XV. Java Serialization
- XVI. Java memory management
- XVII. Java Performance Optimization
- XVIII. Java Design Patterns
- 19. Java Security
- XXIS, Java Logs
- XXI. Java Module System
- XXII. Java microservices development
- XXIV. Generics in Java
- XXV. Advanced features of concurrency in Java
- XXVI. Code Quality and Best Practices in Java
- XXVII. Resource Management in Java
- XXVIII. Dynamic Agents in Java
- XXIX. Scripting Engine in Java
- 30 Internationalization in Java (i18n)
Java 知识汇总
一、Java 基础
(一)Java 概述
Java 是一种面向对象的编程语言,由 Sun Microsystems(现被 Oracle 收购)开发。它具有跨平台的特性,这得益于 Java 虚拟机(JVM),它可以在不同的操作系统上运行相同的 Java 字节码文件。Java 程序编写完成后,会被编译成字节码文件(.class 文件),然后由 JVM 解释执行。Java 广泛应用于企业级开发、安卓开发、桌面应用开发、Web 开发等多个领域。
(二)数据类型
Java 中的数据类型分为基本数据类型和引用数据类型。
1. 基本数据类型
- 整型:
byte:8 位有符号整数,范围是 -128 到 127。short:16 位有符号整数,范围是 -32768 到 32767。int:32 位有符号整数,范围是 -2147483648 到 2147483647,是最常用的整数类型,例如:int num = 10;long:64 位有符号整数,使用时需要在数字后面加L,例如:long bigNum = 123456789012345L;
- 浮点型:
float:单精度浮点数,需要在数字后面加F,例如:float pi = 3.14F;double:双精度浮点数,是最常用的浮点数类型,例如:double moreAccuratePi = 3.141592653589793;
- 字符型:
char:存储单个字符,使用单引号,例如:char letter = 'A';
- 布尔型:
boolean:只有true和false两个值,用于条件判断,例如:boolean isTrue = true;
2. 引用数据类型
- 类:
- 是 Java 中最重要的引用数据类型,通过
class关键字定义,例如:class Person { String name; int age; } - 可以创建对象,例如:
Person person = new Person(); person.name = "John"; person.age = 25;
- 是 Java 中最重要的引用数据类型,通过
- 接口:
- 定义一组方法签名,使用
interface关键字,例如:interface Animal { void eat(); void sleep(); } - 可以通过类实现接口,例如:
class Dog implements Animal { @Override public void eat() { System.out.println("Dog is eating"); } @Override public void sleep() { System.out.println("Dog is sleeping"); } }
- 定义一组方法签名,使用
- 数组:
- 存储同类型元素的集合,例如:
int[] numbers = new int[5]; numbers[0] = 1; numbers[1] = 2; - 也可以使用简化的数组初始化方式:
int[] numbers = {1, 2, 3, 4, 5};
- 存储同类型元素的集合,例如:
(三)变量和常量
- 变量:
- 用于存储数据,在使用前需要声明和初始化,例如:
int count; count = 10; - 也可以同时声明和初始化:
int score = 85;
- 用于存储数据,在使用前需要声明和初始化,例如:
- 常量:
- 使用
final关键字定义,一旦赋值不能修改,例如:final int MAX_SCORE = 100;
- 使用
(四)运算符
Java 中的运算符包括算术运算符、关系运算符、逻辑运算符、位运算符等。
1. 算术运算符
- 加(
+)、减(-)、乘(*)、除(/)、取余(%),例如:int result = 10 + 5; int remainder = 10 % 3;
2. 关系运算符
- 大于(
>)、小于(<)、等于(==)、不等于(!=)、大于等于(>=)、小于等于(<=),用于条件判断,例如:if (score > 80) { System.out.println("优秀"); }
3. 逻辑运算符
- 逻辑与(
&&)、逻辑或(||)、逻辑非(!),例如:if (score >= 60 && score < 80) { System.out.println("及格"); }
4. 位运算符
- 包括按位与(
&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>)、无符号右移(>>>),主要用于二进制操作,例如:int num1 = 5; // 二进制 0101 int num2 = 3; // 二进制 0011 int result = num1 & num2; // 结果是 0001,即 1
(五)控制流
-
if-else 语句:
if (condition) { // 条件为真时执行 } else { // 条件为假时执行 }例如:
if (age >= 18) { System.out.println("成年"); } else { System.out.println("未成年"); } -
switch 语句:
适用于多分支情况,例如:switch (day) { case 1: System.out.println("星期一"); break; case 2: System.out.println("星期二"); break; // 其他情况 default: System.out.println("其他"); break; } -
for 循环:
for (int i = 0; i < 10; i++) { // 循环体 }例如,计算 1 到 10 的和:
int sum = 0; for (int i = 1; i <= 10; i++) { sum += i; } -
while 循环:
while (condition) { // 循环体 }例如:
int i = 0; while (i < 10) { System.out.println(i); i++; } -
do-while 循环:
至少执行一次循环体,例如:int num; do { System.out.println("请输入一个数:"); num = scanner.nextInt(); } while (num!= 0);
(六)方法
-
方法是可重用的代码块,定义方法的一般形式如下:
returnType methodName(parameters) { // 函数体 return returnValue; }例如:
public int add(int a, int b) { return a + b; }使用方法:
int result = add(3, 5); -
方法可以重载,即可以有多个同名方法,但参数类型或参数数量不同,例如:
public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; }
二、面向对象编程(OOP)
(一)类和对象
-
类的定义:
class MyClass { // 成员变量 private int data; // 构造函数 public MyClass() { data = 0; } // 成员方法 public void setData(int value) { data = value; } public int getData() { return data; } } -
对象的创建和使用:
MyClass obj = new MyClass(); obj.setData(5); System.out.println(obj.getData());
(二)封装
- 使用
private关键字将类的成员变量隐藏起来,通过public方法进行访问和修改,实现封装,例如:class BankAccount { private double balance; public BankAccount() { balance = 0; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) { if (balance >= amount) { balance -= amount; } else { System.out.println("余额不足"); } } public double getBalance() { return balance; } }
(三)继承
- 一个类可以继承另一个类,使用
extends关键字,例如:class Animal { public void eat() { System.out.println("Animal is eating"); } } class Dog extends Animal { @Override public void eat() { System.out.println("Dog is eating"); } }
(四)多态
- 多态是指父类引用指向子类对象,并且调用被子类重写的方法时,会调用子类的方法,例如:
Animal animal = new Dog(); animal.eat(); // 调用 Dog 类的 eat 方法
(五)抽象类和接口
-
抽象类:
- 包含抽象方法(只有方法签名,没有方法体)的类,使用
abstract关键字,例如:abstract class Shape { abstract double area(); } - 子类继承抽象类时必须实现抽象方法,例如:
class Circle extends Shape { private double radius; public Circle(double r) { radius = r; } @Override public double area() { return Math.PI * radius * radius; } }
- 包含抽象方法(只有方法签名,没有方法体)的类,使用
-
接口:
- 只包含方法签名和常量,使用
interface关键字,例如:interface Drawable { void draw(); } - 类实现接口需要实现接口中的所有方法,例如:
class Rectangle implements Drawable { @Override public void draw() { System.out.println("Drawing a rectangle"); } }
- 只包含方法签名和常量,使用
三、异常处理
(一)异常类型
-
Java 中的异常分为
Checked Exception(受检异常)和Unchecked Exception(非受检异常)。 -
Checked Exception必须在代码中显式处理,例如IOException,使用try-catch或throws关键字,例如:import java.io.FileReader; import java.io.IOException; public class ExceptionExample { public static void main(String[] args) { try { FileReader reader = new FileReader("file.txt"); // 操作文件 reader.close(); } catch (IOException e) { e.printStackTrace(); } } } -
Unchecked Exception通常是程序错误,如NullPointerException、ArrayIndexOutOfBoundsException等,例如:public class UncheckedExceptionExample { public static void main(String[] args) { int[] arr = new int[5]; try { System.out.println(arr[10]); } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } } }
(二)自定义异常
- 可以自定义异常类,继承自
Exception或RuntimeException,例如:class MyException extends Exception { public MyException(String message) { super(message); } }
(三)finally 块
finally块中的代码无论是否发生异常都会执行,例如:try { // 可能发生异常的代码 } catch (Exception e) { // 处理异常 } finally { // 清理代码 }
四、Java 集合框架
(一)集合概述
Java 集合框架提供了一套用于存储和操作对象集合的类和接口,主要包括 List、Set、Map 等。
(二)List
-
ArrayList:动态数组,允许存储重复元素,元素有序,例如:import java.util.ArrayList; import java.util.List; public class ArrayListExample { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Apple"); list.add("Banana"); list.add("Apple"); System.out.println(list.get(0)); } } -
LinkedList:基于链表实现,适合频繁插入和删除元素,例如:import java.util.LinkedList; import java.util.List; public class LinkedListExample { public static void main(String[] args) { List<String> list = new LinkedList<>(); list.add("Cat"); list.add("Dog"); list.addFirst("Bird"); System.out.println(list.get(0)); } }
(三)Set
-
HashSet:不允许存储重复元素,元素无序,例如:import java.util.HashSet; import java.util.Set; public class HashSetExample { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("Red"); set.add("Green"); set.add("Red"); System.out.println(set.size()); } } -
TreeSet:元素自动排序,例如:import java.util.TreeSet; import java.util.Set; public class TreeSetExample { public static void main(String[] args) { Set<Integer> set = new TreeSet<>(); set.add(5); set.add(3); set.add(8); System.out.println(set.first()); } }
(四)Map
-
HashMap:存储键值对,键唯一,例如:import java.util.HashMap; import java.util.Map; public class HashMapExample { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("Apple", 10); map.put("Banana", 20); System.out.println(map.get("Apple")); } } -
TreeMap:键自动排序,例如:import java.util.TreeMap; import java.util.Map; public class TreeMapExample { public static void main(String[] args) { Map<String, Integer> map = new TreeMap<>(); map.put("Orange", 15); map.put("Grape", 30); System.out.println(map.firstKey()); } }
五、Java 输入输出
(一)标准输入输出
-
使用
System.out.println()输出,例如:System.out.println("Hello, World!"); -
使用
Scanner类进行输入,例如:import java.util.Scanner; public class InputExample { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入一个数:"); int num = scanner.nextInt(); System.out.println("你输入的数是:" + num); scanner.close(); } }
(二)文件输入输出
- 使用
FileInputStream和FileOutputStream进行文件读写,例如:import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileIOExample { public static void main(String[] args) { try { FileOutputStream fos = new FileOutputStream("output.txt"); fos.write("Hello, File".getBytes()); fos.close(); FileInputStream fis = new FileInputStream("output.txt"); int content; while ((content = fis.read())!= -1) { System.out.print((char) content); } fis.close(); } catch (IOException e) { e.printStackTrace(); } } }
(三)字符流
- 使用
FileReader和FileWriter进行字符读写,例如:import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class CharacterIOExample { public static void main(String[] args) { try { FileWriter fw = new FileWriter("character.txt"); fw.write("Hello, Character"); fw.close(); FileReader fr = new FileReader("character.txt"); int character; while ((character = fr.read())!= -1) { System.out.print((char) character); } fr.close(); } catch (IOException e) { e.printStackTrace(); } } }
(四)缓冲流
- 使用
BufferedReader和BufferedWriter提高读写效率,例如:import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class BufferedIOExample { public static void main(String[] args) { try { BufferedWriter bw = new BufferedWriter(new FileWriter("buffered.txt")); bw.write("Hello, Buffered"); bw.close(); BufferedReader br = new BufferedReader(new FileReader("buffered.txt")); String line; while ((line = br.readLine())!= null) { System.out.println(line); } br.close(); } catch (IOException e) { e.printStackTrace(); } } }
六、Java 多线程
(一)线程基础
-
线程是程序中的执行路径,Java 中可以通过继承
Thread类或实现Runnable接口创建线程。 -
继承
Thread类:class MyThread extends Thread { @Override public void run() { System.out.println("Thread is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); } } -
实现
Runnable接口:class MyRunnable implements Runnable { @Override public void run() { System.out.println("Runnable is running"); } } public class RunnableExample { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
(二)线程同步
- 使用
synchronized关键字实现线程同步,防止多个线程同时访问共享资源,例如:class Counter { private int count = 0; public synchronized void increment() { count++; } }
(三)线程池
- 使用
ExecutorService管理线程池,提高性能,例如:import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { executorService.execute(() -> { System.out.println(Thread.currentThread().getName()); }); } executorService.shutdown(); }
以下是 Java 知识汇总的继续部分:
七、Java 8 新特性
(一)Lambda 表达式
- Lambda 表达式是 Java 8 引入的重要特性,它允许将函数作为方法的参数,使代码更加简洁。
- 基本语法:
(parameters) -> expression或(parameters) -> { statements; }。 - 例如,使用 Lambda 表达式实现
Runnable接口:
public class LambdaExample {
public static void main(String[] args) {
// 传统方式
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello from traditional Runnable");
}
};
runnable1.run();
// Lambda 表达式方式
Runnable runnable2 = () -> System.out.println("Hello from Lambda Runnable");
runnable2.run();
}
}
- Lambda 表达式也可以接收参数,例如:
import java.util.Arrays;
import java.util.List;
public class LambdaWithParameters {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry");
// 使用 Lambda 表达式遍历列表
list.forEach((item) -> System.out.println(item));
}
}
(二)函数式接口
- 函数式接口是只包含一个抽象方法的接口,可使用
@FunctionalInterface注解来声明。 - 例如,自定义函数式接口:
@FunctionalInterface
interface MyFunction {
int apply(int a, int b);
}
- 使用 Lambda 表达式调用函数式接口:
public class FunctionalInterfaceExample {
public static void main(String[] args) {
MyFunction add = (a, b) -> a + b;
int result = add.apply(3, 5);
System.out.println(result);
}
}
- Java 8 内置了许多函数式接口,如
Consumer、Supplier、Function、Predicate等,例如使用Consumer打印元素:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class BuiltInFunctionalInterface {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry");
Consumer<String> consumer = (item) -> System.out.println(item);
list.forEach(consumer);
}
}
(三)Stream API
- Stream API 提供了一种对集合进行操作的新方式,支持并行处理。
- 创建流:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 从集合创建流
Stream<Integer> stream = numbers.stream();
// 从数组创建流
int[] array = {1, 2, 3, 4, 5};
Stream<int[]> arrayStream = Stream.of(array);
}
}
- 中间操作:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamIntermediateOperations {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 过滤元素
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 映射元素
List<String> stringNumbers = numbers.stream()
.map(n -> n.toString())
.collect(Collectors.toList());
}
}
- 终端操作:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamTerminalOperations {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 求和
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
// 查找元素
Optional<Integer> firstEven = numbers.stream()
.filter(n -> n % 2 == 0)
.findFirst();
}
}
(四)日期和时间 API
- Java 8 引入了新的日期和时间 API(
java.time包)。 LocalDate表示日期:
import java.time.LocalDate;
public class LocalDateExample {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println(today);
LocalDate specificDate = LocalDate.of(2025, 1, 22);
System.out.println(specificDate);
}
}
LocalTime表示时间:
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println(now);
LocalTime specificTime = LocalTime.of(12, 30, 45);
System.out.println(specificTime);
}
}
LocalDateTime表示日期和时间:
import java.time.LocalDateTime;
public class LocalDateTimeExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
LocalDateTime specificDateTime = LocalDateTime.of(2025, 1, 22, 12, 30, 45);
System.out.println(specificDateTime);
}
}
八、Java 反射
(一)反射基础
- 反射允许程序在运行时检查类、接口、方法、字段等信息,并动态调用方法或访问字段。
- 获取类的信息:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class MyClass {
private int value;
public void display() {
System.out.println("Value: " + value);
}
}
public class ReflectionExample {
public static void main(String[] args) {
try {
Class<?> clazz = MyClass.class;
// 获取类的方法
Method method = clazz.getMethod("display");
// 获取类的字段
Field field = clazz.getDeclaredField("value");
} catch (NoSuchMethodException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}
(二)动态创建对象和调用方法
- 使用反射创建对象:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, " + name);
}
}
public class DynamicObjectCreation {
public static void main(String[] args) {
try {
Class<?> clazz = Person.class;
// 获取构造函数
Constructor<?> constructor = clazz.getConstructor(String.class);
// 创建对象
Object person = constructor.newInstance("John");
// 调用方法
Method method = clazz.getMethod("sayHello");
method.invoke(person);
} catch (Exception e) {
e.printStackTrace();
}
}
}
(三)修改字段的值
- 使用反射修改私有字段的值:
import java.lang.reflect.Field;
class Employee {
private double salary;
public Employee(double salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
}
public class FieldModification {
public static void main(String[] args) {
try {
Employee employee = new Employee(50000);
Class<?> clazz = Employee.class;
Field field = clazz.getDeclaredField("salary");
field.setAccessible(true);
// 修改字段值
field.set(employee, 60000);
System.out.println(employee.getSalary());
} catch (Exception e) {
e.printStackTrace();
}
}
}
九、Java 注解
(一)注解基础
- 注解是元数据,为程序元素(类、方法、字段等)添加额外信息。
- 自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
- 使用注解:
@MyAnnotation(value = "This is a class annotation")
class AnnotatedClass {
}
(二)元注解
- 元注解用于修饰注解,如
@Target、@Retention、@Documented、@Inherited等。 @Target定义注解的使用位置(类、方法、字段等)。@Retention定义注解的生命周期(源码、类文件、运行时)。
(三)使用注解处理器
- 可以使用注解处理器处理注解,例如:
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyMethodAnnotation {
String value();
}
class MyClassWithAnnotation {
@MyMethodAnnotation("This is a method annotation")
public void myMethod() {
}
}
public class AnnotationProcessor {
public static void main(String[] args) {
try {
Class<?> clazz = MyClassWithAnnotation.class;
Method method = clazz.getMethod("myMethod");
Annotation annotation = method.getAnnotation(MyMethodAnnotation.class);
if (annotation instanceof MyMethodAnnotation) {
MyMethodAnnotation myMethodAnnotation = (MyMethodAnnotation) annotation;
System.out.println(myMethodAnnotation.value());
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
十、Java 网络编程
(一)Socket 编程
- 使用
Socket和ServerSocket进行 TCP 编程。 - 服务器端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("Server is listening on port 8080");
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
// 处理输入输出流
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 客户端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class SimpleClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 8080);
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
// 处理输入输出流
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(二)UDP 编程
- 使用
DatagramSocket和DatagramPacket进行 UDP 编程。 - 服务器端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpServer {
public static void main(String[] args) {
try {
DatagramSocket socket = new DatagramSocket(9090);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
// 处理数据包
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 客户端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpClient {
public static void main(String[] args) {
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, 9090);
socket.send(packet);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
十一、Java 数据库编程
(一)JDBC 基础
- JDBC 是 Java 访问数据库的标准接口,通过
DriverManager连接数据库。 - 示例:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcExample {
public static void main(String[] args) {
try {
// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
Statement statement = connection.createStatement();
// 执行查询
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
}
// 关闭资源
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(二)PreparedStatement
- 防止 SQL 注入,使用
PreparedStatement。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class PreparedStatementExample {
public static void main(String[] args) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
String sql = "SELECT * FROM users WHERE id =?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
}
resultSet.close();
preparedStatement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(三)事务管理
- 使用
setAutoCommit和commit管理事务。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TransactionExample {
public static void main(String[] args) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
connection.setAutoCommit(false);
PreparedStatement statement1 = connection.prepareStatement("INSERT INTO users (username) VALUES ('user1')");
PreparedStatement statement2 = connection.prepareStatement("INSERT INTO users (username) VALUES ('user2')");
statement1.executeUpdate();
statement2.executeUpdate();
connection.commit();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
十二、Java 图形用户界面(GUI)
(一)Swing 基础
- Swing 是 Java 的 GUI 工具包,提供了各种组件,如
JFrame、JButton、JTextField等。 - 创建一个简单的窗口:
import javax.swing.JFrame;
public class SimpleSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("Simple Swing");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
(二)布局管理器
- 使用布局管理器组织组件,如
FlowLayout、BorderLayout、GridLayout等。 - 使用
FlowLayout:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.FlowLayout;
public class FlowLayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("FlowLayout Example");
JPanel panel = new JPanel(new FlowLayout());
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 2");
panel.add(button1);
panel.add(button2);
frame.add(panel);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
(三)事件处理
- 使用监听器处理事件,如
ActionListener处理按钮点击事件。
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class EventHandling {
public static void main(String[] args) {
JFrame frame = new JFrame("Event Handling");
JPanel panel = new JPanel(new FlowLayout());
JButton button = new JButton("Click Me");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Button Clicked");
}
});
panel.add(button);
frame.add(panel);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
十三、Java 并发工具
(一)CountDownLatch
CountDownLatch用于线程间的等待,等待多个线程完成任务。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is running");
latch.countDown();
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
try {
latch.await();
System.out.println("All tasks completed");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(二)CyclicBarrier
CyclicBarrier用于多个线程在一个屏障点等待彼此。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached the barrier"));
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " is running");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
(三)Semaphore
Semaphore用于控制并发访问资源的数量。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
Runnable task = () -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is accessing resource");
Thread.sleep(1000);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
十四、Java 单元测试
(一)JUnit 框架
- JUnit 是 Java 最常用的单元测试框架,使用
@Test注解测试方法。
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class JUnitExample {
@Test
public void testAddition() {
int result = 2 + 3;
assertEquals(5, result);
}
}
以下是 Java 知识汇总的后续部分:
十五、Java 序列化
(一)序列化基础
- 序列化是将对象转换为字节流,以便存储或传输,反序列化则是将字节流转换回对象。
- 实现
Serializable接口的类可以被序列化:
import java.io.*;
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class SerializationExample {
public static void main(String[] args) {
Person person = new Person("Alice", 25);
try {
// 序列化
FileOutputStream fileOut = new FileOutputStream("person.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in person.ser");
// 反序列化
FileInputStream fileIn = new FileInputStream("person.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
Person deserializedPerson = (Person) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Person: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
(二)自定义序列化
- 可以通过
writeObject和readObject方法自定义序列化和反序列化过程:
import java.io.*;
class CustomSerializablePerson implements Serializable {
private String name;
private transient int age; // transient 关键字表示该字段不参与序列化
public CustomSerializablePerson(String name, int age) {
this.name = name;
this.age = age;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
// 自定义序列化逻辑
out.writeInt(age + 1); // 对 age 进行特殊处理
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
// 自定义反序列化逻辑
age = in.readInt() - 1; // 恢复 age 的值
}
@Override
public String toString() {
return "CustomSerializablePerson{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class CustomSerializationExample {
public static void main(String[] args) {
CustomSerializablePerson person = new CustomSerializablePerson("Bob", 30);
try {
// 序列化
FileOutputStream fileOut = new FileOutputStream("customPerson.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileIn.close();
System.out.println("Serialized data is saved in customPerson.ser");
// 反序列化
FileInputStream fileIn = new FileInputStream("customPerson.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
CustomSerializablePerson deserializedPerson = (CustomSerializablePerson) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Person: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
(三)序列化版本号
- 为了确保序列化和反序列化的兼容性,可使用
serialVersionUID字段:
import java.io.*;
class VersionedPerson implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public VersionedPerson(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "VersionedPerson{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class SerializationVersionExample {
public static void main(String[] args) {
VersionedPerson person = new VersionedPerson("Charlie", 35);
try {
// 序列化
FileOutputStream fileOut = new FileOutputStream("versionedPerson.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in versionedPerson.ser");
// 反序列化
FileInputStream fileIn = new FileInputStream("versionedPerson.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
VersionedPerson deserializedPerson = (VersionedPerson) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Person: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
十六、Java 内存管理
(一)Java 内存结构
- Java 内存分为堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(Program Counter Register)和本地方法栈(Native Method Stack)。
- 堆:存储对象实例,由垃圾回收器管理。
- 栈:存储局部变量和方法调用信息。
- 方法区:存储类信息、静态变量、常量等。
(二)垃圾回收(GC)
- Java 中的垃圾回收器自动回收不再使用的对象,常见的垃圾回收算法有标记-清除、复制、标记-整理等。
- 可通过
System.gc()建议 JVM 进行垃圾回收,但不能保证立即执行:
public class GarbageCollectionExample {
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
new Object();
}
System.gc();
}
}
(三)内存泄漏
- 内存泄漏是指程序中不再使用的对象仍然占用内存,可能由于对象未正确释放、静态集合持有对象引用等原因导致。
- 避免内存泄漏的一些最佳实践:
- 及时释放资源,如关闭文件、数据库连接、网络连接等。
- 避免使用静态集合存储大量对象。
- 注意对象的生命周期,避免长生命周期对象持有短生命周期对象的引用。
十七、Java 性能优化
(一)代码优化
- 减少对象创建:尽量复用对象,避免频繁创建新对象,如使用
StringBuilder代替String拼接:
public class StringConcatenation {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
}
}
-
使用高效的数据结构:根据使用场景选择合适的数据结构,如
HashSet比ArrayList在查找元素时更高效。 -
避免过度同步:仅在必要时使用
synchronized关键字,避免性能开销。
(二)JVM 优化
- 调整堆大小:根据应用程序的内存需求,调整
-Xmx和-Xms参数:
java -Xmx512m -Xms256m MyApp
- 使用性能分析工具:如 VisualVM、JProfiler 等工具分析程序性能,找出性能瓶颈。
(三)多线程优化
- 合理使用线程池:避免频繁创建和销毁线程,使用
ExecutorService管理线程池:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolOptimization {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executorService.execute(() -> {
// 任务逻辑
});
}
executorService.shutdown();
}
}
- 避免死锁:合理安排锁的获取顺序,使用
tryLock避免死锁。
十八、Java 设计模式
(一)单例模式
- 确保一个类只有一个实例,提供全局访问点。
- 饿汉式单例:
class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
- 懒汉式单例:
class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
(二)工厂模式
- 工厂模式用于创建对象,将对象创建逻辑封装在工厂类中。
- 简单工厂模式:
interface Product {
void use();
}
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductA");
}
}
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductB");
}
}
class SimpleFactory {
public static Product createProduct(String type) {
if (type.equals("A")) {
return new ConcreteProductA();
} else if (type.equals("B")) {
return new ConcreteProductB();
}
return null;
}
}
public class FactoryPatternExample {
public static void main(String[] args) {
Product productA = SimpleFactory.createProduct("A");
productA.use();
}
}
(三)观察者模式
- 当一个对象的状态发生变化时,通知其他对象。
- 观察者接口:
interface Observer {
void update(String message);
}
class ConcreteObserver implements Observer {
@Override
public void update(String message) {
System.out.println("Received message: " + message);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
public class ObserverPatternExample {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers("Hello, Observers!");
}
}
(四)代理模式
- 为其他对象提供代理,以控制对该对象的访问。
- 静态代理:
interface Image {
void display();
}
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading " + fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display();
image.display(); // 第二次显示时无需重新加载
}
}
十九、Java 安全
(一)安全管理器
- Java 安全管理器可以控制 Java 程序的权限,例如限制文件访问、网络访问等。
import java.io.File;
import java.io.FileReader;
import java.security.Permission;
public class SecurityManagerExample {
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission perm) {
if (perm instanceof java.io.FilePermission) {
// 自定义权限检查逻辑
System.out.println("Checking permission: " + perm);
}
}
});
try {
FileReader reader = new FileReader(new File("test.txt"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
(二)加密与解密
- 使用 Java 加密扩展(JCE)进行加密和解密操作。
- 对称加密(AES):
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
public class SymmetricEncryption {
public static void main(String[] args) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] input = "Hello, Encryption".getBytes(StandardCharsets.UTF_8);
byte[] encryptedBytes = cipher.doFinal(input);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
System.out.println(new String(decryptedBytes, StandardCharsets.UTF_8));
}
}
- 非对称加密(RSA):
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;
public class AsymmetricEncryption {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] input = "Hello, RSA".getBytes();
byte[] encryptedBytes = cipher.doFinal(input);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
System.out.println(new String(decryptedBytes));
}
}
(三)数字签名
- 数字签名用于验证消息的来源和完整性。
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
public class DigitalSignature {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
Signature signature = Signature.getInstance("SHA256withDSA");
signature.initSign(privateKey);
String message = "Hello, Digital Signature";
signature.update(message.getBytes());
byte[] sign = signature.sign();
signature.initVerify(publicKey);
signature.update(message.getBytes());
boolean verified = signature.verify(sign);
System.out.println("Signature verified: " + verified);
}
}
二十、Java 日志
(一)日志框架
- Java 自带的日志框架
java.util.logging或常用的第三方日志框架如 Log4j、Logback。 - 使用
java.util.logging:
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingExample {
private static final Logger logger = Logger.getLogger(LoggingExample.class.getName());
public static void main(String[] args) {
logger.log(Level.INFO, "This is an info message");
logger.log(Level.WARNING, "This is a warning message");
}
}
(二)Log4j 日志框架
- 配置 Log4j:
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<root>
<priority value="info" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
- 使用 Log4j 进行日志记录:
import org.apache.log4j.Logger;
public class Log4jExample {
private static final Logger logger = Logger.getLogger(Log4jExample.class);
public static void main(String[] args) {
logger.info("This is an info message from Log4j");
logger.warn("This is a warning message from Log4j");
}
}
(三)日志级别和配置
- 日志级别包括
TRACE、DEBUG、INFO、WARN、ERROR、FATAL。 - 可以根据需要配置日志级别和日志输出位置,如文件、控制台等。
二十一、Java 模块系统
(一)模块基础
- Java 9 引入了模块系统,使用
module-info.java文件定义模块。 - 示例模块定义:
module com.example.myModule {
exports com.example.myPackage;
}
(二)模块依赖
- 模块可以依赖其他模块,在
module-info.java中声明:
module com.example.myModule {
requires java.sql;
exports com.example.myPackage;
}
(三)服务
- 模块可以提供和使用服务,使用
provides和uses关键字:
module com.example.serviceProvider {
provides com.example.MyService with com.example.MyServiceImpl;
}
module com.example.serviceConsumer {
uses com.example.MyService;
}
二十二、Java 微服务开发
(一)Spring Boot
- Spring Boot 是一个快速开发微服务的框架,简化了 Spring 框架的配置。
- 创建一个简单的 Spring Boot 应用:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class SpringBootExample {
public static void main(String[] args) {
SpringApplication.run(SpringBootExample.class, args);
}
}
@RestController
class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
(二)Spring Cloud
- Spring Cloud 提供了微服务的解决方案,包括服务发现、配置管理、断路器等。
- 服务发现(Eureka):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerExample {
public static void main(String[] args) {
SpringApplication.run(EurekaServerExample.class, args);
}
}
(三)Docker 与 Java 微服务
- 使用 Docker 容器化 Java 微服务:
FROM openjdk:11
COPY target/my-service.jar /app.jar
CMD ["java", "-jar", "/app.jar"]
(四)Kubernetes 部署
- 使用 Kubernetes 部署和管理 Java 微服务集群:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-service
ports:
- protocol: TCP
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-service-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-service
template:
metadata:
labels:
app: my-service
spec:
containers:
- name: my-service
image: my-service-image:latest
ports:
- containerPort: 8080
## 二十三、Java 中的函数式编程
### (一)函数作为一等公民
- 在 Java 8 及以后的版本中,函数可以作为方法的参数、返回值,以及存储在变量中。这是函数式编程的重要特征之一。
```java
import java.util.function.Function;
public class FunctionAsFirstClassCitizen {
public static void main(String[] args) {
Function<Integer, Integer> addOne = (x) -> x + 1;
int result = applyFunction(5, addOne);
System.out.println(result);
}
public static int applyFunction(int input, Function<Integer, Integer> function) {
return function.apply(input);
}
}
(二)方法引用
- 方法引用提供了一种简洁的方式来调用现有方法。它可以替代 Lambda 表达式,让代码更加简洁。
- 静态方法引用:
import java.util.Arrays;
import java.util.List;
class StringUtils {
public static int stringLength(String str) {
return str.length();
}
}
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry");
// 使用静态方法引用
strings.stream()
.map(StringUtils::stringLength)
.forEach(System.out::println);
}
}
- 实例方法引用:
import java.util.Arrays;
import java.util.List;
class Printer {
public void print(String str) {
System.out.println(str);
}
}
public class InstanceMethodReference {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry");
Printer printer = new Printer();
// 使用实例方法引用
strings.forEach(printer::print);
}
}
(三)组合函数
- 可以将多个函数组合成一个新的函数,这在函数式编程中很常见。
import java.util.function.Function;
public class FunctionComposition {
public static void main(String[] args) {
Function<Integer, Integer> addOne = (x) -> x + 1;
Function<Integer, Integer> multiplyByTwo = (x) -> x * 2;
// 组合函数
Function<Integer, Integer> addOneAndMultiplyByTwo = multiplyByTwo.compose(addOne);
int result = addOneAndMultiplyByTwo.apply(3);
System.out.println(result);
}
}
(四)高阶函数
- 高阶函数是接受一个或多个函数作为参数,或者返回一个函数的函数。
import java.util.function.Function;
public class HigherOrderFunction {
public static Function<Integer, Function<Integer, Integer>> createAdder() {
return (x) -> (y) -> x + y;
}
public static void main(String[] args) {
Function<Integer, Function<Integer, Integer>> adder = createAdder();
Function<Integer, Integer> addFive = adder.apply(5);
int result = addFive.apply(3);
System.out.println(result);
}
}
二十四、Java 中的泛型
(一)泛型基础
- 泛型允许我们创建可以处理多种类型的类和方法,提高代码的复用性和类型安全性。
- 泛型类:
class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
public class GenericClassExample {
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get());
}
}
(二)泛型方法
- 可以在方法上使用泛型,而不依赖于类的泛型。
class GenericMethodClass {
public static <T> T getFirst(List<T> list) {
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
}
public class GenericMethodExample {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry");
String first = GenericMethodClass.getFirst(strings);
System.out.println(first);
}
}
(三)通配符
- 通配符
?可以用于表示未知类型,在某些情况下可以使代码更加灵活。 - 上界通配符:
import java.util.ArrayList;
import java.util.List;
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class UpperBoundedWildcard {
public static void printAnimals(List<? extends Animal> animals) {
for (Animal animal : animals) {
System.out.println(animal);
}
}
public static void main(String[] args) {
List<Dog> dogs = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
printAnimals(dogs);
printAnimals(cats);
}
}
- 下界通配符:
import java.util.ArrayList;
import java.util.List;
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class LowerBoundedWildcard {
public static void addAnimal(List<? super Dog> animals) {
animals.add(new Dog());
}
public static void main(String[] args) {
List<Animal> animals = new ArrayList<>();
List<Dog> dogs = new ArrayList<>();
addAnimal(animals);
addAnimal(dogs);
}
}
(四)类型擦除
- 泛型信息在编译后会被擦除,在运行时不保留。
class GenericClass<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
public class TypeErasureExample {
public static void main(String[] args) {
GenericClass<String> stringClass = new GenericClass<>();
Class<?> clazz = stringClass.getClass();
// 类型擦除后,T 被替换为 Object 或边界类型
System.out.println(clazz.getDeclaredFields()[0].getType());
}
}
二十五、Java 中的并发高级特性
(一)Fork/Join 框架
- Fork/Join 框架用于并行执行任务,适用于可以分解为子任务的问题。
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;
class FibonacciTask extends RecursiveTask<Integer> {
final int n;
FibonacciTask(int n) {
this.n = n;
}
@Override
protected Integer compute() {
if (n <= 1)
return n;
FibonacciTask f1 = new FibonacciTask(n - 1);
f1.fork();
FibonacciTask f2 = new FibonacciTask(n - 2);
return f2.compute() + f1.join();
}
}
public class ForkJoinExample {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
FibonacciTask task = new FibonacciTask(10);
int result = forkJoinPool.invoke(task);
System.out.println(result);
}
}
(二)CompletableFuture
CompletableFuture提供了一种异步编程的强大方式,可以处理异步操作的结果和异常。- 异步执行任务:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 2 + 3);
int result = future.get();
System.out.println(result);
}
}
- 组合多个异步任务:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureCombination {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 3);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (a, b) -> a + b);
int result = combinedFuture.get();
System.out.println(result);
}
}
(三)并行流
- 并行流可以方便地将流操作并行化。
import java.util.Arrays;
public class ParallelStreamExample {
public static void main(String[] args) {
int sum = Arrays.asList(1, 2, 3, 4, 5)
.parallelStream()
.mapToInt(i -> i)
.sum();
System.out.println(sum);
}
}
二十六、Java 中的代码质量和最佳实践
(一)代码规范
- 遵循 Java 编码规范,如命名约定、代码结构、注释规范等。
- 变量命名:使用驼峰命名法,如
userName。 - 方法命名:使用动词开头,如
getUserById。 - 类命名:使用名词,首字母大写,如
UserService。
(二)代码审查
- 定期进行代码审查,检查代码的质量、可读性、可维护性和性能。
- 检查代码是否遵循编码规范。
- 检查潜在的 bug 和逻辑错误。
(三)单元测试最佳实践
- 测试覆盖率:尽量保证高的测试覆盖率,使用工具如 JaCoCo 进行测试覆盖度检查。
- 测试用例独立性:每个测试用例应该独立运行,不依赖其他测试用例。
- 测试用例可维护性:测试用例应该易于维护,当代码修改时,测试用例也容易更新。
(四)持续集成和持续部署(CI/CD)
- 使用 CI/CD 工具(如 Jenkins、GitLab CI、GitHub Actions)自动化构建、测试和部署流程。
- 配置 CI 流程,在代码提交后自动进行构建和测试。
二十七、Java 中的资源管理
(一)try-with-resources
try-with-resources语句确保资源(如文件、网络连接、数据库连接)在使用后自动关闭,避免资源泄漏。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResources {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine())!= null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(二)AutoCloseable 接口
- 实现
AutoCloseable接口的类可以在try-with-resources中使用。
import java.io.Closeable;
import java.io.IOException;
class CustomResource implements AutoCloseable {
@Override
public void close() throws IOException {
System.out.println("Resource closed");
}
}
public class AutoCloseableExample {
public static void main(String[] args) {
try (CustomResource resource = new CustomResource()) {
// 使用资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
(三)资源池
- 对于昂贵的资源(如数据库连接、线程池),使用资源池管理,避免频繁创建和销毁资源。
- 数据库连接池:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class ConnectionPoolExample {
public static void main(String[] args) throws SQLException {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
Connection connection = dataSource.getConnection();
// 使用连接
connection.close();
}
}
二十八、Java 中的动态代理
(一)动态代理基础
- 动态代理允许在运行时创建代理类,无需提前定义代理类。
- 使用
java.lang.reflect.Proxy类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Service {
void doSomething();
}
class ServiceImpl implements Service {
@Override
public void doSomething() {
System.out.println("Doing something");
}
}
class ServiceInvocationHandler implements InvocationHandler {
private Object target;
public ServiceInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method invocation");
Object result = method.invoke(target, args);
System.out.println("After method invocation");
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
Service service = new ServiceImpl();
Service proxy = (Service) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new ServiceInvocationHandler(service)
);
proxy.doSomething();
}
}
(二)应用场景
- 动态代理常用于 AOP(面向切面编程),如日志记录、事务管理、性能监控等。
二十九、Java 中的脚本引擎
(一)脚本引擎基础
- Java 提供了脚本引擎,可以运行脚本语言(如 JavaScript、Groovy)。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineExample {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
Object result = engine.eval("2 + 3");
System.out.println(result);
}
}
(二)与 Java 代码交互
- 脚本引擎可以与 Java 代码交互,调用 Java 方法和访问 Java 对象。
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineInteraction {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
Bindings bindings = engine.getBindings(javax.script.ScriptContext.ENGINE_SCOPE);
bindings.put("greeting", "Hello");
engine.eval("print(greeting + ', World!')");
}
}
三十、Java 中的国际化(i18n)
(一)资源束
- 使用资源束存储不同语言的文本信息。
- 创建
Messages.properties文件:
greeting=Hello
- 创建
Messages_fr.properties文件(法语):
greeting=Bonjour
- 使用资源束:
import java.util.Locale;
import java.util.ResourceBundle;
public class InternationalizationExample {
public static void main(String[] args) {
Locale locale = new Locale("fr");
ResourceBundle bundle = ResourceBundle.getBundle("Messages", locale);
System.out.println(bundle.getString("greeting"));
}
}
(二)格式化消息
- 使用
MessageFormat格式化消息:
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
public class MessageFormatting {
public static void main(String[] args) {
Locale locale = new Locale("en");
ResourceBundle bundle = ResourceBundle.getBundle("Messages", locale);
String message = bundle.getString("welcome");
String formattedMessage = MessageFormat.format(message, "John");
System.out.println(formattedMessage);
}
}
以上 Java 知识汇总涵盖了 Java 编程的多个方面,从基础的数据类型、面向对象编程到高级的并发、微服务开发、函数式编程等,希望能帮助你全面掌握 Java 编程技能。在学习过程中,要多动手实践,结合实际项目不断提升自己的编程水平,并且持续关注 Java 语言的新特性和发展趋势,以便更好地运用 Java 开发出高质量的软件系统。
请注意,此文档只是 Java 众多知识中的一部分,Java 语言不断发展,新的特性和框架不断涌现,需要不断学习和探索。
你可以根据自己的学习进度和兴趣,对每个部分进行深入研究,阅读官方文档、参考书籍和参与开源项目,将有助于你更加深入理解和掌握 Java 编程。如果你在学习或开发过程中遇到问题,可以使用调试工具、搜索引擎和社区论坛(如 Stack Overflow)来解决问题。祝你在 Java 编程的道路上取得更大的进步
Due to the length of the article, some code snippets may be incomplete, so you can mention them if you have any questions
Here’s a summary of Java knowledge that covers many of the most important aspects of Java that you can adapt and expand to suit your needs.
文章目录
- 由于文章篇幅过长,一些代码段可能会不完整,有疑问大家可以尽管提
- Java 知识汇总
- 一、Java 基础
- 二、面向对象编程(OOP)
- 三、异常处理
- 四、Java 集合框架
- 五、Java 输入输出
- 六、Java 多线程
- 七、Java 8 新特性
- 八、Java 反射
- 九、Java 注解
- 十、Java 网络编程
- 十一、Java 数据库编程
- 十二、Java 图形用户界面(GUI)
- 十三、Java 并发工具
- 十四、Java 单元测试
- 十五、Java 序列化
- 十六、Java 内存管理
- 十七、Java 性能优化
- 十八、Java 设计模式
- 十九、Java 安全
- 二十、Java 日志
- 二十一、Java 模块系统
- 二十二、Java 微服务开发
- 二十四、Java 中的泛型
- 二十五、Java 中的并发高级特性
- 二十六、Java 中的代码质量和最佳实践
- 二十七、Java 中的资源管理
- 二十八、Java 中的动态代理
- 二十九、Java 中的脚本引擎
- 三十、Java 中的国际化(i18n)
- Due to the length of the article, some code snippets may be incomplete, so you can mention them if you have any questions
- Java Knowledge Summary
- I. Java Basics
- 2. Object-Oriented Programming (OOP)
- 3. Exception handling
- Fourth, the Java Collection Framework
- 5. Java input and output
- Sixth, Java multithreading
- 7. What's new in Java 8
- VIII. Java Reflection
- IX. Java Annotations
- 10. Java Network Programming
- 11. Java Database Programming
- 12. Java Graphical User Interface (GUI)
- XIII. Java Concurrency Tools
- XIV. Java Unit Tests
- XV. Java Serialization
- XVI. Java memory management
- XVII. Java Performance Optimization
- XVIII. Java Design Patterns
- 19. Java Security
- XXIS, Java Logs
- XXI. Java Module System
- XXII. Java microservices development
- XXIV. Generics in Java
- XXV. Advanced features of concurrency in Java
- XXVI. Code Quality and Best Practices in Java
- XXVII. Resource Management in Java
- XXVIII. Dynamic Agents in Java
- XXIX. Scripting Engine in Java
- 30 Internationalization in Java (i18n)
Java Knowledge Summary
I. Java Basics
(1) Java Overview
Java is an object-oriented programming language developed by Sun Microsystems (now acquired by Oracle). It is cross-platform, thanks to the Java Virtual Machine (JVM), which can run the same Java bytecode file on different operating systems. Once a Java program is written, it is compiled into a bytecode file (.class file) that is then interpreted and executed by the JVM. Java is widely used in enterprise development, Android development, desktop application development, web development, and other fields.
(2) Data type
Data types in Java are divided into basic data types and reference data types.
1. Basic data types
- Integer:
- ‘byte’: An 8-bit signed integer with a range of -128 to 127.
- ‘short’: A 16-bit signed integer with a range of -32768 to 32767.
- ‘int’: A 32-bit signed integer, ranging from -2147483648 to 2147483647, and is the most commonly used type of integer, for example:
int num = 10; - ‘long’: A 64-bit signed integer that needs to be followed by an ‘L’ when used, for example:
long bigNum = 123456789012345L;
- Floating-point:
- ‘float’: a single-precision floating-point number with ‘F’ after the number, for example:
float pi = 3.14F; - ‘double’: a double-precision floating-point number, which is the most commonly used type of floating-point number, for example:
double moreAccuratePi = 3.141592653589793;
- ‘float’: a single-precision floating-point number with ‘F’ after the number, for example:
- Character Type:
- ‘char’: Stores a single character, using single quotes, e.g.:
char letter = 'A';
- ‘char’: Stores a single character, using single quotes, e.g.:
- Boolean:
- ‘boolean’: There are only two values, ‘true’ and ‘false’, which are used for conditional judgment, for example:
boolean isTrue = true;
- ‘boolean’: There are only two values, ‘true’ and ‘false’, which are used for conditional judgment, for example:
2. Reference data type
-Kind:
- is the most important type of reference data in Java, defined by the ‘class’ keyword, for example:
class Person { String name; int age; } - You can create objects, such as:
Person person = new Person(); person.name = "John"; person.age = 25;
-Interface:
- Define a set of method signatures, using the ‘interface’ keyword, for example:
interface Animal { void eat(); void sleep(); } - Interfaces can be implemented via classes, such as:
class Dog implements Animal { @Override public void eat() { System.out.println("Dog is eating"); } @Override public void sleep() { System.out.println("Dog is sleeping"); } }
-Array:
- Store a collection of elements of the same type, such as:
int[] numbers = new int[5]; numbers[0] = 1; numbers[1] = 2; - You can also use a simplified array initialization:
int[] numbers = {1, 2, 3, 4, 5};
(3) Variables and constants
-Variable:
- Used to store data, which needs to be declared and initialized before use, e.g.:
int count; count = 10; - It is also possible to declare and initialize at the same time:
int score = 85;
-Constant:
- Use the ‘final’ keyword definition, once the assignment cannot be modified, for example:
final int MAX_SCORE = 100;
(iv) Operator
Operators in Java include arithmetic operators, relational operators, logical operators, bitwise operators, and so on.
1. Arithmetic operators
- Add (‘+’), subtract (‘-’), multiply (‘*’), divide (‘/’), take balance (‘%’), e.g.:
int result = 10 + 5; int remainder = 10 % 3;
2. Relational operators
- Greater than (‘>’), less than (‘<’), equal to (‘==’), not equal to (‘!=’), greater than or equal to (‘>=’), less than or equal to (‘<=’) for conditional judgment, for example:
if (score > 80) { System.out.println("优秀"); }
3. Logical operators
- Logical and (‘&&’), logical, or (‘||’), logical non (‘!’), for example:
if (score >= 60 && score < 80) { System.out.println("及格"); }
4. Bitwise operators
- Includes bitwise AND (‘&’), bitwise OR (‘|’), bitwise XOR (‘^’), bitwise negation (‘~’), shift left (‘<<’), shift right (‘>>’), and shift right unsigned (‘>>>’), which are mainly used for binary operations, such as:
int number1 = 5; // 二进制 0101 int number2 = 3; // 二进制 0011 int result = num1 & num2; // 结果是 0001,即 1
(5) Control flow
-
if-else 语句:
if (condition) { Executed when the condition is true } else { Executed when the condition is false }For example:
if (age >= 18) { System.out.println("成年"); } else { System.out.println("未成年"); } -
switch 语句:
Suitable for multi-branch situations, such as:switch (day) { case 1: System.out.println("星期一"); break; case 2: System.out.println("星期二"); break; Other situations default: System.out.println("其他"); break; } -
for 循环:
for (int i = 0; i < 10; i++) { Circulating bodies }For example, calculate the sum of 1 to 10:
int sum = 0; for (int i = 1; i <= 10; i++) { sum += i; } -
while 循环:
while (condition) { Circulating bodies }For example:
int i = 0; while (i < 10) { System.out.println(i); i++; } -
do-while 循环:
Perform the loop at least once, for example:int num; { System.out.println("请输入一个数:"); num = scanner.nextInt(); } while (num!= 0);
(6) Method
-
Methods are reusable blocks of code that define methods in the following general form:
returnType methodName(parameters) { Function body return returnValue; }For example:
public int add(int a, int b) { return a + b; }How to use:
int result = add(3, 5); -
Methods can be overloaded, i.e., there can be multiple methods with the same name, but with different parameter types or numbers, for example:
public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; }
2. Object-Oriented Programming (OOP)
(a) Classes and Objects
-
Definition of Class:
class MyClass { Member variables private int data; Constructor public MyClass() { data = 0; } Membership Methods public void setData(int value) { data = value; } public int getData() { return data; } } -
Creation and Use of Objects:
MyClass obj = new MyClass(); OBJ.setgiver(5); System.out.println(obj.getData());
(2) Encapsulation
- Use the ‘private’ keyword to hide the member variables of the class, which can be accessed and modified through the ‘public’ method to achieve encapsulation, for example:
class BankAccount { private double balance; public BankAccount() { balance = 0; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) { if (balance >= amount) { balance -= amount; } else { System.out.println("余额不足"); } } public double getBalance() { return balance; } }
(3) Inheritance
- One class can inherit from another, using the ‘extends’ keyword, for example:
class Animal { public void eat() { System.out.println("Animal is eating"); } } class Dog extends Animal { @Override public void eat() { System.out.println("Dog is eating"); } }
(4) Polymorphism
- Polymorphism means that when a parent class reference points to a child class object, and when a method that is overridden by the child class is called, the method of the child class is called, for example:
Animal animal = new Dog(); animal.eat(); // 调用 Dog 类的 eat 方法
(5) Abstract classes and interfaces
- Abstract Classes:
- Classes that contain abstract methods (only method signatures, no method bodies), using the ‘abstract’ keyword, for example:
abstract class Shape { abstract double area(); } - When a subclass inherits an abstract class, an abstract method must be implemented, for example:
class Circle extends Shape { private double radius; public Circle(double r) { radius = r; } @Override public double area() { return Math.PI * radius * radius; } }
- Classes that contain abstract methods (only method signatures, no method bodies), using the ‘abstract’ keyword, for example:
-Interface:
- Include only method signatures and constants, using the ‘interface’ keyword, for example:
interface Drawable { void draw(); } - The class implementation interface needs to implement all the methods in the interface, for example:
class Rectangle implements Drawable { @Override public void draw() { System.out.println("Drawing a rectangle"); } }
3. Exception handling
(1) Type of exception
-
Java 中的异常分为
Checked Exception(受检异常)和Unchecked Exception(非受检异常)。 -
Checked Exception必须在代码中显式处理,例如IOException,使用try-catch或throws关键字,例如:import java.io.FileReader; import java.io.IOException; public class ExceptionExample { public static void main(String[] args) { try { FileReader reader = new FileReader("file.txt"); Manipulating files reader.close(); } catch (IOException e) { b.printStackTrace(); } } } -
‘Unchecked Exception’ ‘NullPointerExhra’、'ArrayIndexOutOfBoundsEx!!! 等,例如:
public class UncheckedExceptionExample { public static void main(String[] args) { int[] arr = new int[5]; try { System.out.println(arr[10]); } catch (ArrayIndexOutOfBoundsException e) { b.printStackTrace(); } } }
(2) Custom exceptions
- You can customize the exception class, inheriting from either ‘Exception’ or ‘RuntimeException’, for example:
class MyException extends Exception { public MyException(String message) { super(message); } }
(三)finally 块
- The code in the ‘finally’ block executes with or without an exception, for example:
try { Code where exceptions can occur } catch (Exception e) { Handle exceptions } finally { Clean up the code }
Fourth, the Java Collection Framework
(a) Overview of the collection
The Java Collection Framework provides a set of classes and interfaces for storing and manipulating collections of objects, including ‘List’, ‘Set’, ‘Map’, etc.
(2) List
-
‘ArrayList’: a dynamic array that allows the storage of duplicate elements, such as
import java.util.ArrayList; import java.util.List; public class ArrayListExample { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Apple"); list.add("Banana"); list.add("Apple"); System.out.println(list.get(0)); } } -
‘LinkedList’: Implemented based on linked lists, suitable for frequent insertion and deletion of elements, such as:
import java.util.LinkedList; import java.util.List; public class LinkedListExample { public static void main(String[] args) { List<String> list = new LinkedList<>(); list.add("Cat"); list.add("Dog"); list.addFirst("Bird"); System.out.println(list.get(0)); } }
(3) Set
-
‘HashSet’: Duplicate elements are not allowed to be stored, and the elements are out of order, for example:
Import Java.u.s.hashset; import java.util.Set; public class HashSetExample { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("Red"); set.add("Green"); set.add("Red"); System.out.println(set.size()); } } -
‘TreeSet’: Elements are automatically sorted, for example:
import java.util.TreeSet; import java.util.Set; public class TreeSetExample { public static void main(String[] args) { Set<Integer> set = new TreeSet<>(); set.add(5); set.add(3); set.add(8); System.out.println(set.first()); } }
(4) Map
-
‘HashMap’: Stores key-value pairs, which are unique, for example:
Import java.hashmap; import java.util.Map; public class HashMapExample { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("Apple", 10); map.put("Banana", 20); System.out.println(map.get("Apple")); } } -
‘TreeMap’: keys are automatically sorted, for example:
import java.util.TreeMap; import java.util.Map; public class TreeMapExample { public static void main(String[] args) { Map<String, Integer> map = new TreeMap<>(); map.put("Orange", 15); map.put("Grape", 30); System.out.println(map.firstKey()); } }
5. Java input and output
(1) Standard input and output
-
使用 ‘System.out.println()’ 输出,例如:
System.out.println("Hello, World!"); -
Use the ‘Scanner’ class to make inputs, for example:
import java.util.Scanner; public class InputExample { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入一个数:"); int num = scanner.nextInt(); System.out.println("你输入的数是:" + num); scanner.close(); } }
(2) File input and output
- Use ‘FileInputStream’ and ‘FileOutputStream’ for file reads and writes, for example:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileIOExample { public static void main(String[] args) { try { FileOutputStream fos = new FileOutputStream("output.txt"); fos.write("Hello, File".getBytes()); fos.close(); FileInputStream fis = new FileInputStream("output.txt"); int content; while ((content = fis.read())!= -1) { System.out.print((char) content); } fis.close(); } catch (IOException e) { b.printStackTrace(); } } }
(iii) Character flow
- Use ‘FileReader’ and ‘FileWriter’ for character reading and writing, for example:
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class CharacterIOExample { public static void main(String[] args) { try { FileWriter fw = new FileWriter("character.txt"); fw.write("Hello, Character"); fw.close(); FileReader fr = new FileReader("character.txt"); int character; while ((character = fr.read())!= -1) { System.out.print((char) character); } fr.close(); } catch (IOException e) { b.printStackTrace(); } } }
(4) Buffer flow
- Use ‘BufferedReader’ and ‘BufferedWriter’ to improve read and write efficiency, for example:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class BufferedIOExample { public static void main(String[] args) { try { BufferedWriter bw = new BufferedWriter(new FileWriter("buffered.txt")); bw.write("Hello, Buffered"); bw.close(); BufferedReader br = new BufferedReader(new FileReader("buffered.txt")); String line; while ((line = br.readLine())!= null) { System.out.println(line); } br.close(); } catch (IOException e) { b.printStackTrace(); } } }
Sixth, Java multithreading
(1) Threading basics
-
A thread is an execution path in a program, and in Java it can be created by inheriting the ‘Thread’ class or implementing the ‘Runnable’ interface.
-
Inherit the ‘Thread’ class:
class MyThread extends Thread { @Override public void run() { System.out.println("Thread is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); } } -
Implement the ‘Runnable’ interface:
class MyRunnable implements Runnable { @Override public void run() { System.out.println("Runnable is running"); } } public class RunnableExample { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
(2) Thread synchronization
- Use the ‘synchronized’ keyword to synchronize threads to prevent multiple threads from accessing shared resources at the same time, for example:
class Counter { private int count = 0; public synchronized void increment() { count++; } }
(iii) Thread pool
- Use ‘ExecutorService’ to manage thread pools to improve performance, such as:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { executorService.execute(() -> { System.out.println(Thread.currentThread().getName()); }); } executorService.shutdown(); }
Here’s a continuation of the Java knowledge rollup:
7. What’s new in Java 8
(a) Lambda expressions
- Lambda expressions are an important feature introduced in Java 8 that allow functions to be used as arguments to methods, making code more concise.
- 基本语法:
(parameters) -> expression或(parameters) -> { statements; }。 - For example, implement the ‘Runnable’ interface using a lambda expression:
public class LambdaExample {
public static void main(String[] args) {
The traditional way
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello from traditional Runnable");
}
};
runnable1.run();
Lambda expressions
Runnable runnable2 = () -> System.out.println("Hello from Lambda Runnable");
runnable2.run();
}
}
- Lambda expressions can also receive arguments, such as:
import java.util.Arrays;
import java.util.List;
public class LambdaWithParameters {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry");
Use a lambda expression to iterate through the list
list.forEach((item) -> System.out.println(item));
}
}
(2) Functional interface
- A functional interface is an interface that contains only one abstract method that can be declared using the ‘@FunctionalInterface’ annotation.
- For example, a custom functional API:
@FunctionalInterface
interface MyFunction {
int apply(int a, int b);
}
- Use Lambda expressions to call functional interfaces:
public class FunctionalInterfaceExample {
public static void main(String[] args) {
MyFunction add = (a, b) -> a + b;
int result = add.apply(3, 5);
System.out.println(result);
}
}
- Java 8 has a number of built-in functional interfaces, such as ‘Consumer’, ‘Supplier’, ‘Function’, ‘Predicate’, etc., such as printing elements with ‘Consumer’:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class BuiltInFunctionalInterface {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry");
Consumer<String> consumer = (item) -> System.out.println(item);
list.forEach(consumer);
}
}
(三)Stream API
- The Stream API provides a new way to manipulate collections, supporting parallel processing.
- Create a flow:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Create a flow from a collection
Stream<Integer> stream = numbers.stream();
Create a stream from an array
int[] array = {1, 2, 3, 4, 5};
Stream<int[]> arrayStream = Stream.of(array);
}
}
- Intermediate Operations:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamIntermediateOperations {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Filter elements
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
Mapping elements
List<String> stringNumbers = numbers.stream()
.map(n -> n.toString())
.collect(Collectors.toList());
}
}
- Terminal Operation:
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamTerminalOperations {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
sue for peace
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
Find the element
Optional<Integer> firstEven = numbers.stream()
.filter(n -> n % 2 == 0)
.findFirst();
}
}
(iv) Date and Time API
- Java 8 introduces a new date and time API (the ‘java.time’ package).
- ‘LocalDate’ for the date:
import java.time.LocalDate;
public class LocalDateExample {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println(today);
LocalDate specificDate = LocalDate.of(2025, 1, 22);
System.out.println(specificDate);
}
}
- ‘LocalTime’ indicates the time:
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println(now);
LocalTime specificTime = LocalTime.of(12, 30, 45);
System.out.println(specificTime);
}
}
- ‘LocalDateTime’ for date and time:
import java.time.LocalDateTime;
public class LocalDateTimeExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
LocalDateTime specificDateTime = LocalDateTime.of(2025, 1, 22, 12, 30, 45);
System.out.println(specificDateTime);
}
}
VIII. Java Reflection
(1) Reflection Basics
- Reflection allows a program to inspect information such as classes, interfaces, methods, fields, etc., at runtime, and dynamically call methods or access fields.
- Get class information:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class MyClass {
private int value;
public void display() {
System.out.println("Value: " + value);
}
}
public class ReflectionExample {
public static void main(String[] args) {
try {
Class<?> clazz = MyClass.class;
A method to get a class
Method method = clazz.getMethod("display");
Get the fields of the class
Field field = clazz.getDeclaredField("value");
} catch (NoSuchMethodException | NoSuchFieldException e) {
b.printStackTrace();
}
}
}
(2) Dynamically create objects and call methods
- Create an object using reflections:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, " + name);
}
}
public class DynamicObjectCreation {
public static void main(String[] args) {
try {
Class<?> clazz = Person.class;
Get the constructor
Constructor<?> constructor = clazz.getConstructor(String.class);
Create an object
Object person = constructor.newInstance("John");
Call the method
Method method = clazz.getMethod("sayHello");
method.invoke(person);
} catch (Exception e) {
b.printStackTrace();
}
}
}
(3) Modify the value of the field
- Use reflection to modify the value of a private field:
import java.lang.reflect.Field;
class Employee {
private double salary;
public Employee(double salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
}
public class FieldModification {
public static void main(String[] args) {
try {
Employee employee = new Employee(50000);
Class<?> clazz = Employee.class;
Field field = clazz.getDeclaredField("salary");
field.setAccessible(true);
Modify the field value
field.set(employee, 60000);
System.out.println(employee.getSalary());
} catch (Exception e) {
b.printStackTrace();
}
}
}
IX. Java Annotations
(1) Annotation Basis
- Annotations are metadata that add extra information to program elements (classes, methods, fields, and so on).
- Custom annotations:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
- Use annotations:
@MyAnnotation(value = "This is a class annotation")
class AnnotatedClass {
}
(2) Meta annotation
- Meta-annotations are used to modify annotations such as ‘@Target’, ‘@Retention’, ‘@Documented’, ‘@Inherited’, and so on.
- ‘@Target’ defines where the annotation is used (class, method, field, etc.).
- ‘@Retention’ defines the lifecycle of the annotation (source code, class file, runtime).
(iii) Use the annotation processor
- You can use the annotation processor to process annotations, for example:
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyMethodAnnotation {
String value();
}
class MyClassWithAnnotation {
@MyMethodAnnotation("This is a method annotation")
public void myMethod() {
}
}
public class AnnotationProcessor {
public static void main(String[] args) {
try {
Class<?> clazz = MyClassWithAnnotation.class;
Method method = clazz.getMethod("myMethod");
Annotation annotation = method.getAnnotation(MyMethodAnnotation.class);
if (annotation instanceof MyMethodAnnotation) {
MyMethodAnnotation myMethodAnnotation = (MyMethodAnnotation) annotation;
System.out.println(myMethodAnnotation.value());
}
} catch (NoSuchMethodException e) {
b.printStackTrace();
}
}
}
10. Java Network Programming
(1) Socket programming
- TCP programming using ‘Socket’ and ‘ServerSocket’.
- Server-side:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("Server is listening on port 8080");
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
Process input and output streams
serverSocket.close();
} catch (IOException e) {
b.printStackTrace();
}
}
}
-Client:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class SimpleClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 8080);
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
Process input and output streams
socket.close();
} catch (IOException e) {
b.printStackTrace();
}
}
}
(2) UDP programming
- UDP programming using ‘DatagramSocket’ and ‘DatagramPacket’.
- Server-side:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpServer {
public static void main(String[] args) {
try {
DatagramSocket socket = new DatagramSocket(9090);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
Process packets
socket.close();
} catch (IOException e) {
b.printStackTrace();
}
}
}
-Client:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpClient {
public static void main(String[] args) {
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, 9090);
socket.send(packet);
socket.close();
} catch (IOException e) {
b.printStackTrace();
}
}
}
11. Java Database Programming
(1) JDBC Fundamentals
- JDBC is the standard interface for Java to access the database, and the database is connected through the ‘DriverManager’.
-Example:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcExample {
public static void main(String[] args) {
try {
Load the driver
Class.forName("com.mysql.cj.jdbc.Driver");
Establish a connection
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
Statement statement = connection.createStatement();
Execute the query
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
}
Turn off the resource
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
b.printStackTrace();
}
}
}
(二)PreparedStatement
- Prevent SQL injection,Use ‘PreparedStatement’。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class PreparedStatementExample {
public static void main(String[] args) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
String sql = "SELECT * FROM users WHERE id =?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
}
resultSet.close();
preparedStatement.close();
connection.close();
} catch (Exception e) {
b.printStackTrace();
}
}
}
(3) Transaction management
- Use ‘setAutoCommit’ and ‘commit’ to manage transactions.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TransactionExample {
public static void main(String[] args) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
connection.setAutoCommit(false);
PreparedStatement statement1 = connection.prepareStatement("INSERT INTO users (username) VALUES ('user1')");
PreparedStatement statement2 = connection.prepareStatement("INSERT INTO users (username) VALUES ('user2')");
statement1.executeUpdate();
statement2.executeUpdate();
connection.commit();
connection.close();
} catch (Exception e) {
b.printStackTrace();
}
}
}
12. Java Graphical User Interface (GUI)
(1) Swing Basics
- Swing is a GUI toolkit for Java that provides various components such as ‘JFrame’, ‘JButton’, ‘JTextField’, etc.
- Create a simple window:
import javax.swing.JFrame;
public class SimpleSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("Simple Swing");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
(b) Layout Manager
- Use the layout manager to organize components such as ‘FlowLayout’, ‘BorderLayout’, ‘GridLayout’, etc.
- Use ‘FlowLayout’:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.FlowLayout;
public class FlowLayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("FlowLayout Example");
JPanel panel = new JPanel(new FlowLayout());
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 2");
panel.add(button1);
panel.add(button2);
frame.add(panel);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
(3) Event handling
- Use listeners to handle events, such as ‘ActionListener’ for button click events.
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class EventHandling {
public static void main(String[] args) {
JFrame frame = new JFrame("Event Handling");
JPanel panel = new JPanel(new FlowLayout());
JButton button = new JButton("Click Me");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Button Clicked");
}
});
panel.add(button);
frame.add(panel);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
XIII. Java Concurrency Tools
(一)CountDownLatch
- ‘CountDownLatch’ is used for inter-thread waiting, waiting for multiple threads to complete the task.
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is running");
latch.countDown();
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
try {
latch.await();
System.out.println("All tasks completed");
} catch (InterruptedException e) {
b.printStackTrace();
}
}
}
(二)CyclicBarrier
- ‘CyclicBarrier’ is used for multiple threads waiting for each other at a barrier point.
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached the barrier"));
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " is running");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
b.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
(三)Semaphore
- ‘Semaphore’ is used to control the number of concurrent access resources.
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
Runnable task = () -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is accessing resource");
Thread.sleep(1000);
semaphore.release();
} catch (InterruptedException e) {
b.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
XIV. Java Unit Tests
(a) JUnit framework
- JUnit is the most commonly used unit testing framework in Java and uses the ‘@Test’ annotation testing method.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class JUnitExample {
@Test
public void testAddition() {
int result = 2 + 3;
assertEquals(5, result);
}
}
Here’s the next part of the Java knowledge rollup:
XV. Java Serialization
(1) Serialization Basics
- Serialization is the conversion of an object into a stream of bytes for storage or transmission, while deserialization is the conversion of a stream of bytes back into an object.
- Classes that implement the ‘Serializable’ interface can be serialized:
import java.io.*;
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"In name='" + in name + '\''+
", age=" + age +
'}';
}
}
public class SerializationExample {
public static void main(String[] args) {
Person person = new Person("Alice", 25);
try {
serialization
FileOutputStream fileOut = new FileOutputStream("person.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in person.ser");
Deserialization
FileInputStream fileIn = new FileInputStream("person.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
Person deserializedPerson = (Person) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Person: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
b.printStackTrace();
}
}
}
(2) Custom serialization
- The serialization and deserialization process can be customized via the ‘writeObject’ and ‘readObject’ methods:
import java.io.*;
class CustomSerializablePerson implements Serializable {
private String name;
private transient int age; // transient 关键字表示该字段不参与序列化
public CustomSerializablePerson(String name, int age) {
this.name = name;
this.age = age;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
Custom serialization logic
out.writeInt(age + 1); // 对 age 进行特殊处理
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Custom deserialization logic
age = in.readInt() - 1; // 恢复 age 的值
}
@Override
public String toString() {
return "CustomSerializablePerson{" +
"In name='" + in name + '\''+
", age=" + age +
'}';
}
}
public class CustomSerializationExample {
public static void main(String[] args) {
CustomSerializablePerson person = new CustomSerializablePerson("Bob", 30);
try {
serialization
FileOutputStream fileOut = new FileOutputStream("customPerson.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileIn.close();
System.out.println("Serialized data is saved in customPerson.ser");
Deserialization
FileInputStream fileIn = new FileInputStream("customPerson.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
CustomSerializablePerson deserializedPerson = (CustomSerializablePerson) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Person: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
b.printStackTrace();
}
}
}
(3) Serialized version number
- To ensure compatibility between serialization and deserialization, use the ‘serialVersionUID’ field:
import java.io.*;
class VersionedPerson implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public VersionedPerson(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "VersionedPerson{" +
"In name='" + in name + '\''+
", age=" + age +
'}';
}
}
public class SerializationVersionExample {
public static void main(String[] args) {
VersionedPerson person = new VersionedPerson("Charlie", 35);
try {
serialization
FileOutputStream fileOut = new FileOutputStream("versionedPerson.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(person);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in versionedPerson.ser");
Deserialization
FileInputStream fileIn = new FileInputStream("versionedPerson.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
VersionedPerson deserializedPerson = (VersionedPerson) in.readObject();
in.close();
fileIn.close();
System.out.println("Deserialized Person: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
b.printStackTrace();
}
}
}
XVI. Java memory management
(a) Java memory structure
- Java 内存分为堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(Program Counter Register)和本地方法栈(Native Method Stack)。
- Heap: Stores object instances, managed by the garbage collector.
- Stack: Stores local variables and method call information.
- Method area: stores class information, static variables, constants, etc.
(2) Garbage Collection (GC)
- The garbage collector in Java automatically collects objects that are no longer in use, and common garbage collection algorithms include mark-clean, copy, mark-and-clean, etc.
- Garbage collection can be suggested by the JVM via ‘System.gc()’, but it is not guaranteed to be executed immediately:
public class GarbageCollectionExample {
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
new Object();
}
System.gc();
}
}
(3) Memory leak
- A memory leak is when an object that is no longer used in the program still occupies memory, which may be caused by objects not being released correctly, static collections holding object references, etc.
- Some best practices to avoid memory leaks:
- Release resources in a timely manner, such as shutting down files, database connections, and network connections.
- Avoid using static collections to store a large number of objects.
- Pay attention to the lifecycle of objects and avoid long-lived objects holding references to short-lived objects.
XVII. Java Performance Optimization
(1) Code optimization
- Reduce object creation: Reuse objects as much as possible and avoid creating new objects frequently, such as using ‘StringBuilder’ instead of ‘String’ splicing:
public class StringConcatenation {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
}
}
-
Use efficient data structures: Choose the right data structure for your use case, such as ‘HashSet’ is more efficient than ‘ArrayList’ when looking for elements.
-
Avoid over-syncing: Use the ‘synchronized’ keyword only when necessary to avoid performance overhead.
(2) JVM optimization
- Resize heap: Adjust the ‘-xmx’ and ‘-xms’ parameters based on your application’s memory needs:
java -Xmx512m -Xms256m MyApp
- Use profiling tools: Tools such as VisualVM, JProfiler, etc., analyze program performance and identify performance bottlenecks.
(3) Multi-threading optimization
- Wise use of thread pools: Avoid creating and destroying threads frequently and use ExecutorService to manage thread pools:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolOptimization {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executorService.execute(() -> {
Task logic
});
}
executorService.shutdown();
}
}
- Avoid deadlocks: Arrange the order in which locks are acquired, and use ‘tryLock’ to avoid deadlocks.
XVIII. Java Design Patterns
(a) Singleton pattern
- Make sure that there is only one instance of a class, providing a global access point.
- Hungry Singleton:
class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
- Slobble singleton:
class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
(2) Factory mode
- The factory pattern is used to create objects, encapsulating the object creation logic in the factory class.
- Simple Factory Mode:
interface Product {
void use();
}
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductA");
}
}
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductB");
}
}
class SimpleFactory {
public static Product createProduct(String type) {
if (type.equals("A")) {
return new ConcreteProductA();
} else if (type.equals("B")) {
return new ConcreteProductB();
}
return null;
}
}
public class FactoryPatternExample {
public static void main(String[] args) {
Product productA = SimpleFactory.createProduct("A");
productA.use();
}
}
(3) Observer mode
- Notify other objects when the state of one object changes.
- Observer Interface:
interface Observer {
void update(String message);
}
class ConcreteObserver implements Observer {
@Override
public void update(String message) {
System.out.println("Received message: " + message);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
public class ObserverPatternExample {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers("Hello, Observers!");
}
}
(4) Proxy mode
- Provide proxies for other objects to control access to that object.
- Static Proxies:
interface Image {
void display();
}
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading " + fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display();
image.display(); There is no need to reload the second time it is displayed
}
}
19. Java Security
(a) Security Manager
- Java Security Manager can control the permissions of Java programs, such as restricting file access, network access, etc.
import java.io.File;
import java.io.FileReader;
import java.security.Permission;
public class SecurityManagerExample {
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission perm) {
if (perm instanceof java.io.FilePermission) {
Customize permission check logic
System.out.println("Checking permission: " + perm);
}
}
});
try {
FileReader reader = new FileReader(new File("test.txt"));
} catch (Exception e) {
b.printStackTrace();
}
}
}
(2) Encryption and decryption
- Use Java Encryption Extensions (JCE) for encryption and decryption operations.
- Symmetric Encryption (AES):
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
public class SymmetricEncryption {
public static void main(String[] args) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] input = "Hello, Encryption".getBytes(StandardCharsets.UTF_8);
byte[] encryptedBytes = cipher.doFinal(input);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
System.out.println(new String(decryptedBytes, StandardCharsets.UTF_8));
}
}
- Asymmetric Encryption (RSA):
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;
public class AsymmetricEncryption {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] input = "Hello, RSA".getBytes();
byte[] encryptedBytes = cipher.doFinal(input);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
System.out.println(new String(decryptedBytes));
}
}
(3) Digital signatures
- Digital signatures are used to verify the origin and integrity of a message.
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
public class DigitalSignature {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
Signature signature = Signature.getInstance("SHA256withDSA");
signature.initSign(privateKey);
String message = "Hello, Digital Signature";
signature.update(message.getBytes());
byte[] sign = signature.sign();
signature.initVerify(publicKey);
signature.update(message.getBytes());
boolean verified = signature.verify(sign);
System.out.println("Signature verified: " + verified);
}
}
XXIS, Java Logs
(a) Log framework
- Java 自带的日志框架 ‘Java.Util.logging’ 或常用的第三方日志框架如 log4J、logback.
- 使用 ‘java.util.logging’:
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingExample {
private static final Logger logger = Logger.getLogger(LoggingExample.class.getName());
public static void main(String[] args) {
logger.log(Level.INFO, "This is an info message");
logger.log(Level.WARNING, "This is a warning message");
}
}
(二)Log4j 日志框架
- Configure Log4j:
<! DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<root>
<priority value="info" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
- Logging with Log4j:
import org.apache.log4j.Logger;
public class Log4jExample {
private static final Logger logger = Logger.getLogger(Log4jExample.class);
public static void main(String[] args) {
logger.info("This is an info message from Log4j");
logger.warn("This is a warning message from Log4j");
}
}
(iii) Log level and configuration
- Song of ‘TRACE’、‘DEBUG’、‘INFO’、‘WARN’、‘ERROR’、‘FATAL’。
- You can configure the log level and log output location, such as files and consoles, as needed.
XXI. Java Module System
(1) Module Basics
- Java 9 introduces a module system, using ‘module-info.java’ files to define modules.
- Example module definition:
module com.example.myModule {
exports com.example.myPackage;
}
(2) Module dependencies
- Modules can depend on other modules, declaring in ‘module-info.java’:
module com.example.myModule {
requires java.sql;
exports com.example.myPackage;
}
(3) Services
- Modules can provide and use services, using the ‘provides’ and ‘uses’ keywords:
module com.example.serviceProvider {
provides com.example.MyService with com.example.MyServiceImpl;
}
module com.example.serviceConsumer {
uses com.example.MyService;
}
XXII. Java microservices development
(一)Spring Boot
- Spring Boot is a framework for rapid development of microservices, simplifying the configuration of the Spring Framework.
- Create a simple Spring Boot application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class SpringBootExample {
public static void main(String[] args) {
SpringApplication.run(SpringBootExample.class, args);
}
}
@RestController
class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
(二)Spring Cloud
- Spring Cloud provides solutions for microservices, including service discovery, configuration management, circuit breakers, and more.
- Service Discovery (Eureka):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerExample {
public static void main(String[] args) {
SpringApplication.run(EurekaServerExample.class, args);
}
}
(3) Docker and Java microservices
- Containerize Java microservices using Docker:
FROM openjdk:11
COPY target/my-service.jar /app.jar
CMD["java","-jar","/app.jar"]
(4) Kubernetes deployment
- Deploy and manage Java microservice clusters with Kubernetes:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-service
ports:
- protocol: TCP
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-service-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-service
template:
metadata:
labels:
app: my-service
spec:
containers:
- name: my-service
image: my-service-image:latest
ports:
- containerPort: 8080
## XXIII. Functional Programming in Java
### (a) Functions as first-class citizens
- In Java 8 and later, functions can be stored as arguments to methods, return values, and variables. This is one of the important characteristics of functional programming.
```java
import java.util.function.Function;
public class FunctionAsFirstClassCitizen {
public static void main(String[] args) {
Function<Integer, Integer> addOne = (x) -> x + 1;
int result = applyFunction(5, addOne);
System.out.println(result);
}
public static int applyFunction(int input, Function<Integer, Integer> function) {
return function.apply(input);
}
}
(b) Method references
- Method references provide a concise way to call existing methods. It can be used as an alternative to lambda expressions to make the code more concise.
- Static method references:
import java.util.Arrays;
import java.util.List;
class StringUtils {
public static int stringLength(String str) {
return str.length();
}
}
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry");
Use static method references
strings.stream()
.map(StringUtils::stringLength)
.forEach(System.out::println);
}
}
- Example method references:
import java.util.Arrays;
import java.util.List;
class Printer {
public void print(String str) {
System.out.println(str);
}
}
public class InstanceMethodReference {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry");
Printer printer = new Printer();
Use instance method references
strings.forEach(printer::print);
}
}
(3) Combinatorial functions
- Multiple functions can be combined into a new function, which is common in functional programming.
import java.util.function.Function;
public class FunctionComposition {
public static void main(String[] args) {
Function<Integer, Integer> addOne = (x) -> x + 1;
Function<Integer, Integer> multiplyByTwo = (x) -> x * 2;
Combination functions
Function<Integer, Integer> addOneAndMultiplyByTwo = multiplyByTwo.compose(addOne);
int result = addOneAndMultiplyByTwo.apply(3);
System.out.println(result);
}
}
(4) Higher-order functions
- A higher-order function is a function that accepts one or more functions as arguments, or returns a function.
import java.util.function.Function;
public class HigherOrderFunction {
public static Function<Integer, Function<Integer, Integer>> createAdder() {
return (x) -> (y) -> x + y;
}
public static void main(String[] args) {
Function<Integer, Function<Integer, Integer>> adder = createAdder();
Function<Integer, Integer> addFive = adder.apply(5);
int result = addFive.apply(3);
System.out.println(result);
}
}
XXIV. Generics in Java
(1) Generic foundations
- Generics allow us to create classes and methods that can handle multiple types, improving code reusability and type safety.
- Generic classes:
class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
public class GenericClassExample {
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get());
}
}
(2) Generic methods
- You can use generics on your methods without relying on the generics of the class.
class GenericMethodClass {
public static <T> T getFirst(List<T> list) {
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
}
public class GenericMethodExample {
public static void main(String[] args) {
List<String> strings = Arrays.asList("apple", "banana", "cherry");
String first = GenericMethodClass.getFirst(strings);
System.out.println(first);
}
}
(3) Wildcard
- The wildcard ‘?’ can be used to represent an unknown type, which can make the code more flexible in some cases.
- Upper Bound Wildcard:
import java.util.ArrayList;
import java.util.List;
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class UpperBoundedWildcard {
public static void printAnimals(List<? extends Animal> animals) {
for (Animal animal : animals) {
System.out.println(animal);
}
}
public static void main(String[] args) {
List<Dog> dogs = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
printAnimals(dogs);
printAnimals(cats);
}
}
- Nether wildcards:
import java.util.ArrayList;
import java.util.List;
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
public class LowerBoundedWildcard {
public static void addAnimal(List<? super Dog> animals) {
animals.add(new Dog());
}
public static void main(String[] args) {
List<Animal> animals = new ArrayList<>();
List<Dog> dogs = new ArrayList<>();
addAnimal(animals);
addAnimal(dogs);
}
}
(iv) Type erasure
- Generic information is erased after compilation and is not retained at runtime.
class GenericClass<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
public class TypeErasureExample {
public static void main(String[] args) {
GenericClass<String> stringClass = new GenericClass<>();
Class<?> clazz = stringClass.getClass();
After the type is erased, T is replaced with an Object or boundary type
System.out.println(clazz.getDeclaredFields()[0].getType());
}
}
XXV. Advanced features of concurrency in Java
(一)Fork/Join 框架
- The Fork/Join framework is used to execute tasks in parallel and is suitable for problems that can be broken down into subtasks.
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;
class FibonacciTask extends RecursiveTask<Integer> {
final int n;
FibonacciTask(int n) {
this.n = n;
}
@Override
protected Integer compute() {
if (n <= 1)
return n;
FibonacciTask f1 = new FibonacciTask(n - 1);
f1.fork();
FibonacciTask f2 = new FibonacciTask(n - 2);
return f2.compute() + f1.join();
}
}
public class ForkJoinExample {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
FibonacciTask task = new FibonacciTask(10);
int result = forkJoinPool.invoke(task);
System.out.println(result);
}
}
(二)CompletableFuture
- ‘CompletableFuture’ provides a powerful way to program asynchronously to handle the results and exceptions of asynchronous operations.
- Perform tasks asynchronously:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 2 + 3);
int result = future.get();
System.out.println(result);
}
}
- Combine multiple asynchronous tasks:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureCombination {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 3);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (a, b) -> a + b);
int result = combinedFuture.get();
System.out.println(result);
}
}
(iii) Parallel streaming
- Parallel streaming makes it easy to parallelize stream operations.
import java.util.Arrays;
public class ParallelStreamExample {
public static void main(String[] args) {
int sum = Arrays.asList(1, 2, 3, 4, 5)
.parallelStream()
.mapToInt(i -> i)
.sum();
System.out.println(sum);
}
}
XXVI. Code Quality and Best Practices in Java
(1) Code specification
- Follow Java coding conventions such as naming conventions, code structure, annotation conventions, etc.
- Variable naming: Use camel nomenclature, e.g. ‘userName’.
- Method naming: Start with a verb, such as ‘getUserById’.
- Class naming: Use a noun with the first letter capitalized, e.g. ‘UserService’.
(2) Code review
- Conduct regular code reviews to check the quality, readability, maintainability, and performance of the code.
- Check that the code follows the coding guidelines.
- Check for potential bugs and logic errors.
(3) Unit testing best practices
- Test coverage: Try to keep test coverage as high as possible, using a tool such as JaCoCo to check test coverage.
- Test case independence: Each test case should run independently and not depend on other test cases.
- Test case maintainability: Test cases should be easy to maintain, and easy to update when the code is modified.
(4) Continuous Integration and Continuous Deployment (CI/CD)
- 使用 CI/CD 工具(如 Jenkins、GitLab CI、GitHub Actions)自动化构建、测试和部署流程。
- Configure CI processes to automate builds and tests after code is committed.
XXVII. Resource Management in Java
(一)try-with-resources
- The ‘try-with-resources’ statement ensures that resources (such as files, network connections, and database connections) are automatically shut down after use to avoid resource leakage.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResources {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine())!= null) {
System.out.println(line);
}
} catch (IOException e) {
b.printStackTrace();
}
}
}
(b) ‘AutoCloseable’ interface
- 实现
AutoCloseable接口的类可以在try-with-resources中使用。
import java.io.Closeable;
import java.io.IOException;
class CustomResource implements AutoCloseable {
@Override
public void close() throws IOException {
System.out.println("Resource closed");
}
}
public class AutoCloseableExample {
public static void main(String[] args) {
try (CustomResource resource = new CustomResource()) {
Use resources
} catch (IOException e) {
b.printStackTrace();
}
}
}
(3) Resource pools
- For expensive resources (such as database connections and thread pools), use resource pool management to avoid frequent creation and destruction of resources.
- Database connection pooling:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class ConnectionPoolExample {
public static void main(String[] args) throws SQLException {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
Connection connection = dataSource.getConnection();
Use connections
connection.close();
}
}
XXVIII. Dynamic Agents in Java
(1) Dynamic proxy basis
- Dynamic proxies allow proxy classes to be created at runtime, without the need to define proxy classes in advance.
- Using the java.lang.reflect.Proxy class:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Service {
void doSomething();
}
class ServiceImpl implements Service {
@Override
public void doSomething() {
System.out.println("Doing something");
}
}
class ServiceInvocationHandler implements InvocationHandler {
private Object target;
public ServiceInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method invocation");
Object result = method.invoke(target, args);
System.out.println("After method invocation");
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
Service service = new ServiceImpl();
Service proxy = (Service) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new ServiceInvocationHandler(service)
);
proxy.doSomething();
}
}
(2) Application scenarios
- Dynamic agents are commonly used for AOP (Section-Oriented Programming) such as logging, transaction management, performance monitoring, and more.
XXIX. Scripting Engine in Java
(1) Scripting Engine Basics
- Java provides a scripting engine that can run scripting languages (e.g. JavaScript, Groovy).
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineExample {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
Object result = engine.eval("2 + 3");
System.out.println(result);
}
}
(b) Interact with Java code
- The scripting engine can interact with Java code, invoke Java methods, and access Java objects.
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineInteraction {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
Bindings bindings = engine.getBindings(javax.script.ScriptContext.ENGINE_SCOPE);
bindings.put("greeting", "Hello");
engine.eval("print(greeting + ', World!')");
}
}
30 Internationalization in Java (i18n)
(1) Resource bundles
- Use resource bundles to store text information in different languages.
- 创建
Messages.properties文件:
greeting=Hello
- Create a ‘Messages_fr.properties’ file (in French):
greeting=Bonjour
- Using Resource Bundles:
import java.util.Locale;
import java.util.ResourceBundle;
public class InternationalizationExample {
public static void main(String[] args) {
Locale locale = new Locale("fr");
ResourceBundle bundle = ResourceBundle.getBundle("Messages", locale);
System.out.println(bundle.getString("greeting"));
}
}
(b) Format the message
- Format the message with ‘MessageFormat’:
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
public class MessageFormatting {
public static void main(String[] args) {
Locale locale = new Locale("en");
ResourceBundle bundle = ResourceBundle.getBundle("Messages", locale);
String message = bundle.getString("welcome");
String formattedMessage = MessageFormat.format(message, "John");
System.out.println(formattedMessage);
}
}
The above summary of Java knowledge covers many aspects of Java programming, from basic data types, object-oriented programming to advanced concurrency, microservice development, functional programming, etc., hoping to help you fully master Java programming skills. In the learning process, you should practice more, continuously improve your programming level in combination with actual projects, and continue to pay attention to the new features and development trends of the Java language, so as to better use Java to develop high-quality software systems.
Please note that this document is just a small part of what you need to know about Java, as the Java language is constantly evolving, with new features and frameworks emerging that need to be learned and explored.
You can delve into each section according to your own learning pace and interests, read official documentation, reference books, and participate in open source projects, which will help you gain a deeper understanding and mastery of Java programming. If you run into problems during learning or development, you can use debugging tools, search engines, and community forums like Stack Overflow to resolve the issue. I wish you more progress on your path to Java programming

1368

被折叠的 条评论
为什么被折叠?



