Java 异常机制与常用类详解

 更新时间:2026年06月08日 10:06:29   作者:数开小羊  
本文介绍了Java异常处理机制,包括Error、RuntimeException和CheckedException的区分,以及try-catch-finally结构的应用,同时包装类、时间处理、数组、字符串等常用类的使用方法和特性,强调理解JDK源码的重要性,感兴趣的朋友一起看看吧

本章主要涵盖 Java 异常处理的完整机制,以及日常开发中最常用的类:Object、包装类、时间处理、数组、字符串、Math、File、枚举。感谢大家观看

第一部分:异常机制(Exception Handling)

1. 异常的概念与必要性

异常(Exception)是指程序在运行时发生的非正常情况,如除零、数组越界、文件找不到、网络中断等。如果没有异常处理,程序会直接崩溃。异常机制让程序在遇到问题时能够:

  • 捕获 异常并做出合理响应(如提示用户、记录日志)
  • 清理 资源(关闭文件、数据库连接)
  • 平稳退出 或尝试其他路径

2. 异常的层次结构

Java 中所有异常都继承自 java.lang.Throwable 类。

Throwable
├── Error               // 严重错误,程序无法处理
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── ...
└── Exception           // 需要处理的异常
    ├── RuntimeException // 运行时异常(非受检异常)
    │   ├── NullPointerException
    │   ├── ArithmeticException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── ClassCastException
    │   ├── IllegalArgumentException
    │   └── ...
    └── 其他 Exception    // 受检异常(Checked Exception)
        ├── IOException
        ├── SQLException
        ├── ParseException
        └── ...

关键区别

  • Error:JVM 内部错误、资源耗尽等,应用程序无法恢复,通常不处理(例如 OutOfMemoryError 你 catch 了也救不回来)。
  • RuntimeException:编译器不强制处理,通常由编程错误引起(如空指针、除数零)。应当通过改进代码逻辑避免,而不是用 try-catch 掩盖。
  • Checked Exception:编译器强制要求处理(要么 try-catch,要么 throws),代表外部不可控因素(文件不存在、网络故障)。

3. 异常的产生与传播

public class Demo {
    public static void main(String[] args) {
        method1();
    }
    static void method1() {
        method2();
    }
    static void method2() {
        int a = 10 / 0;   // 这里产生 ArithmeticException
    }
}

过程

  1. method2 执行到 10/0 时,JVM 检测到除零错误,创建一个 ArithmeticException 对象。
  2. 当前方法没有 catch 该异常,异常对象被抛给调用者 method1
  3. method1 也没有处理,继续抛给 main
  4. main 也没有处理,最终抛给 JVM,JVM 打印异常栈并终止程序。

4. 异常处理方式

方式一:try-catch-finally

try {
    // 可能抛出异常的代码块
} catch (SomeException e) {
    // 处理该异常
} catch (AnotherException e) {
    // 可以有多个 catch
} finally {
    // 无论是否发生异常都会执行(除了 System.exit())
}

详细规则

  • try 块:一旦发生异常,后面的代码立即停止,跳转到对应的 catch。
  • catch 块:可以有多个,但最多只有一个会被执行。顺序必须从子类到父类(否则子类永远没机会执行,编译错误)。
  • finally 块:总是执行,适合释放资源(关闭文件、socket、数据库连接)。唯一不执行的情况:在 try 或 catch 中调用了 System.exit()
  • try 可以没有 catch,但必须有 finally(即 try-finally 结构,用于保证资源释放,但异常会向上抛)。
// try-finally 示例
InputStream is = null;
try {
    is = new FileInputStream("test.txt");
    // 读取操作
} finally {
    if (is != null) is.close();  // 确保关闭
}
// 如果发生异常,finally 执行后异常继续向上抛

方式二:throws 声明抛出

在方法签名上声明 throws,表示本方法不处理异常,交给调用者处理。

public static void readFile() throws IOException {
    FileInputStream fis = new FileInputStream("test.txt");
    // ...
}
// 调用者必须处理
public static void main(String[] args) {
    try {
        readFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意:重写方法时,子类方法抛出的异常不能比父类方法抛出的异常更宽泛(即不能抛出父类未声明的受检异常)。

throw 关键字(手动抛出)

可以在代码中主动抛出异常对象。

if (age < 0 || age > 150) {
    throw new IllegalArgumentException("年龄必须在0~150之间");
}

5. finally 与 return 的纠缠(经典面试题)

public static int test() {
    int x = 1;
    try {
        return x;   // ① 暂存返回值 1
    } finally {
        x = 2;      // ② 修改局部变量
    }
}
// 结果返回 1,而不是 2

解释

  • return x 不会立即返回,而是先计算表达式值(1)并暂存。
  • 执行 finally 块。
  • 最后返回暂存的值(1)。

特殊情况:如果 finally 中也含有 return,则会覆盖暂存值。

public static int test() {
    try {
        return 1;
    } finally {
        return 2;   // 会覆盖
    }
}
// 返回 2

总结:避免在 finally 中使用 return,否则会吞掉 trycatch 中的异常。

6. try-with-resources(JDK7+)

用于自动关闭实现了 AutoCloseable 接口的资源(如流、数据库连接)。

try (FileInputStream fis = new FileInputStream("test.txt");
     BufferedInputStream bis = new BufferedInputStream(fis)) {
    // 使用资源
} catch (IOException e) {
    e.printStackTrace();
}
// 无需显式 close,自动调用

等价于 try-finally 写法,更简洁安全。

7. 异常链(Exception Chaining)

在捕获一个异常后,抛出另一个异常,同时保留原始异常信息。

try {
    // 底层操作
} catch (SQLException e) {
    throw new ServiceException("业务异常", e);  // 第二个参数是 cause
}

可通过 e.getCause() 获取原始异常。

8. 自定义异常

何时自定义:当 JDK 内置异常不足以表达业务语义时(如 InsufficientBalanceExceptionUserNotFoundException)。

步骤

// 受检异常
public class MyCheckedException extends Exception {
    public MyCheckedException() {}
    public MyCheckedException(String message) {
        super(message);
    }
    public MyCheckedException(String message, Throwable cause) {
        super(message, cause);
    }
}
// 非受检异常(常用)
public class MyRuntimeException extends RuntimeException {
    public MyRuntimeException(String message) {
        super(message);
    }
}

建议

  • 如果是业务逻辑错误,通常继承 RuntimeException,避免强迫调用者处理。
  • 如果是外部因素可恢复的(如重试),可以继承 Exception

9. 常见运行时异常及避免方法

异常常见原因避免方法
NullPointerException调用 null 对象的方法/属性调用前判空,或用 Optional
ArrayIndexOutOfBoundsException访问数组越界确保索引在 0~length-1
ClassCastException类型转换失败instanceof 检查
ArithmeticException整数除零检查分母不为0
NumberFormatException字符串转数字格式错误用正则或 try-catch
IllegalArgumentException参数不合法方法入口做参数校验

10. 异常处理最佳实践

  1. 不要吞异常catch 后什么都不做(空 catch)极其糟糕,会掩盖错误。
  2. 日志记录:使用 logger.error("xxx", e) 打印堆栈。
  3. 尽早抛出,晚点捕获:底层抛出具体异常,上层统一处理。
  4. 不要用异常控制正常流程:异常性能差,用 if-else 代替。
  5. 关闭资源:使用 try-with-resources 或 finally。
  6. 抛出的异常要合适:不要抛出 Exception,尽量具体(如 IOException)。

第二部分:常用类详解

1. Object 类(所有类的根)

1.1 toString()

默认返回 类名@哈希码,一般需要重写。

@Override
public String toString() {
    return "Person{name='" + name + "', age=" + age + "}";
}

自动调用:System.out.println(obj) 实际调用 obj.toString()

1.2 equals()

默认比较内存地址(==)。需要比较内容时重写。

重写契约

  • 自反性:x.equals(x) 为 true
  • 对称性:x.equals(y)y.equals(x) 结果相同
  • 传递性
  • 一致性:多次调用结果不变
  • null 比较返回 false
@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Person p = (Person) obj;
    return age == p.age && Objects.equals(name, p.name);
}

1.3 hashCode()

必须与 equals 保持一致:如果 equals 相等,hashCode 必须相等。反之不要求。

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

作用:用于哈希集合(HashMapHashSet)的快速查找。

1.4 clone() 与 Cloneable 接口

Cloneable 是个标记接口(没有方法),指示 Object.clone() 可以合法复制对象。

浅拷贝(默认):

class Student implements Cloneable {
    String name;
    int[] scores;
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅拷贝:scores 数组引用相同
    }
}

深拷贝:手动复制引用类型字段。

@Override
public Object clone() throws CloneNotSupportedException {
    Student s = (Student) super.clone();
    s.scores = this.scores.clone();  // 数组是引用类型,需要单独克隆
    return s;
}

注意:克隆时如果字段是自定义对象,该对象也需实现 Cloneable

1.5 getClass() 和 finalize()

  • getClass():返回运行时类对象(Class 实例),用于反射。
  • finalize():垃圾回收前调用,已废弃(从 Java 9 开始)。不推荐使用。

2. 包装类(Wrapper Class)

2.1 基本对应关系

基本类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

2.2 构造与转换(以 Integer 为例)

// 构造(JDK9 后标记为过时,推荐 valueOf)
Integer i1 = new Integer(10);
Integer i2 = Integer.valueOf(10);   // 推荐,有缓存
// 字符串转 Integer
Integer i3 = Integer.valueOf("123");
int i4 = Integer.parseInt("123");    // 返回基本类型
// 包装类转基本类型
int val = i1.intValue();
// 字符串转基本类型
int i5 = Integer.parseInt("456");

2.3 自动装箱与拆箱(编译器语法糖)

Integer a = 100;        // 实际是 Integer.valueOf(100)
int b = a;              // 实际是 a.intValue()

陷阱

Integer n = null;
int m = n;   // NullPointerException,因为拆箱调用 n.intValue()

2.4 缓存池

  • Integer 默认缓存 -128127valueOf() 在此范围内返回缓存对象,否则 new Integer
  • ByteShortLong 也缓存 -128~127
  • Character 缓存 0~127
  • Boolean 缓存 TRUEFALSE
Integer x = 127;
Integer y = 127;
System.out.println(x == y);   // true(缓存)
Integer m = 128;
Integer n = 128;
System.out.println(m == n);   // false(超出范围,新对象)
// 解决方案:用 equals 比较
System.out.println(m.equals(n)); // true

2.5 常用常量与方法

System.out.println(Integer.MAX_VALUE);  // 2147483647
System.out.println(Integer.MIN_VALUE);  // -2147483648
System.out.println(Integer.SIZE);       // 32(位)
System.out.println(Integer.toBinaryString(10)); // "1010"

3. 时间处理类

3.1 旧版 Date & Calendar(线程不安全,不推荐)

Date date = new Date();                     // 当前时间
long time = date.getTime();                 // 毫秒数
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(date);
Date parsed = sdf.parse("2020-01-01 12:00:00"); // 可能抛 ParseException

问题SimpleDateFormat 不是线程安全的,多线程共用需要加锁或使用 ThreadLocal

3.2 Java 8 新时间 API(推荐)

位于 java.time 包,不可变、线程安全。

核心类

  • LocalDate:日期(年-月-日)
  • LocalTime:时间(时:分:秒.纳秒)
  • LocalDateTime:日期+时间
  • ZonedDateTime:带时区的日期时间
  • Instant:时间戳(秒/纳秒)
  • Duration:时间间隔(秒、纳秒)
  • Period:日期间隔(年、月、日)
  • DateTimeFormatter:格式化器
// 获取当前时间
LocalDate today = LocalDate.now();
LocalTime nowTime = LocalTime.now();
LocalDateTime now = LocalDateTime.now();
// 指定日期
LocalDate birthday = LocalDate.of(1999, 3, 15);
LocalDateTime dt = LocalDateTime.of(2024, 12, 31, 23, 59, 59);
// 解析与格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter);
LocalDateTime parsed = LocalDateTime.parse("2025-01-01 10:20:30", formatter);
// 日期运算
LocalDate nextWeek = today.plusWeeks(1);
LocalDate twoMonthsAgo = today.minusMonths(2);
LocalDate nextBirthday = birthday.withYear(today.getYear());
if (nextBirthday.isBefore(today)) {
    nextBirthday = nextBirthday.plusYears(1);
}
// 时间差
Period period = Period.between(birthday, today);
System.out.println(period.getYears() + "年" + period.getMonths() + "月");
long days = ChronoUnit.DAYS.between(birthday, today);
// Instant 时间戳
Instant nowInstant = Instant.now();        // UTC 时间
long epochSecond = nowInstant.getEpochSecond();
long nano = nowInstant.getNano();
// Duration
Duration d = Duration.between(LocalTime.of(9,0), LocalTime.of(17,30));
System.out.println(d.toHours());   // 8

4. 数组(Array)

4.1 内存结构

int[] arr = new int[3];
  • arr 在栈中存储引用,指向堆中一块连续内存区域。
  • 每个元素有默认初始值(0、0.0、false、\u0000、null)。
  • 引用类型数组存的是对象的引用,对象本身在堆中的其他位置。

4.2 创建与初始化

// 静态初始化
int[] a = {1,2,3};
int[] b = new int[]{4,5,6};
// 动态初始化
int[] c = new int[10];      // 元素默认0
String[] d = new String[5]; // 元素默认null

4.3 多维数组(非规则数组)

int[][] matrix = new int[3][4];          // 3行4列
int[][] jagged = new int[3][];
jagged[0] = new int[2];
jagged[1] = new int[4];
jagged[2] = new int[1];

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

4.4 Arrays 工具类(java.util.Arrays)

// 排序
int[] arr = {3,1,4,1,5,9};
Arrays.sort(arr);                    // 升序
Arrays.parallelSort(arr);            // 并发排序(大数据量)
// 二分查找(必须先排序)
int idx = Arrays.binarySearch(arr, 4);
// 填充
int[] fillArr = new int[10];
Arrays.fill(fillArr, 5);             // 全填充5
Arrays.fill(fillArr, 2, 5, 8);       // 索引2~4填充8
// 复制
int[] copy = Arrays.copyOf(arr, arr.length);
int[] rangeCopy = Arrays.copyOfRange(arr, 1, 4);
// 比较
boolean eq = Arrays.equals(arr, copy);
boolean deepEq = Arrays.deepEquals(matrix1, matrix2); // 多维
// 转字符串
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.deepToString(matrix));
// 转换为 List(不可修改大小)
List<Integer> list = Arrays.asList(1,2,3);
// 注意:返回的是视图,不能 add/remove,但可以 set

4.5 数组复制与扩容

// 手动扩容
int[] old = {1,2,3};
int[] newArr = new int[old.length * 2];
System.arraycopy(old, 0, newArr, 0, old.length);

5. 字符串(String)

5.1 String 的不可变性

  • String 内部使用 final char[](Java 9+ 改为 byte[])存储,且数组不对外暴露。
  • 每次修改(如 concatreplacesubstring)都会创建新的 String 对象。
String s = "hello";
s = s + " world";   // 实际创建新对象,原 "hello" 变成垃圾

5.2 字符串常量池

  • 字面量 "abc" 存储在常量池(堆中,JDK7+)。
  • new String("abc") 会在堆中创建新对象,同时常量池中如果不存在也会创建。
  • intern() 方法:如果常量池中存在相等字符串,返回常量池引用;否则将当前字符串放入常量池并返回引用。
String s1 = "java";
String s2 = new String("java");
System.out.println(s1 == s2);               // false
System.out.println(s1 == s2.intern());      // true

JDK 版本差异

  • JDK6:常量池在 PermGen 区域,intern() 复制字符串到永久代。
  • JDK7+:常量池移到堆,intern() 只存储引用,不再复制。

5.3 常用方法

String str = " Hello World ";
// 长度
int len = str.length();
// 取字符
char ch = str.charAt(6);
// 比较
boolean eq = str.equals("hello world");          // 区分大小写
boolean eqIgnore = str.equalsIgnoreCase("hello world");
int cmp = str.compareTo("Hello");                 // 字典序
// 查找
int idx = str.indexOf('o');          // 第一个出现位置
int lastIdx = str.lastIndexOf('o');
boolean contains = str.contains("World");
// 替换
String r1 = str.replace('o', 'a');
String r2 = str.replaceAll("\\s+", "");  // 正则
// 截取
String sub = str.substring(6, 11);       // [6,11)
// 分割
String[] parts = str.split("\\s+");      // 按空白分割
// 去首尾空白
String trimmed = str.trim();
// 大小写转换
String upper = str.toUpperCase();
String lower = str.toLowerCase();
// 判断前后缀
boolean starts = str.startsWith(" He");
boolean ends = str.endsWith("ld ");
// 字符串连接
String joined = String.join("-", "a", "b", "c");  // "a-b-c"
// 格式化
String fmt = String.format("姓名:%s,年龄:%d", "张三", 25);
// 转字符数组
char[] chars = str.toCharArray();
// 字符串和基本类型的转换
String numStr = String.valueOf(123);
int num = Integer.parseInt("123");

5.4 StringBuilder / StringBuffer

  • StringBuilder(非线程安全,速度快)
  • StringBuffer(线程安全,方法有 synchronized,速度慢)

常用方法

StringBuilder sb = new StringBuilder();          // 默认容量16
sb.append("hello");
sb.append(' ');
sb.append("world");
sb.insert(5, ",");
sb.delete(5, 6);
sb.replace(0, 5, "HELLO");
sb.reverse();
String result = sb.toString();

性能建议:在循环内拼接大量字符串时,显式使用 StringBuilder,避免使用 +,因为 + 在循环内会产生大量临时对象。

6. Math 类

所有方法都是 static,主要用于数学运算。

// 基本
Math.abs(-10);          // 10
Math.max(10,20);        // 20
Math.min(10,20);        // 10
Math.pow(2,3);          // 8.0
Math.sqrt(9);           // 3.0
// 取整
Math.ceil(3.2);         // 4.0 向上取整
Math.floor(3.9);        // 3.0 向下取整
Math.round(3.5);        // 4 四舍五入(返回 long)
Math.round(3.4);        // 3
// 随机数 [0.0, 1.0)
double r = Math.random();
int dice = (int)(Math.random() * 6) + 1;   // 1~6
// 三角函数、对数等
Math.sin(Math.PI/2);
Math.log(10);
Math.exp(1);

7. File 类(java.io.File)

代表文件或目录的路径,并不代表文件内容。

7.1 构造

File f1 = new File("D:/test/a.txt");
File f2 = new File("D:/test", "a.txt");
File parent = new File("D:/test");
File f3 = new File(parent, "a.txt");

路径分隔符File.separator 跨平台(Windows 是 \,Linux 是 /),建议使用。

7.2 常用方法

File f = new File("D:/test/a.txt");
// 判断
f.exists();
f.isFile();
f.isDirectory();
f.isHidden();
f.canRead();
f.canWrite();
// 获取信息
f.getName();          // "a.txt"
f.getPath();          // 构造时的路径
f.getAbsolutePath();  // 绝对路径
f.length();           // 字节数
f.lastModified();     // 最后修改时间(毫秒)
// 创建删除
f.createNewFile();            // 创建新文件,返回 boolean
f.mkdir();                    // 创建单级目录
f.mkdirs();                   // 创建多级目录
f.delete();                   // 删除文件或空目录
f.deleteOnExit();             // JVM 退出时删除
// 目录操作
File dir = new File("D:/test");
String[] names = dir.list();               // 文件名数组
File[] files = dir.listFiles();            // File 对象数组
File[] mp3s = dir.listFiles((d, name) -> name.endsWith(".mp3"));

7.3 递归遍历目录

public static void listAll(File dir) {
    if (dir == null || !dir.exists()) return;
    if (dir.isFile()) {
        System.out.println(dir.getAbsolutePath());
    } else {
        File[] subs = dir.listFiles();
        if (subs != null) {
            for (File sub : subs) {
                listAll(sub);
            }
        }
    }
}

8. 枚举(Enum)

8.1 基本用法

public enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

每个枚举值都是 Season 类的实例,且是唯一的单例。

8.2 枚举的本质

  • 隐式继承 java.lang.Enum 类,因此不能继承其他类,但可以实现接口。
  • 枚举值实际上是 public static final 常量。
  • 编译器会自动生成 values()valueOf(String) 方法。
Season s = Season.SPRING;
System.out.println(s.name());        // "SPRING"
System.out.println(s.ordinal());     // 0(声明顺序)
System.out.println(s.toString());    // "SPRING"(可重写)

8.3 带字段和构造器的枚举

public enum Status {
    SUCCESS(200, "成功"),
    ERROR(500, "服务器错误"),
    NOT_FOUND(404, "资源不存在");
    private int code;
    private String msg;
    Status(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public int getCode() { return code; }
    public String getMsg() { return msg; }
    public static Status fromCode(int code) {
        for (Status s : values()) {
            if (s.code == code) return s;
        }
        return null;
    }
}

8.4 枚举实现接口

interface Desc {
    String getDescription();
}
enum Color implements Desc {
    RED {
        public String getDescription() { return "红色"; }
    },
    BLUE {
        public String getDescription() { return "蓝色"; }
    };
}

8.5 枚举的单例模式

利用枚举的特性(JVM 保证单例、线程安全、防止反射和序列化破坏)。

public enum Singleton {
    INSTANCE;
    public void doSomething() { ... }
}

8.6 EnumSet 和 EnumMap(性能高效)

EnumSet<Season> set = EnumSet.of(Season.SPRING, Season.SUMMER);
EnumMap<Season, String> map = new EnumMap<>(Season.class);
map.put(Season.SPRING, "春天");

总结

异常机制

  • 区分 Error、RuntimeException 和 Checked Exception。
  • 使用 try-catch-finally 或 throws,推荐 try-with-resources。
  • finally 中避免 return。
  • 自定义异常时根据场景选择继承 Exception 还是 RuntimeException。

常用类

  • Object 的 toString/equals/hashCode 必须配合重写。
  • 包装类注意缓存池和自动装箱的空指针风险。
  • 时间处理优先用 java.time 包。
  • 数组工具类 Arrays 提供丰富操作。
  • String 不可变,拼接多用 StringBuilder。
  • File 操作路径注意跨平台分隔符。
  • 枚举用于固定常量集合,功能强大。

这些类在日常开发中几乎天天使用,建议结合 JDK 源码加深理解。

到此这篇关于Java 异常机制与常用类的文章就介绍到这了,更多相关Java 异常机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 通过Java添加Word文本框过程详解

    通过Java添加Word文本框过程详解

    这篇文章主要介绍了通过Java添加Word文本框过程详解,在Word中,文本框是指一种可移动、可调节大小的文字或图形容器。我们可以向文本框中添加文字、图片、表格等对象,下面,将通过Java编程来实现添加以上对象到Word文本框,需要的朋友可以参考下
    2019-07-07
  • Mybatis MappedStatement类核心原理详解

    Mybatis MappedStatement类核心原理详解

    这篇文章主要介绍了Mybatis MappedStatement类,mybatis的mapper文件最终会被解析器,解析成MappedStatement,其中insert|update|delete|select每一个标签分别对应一个MappedStatement
    2022-11-11
  • Java调用WebService服务的三种方式总结

    Java调用WebService服务的三种方式总结

    虽然WebService这个框架已经过时,但是有些公司还在使用,在调用他们的服务的时候就不得不面对各种问题,本篇文章总结了最近我调用 WebService的心路历程,3种方式可以分别尝试,需要的朋友可以参考下
    2023-08-08
  • SpringMVC+ZTree实现树形菜单权限配置的方法

    SpringMVC+ZTree实现树形菜单权限配置的方法

    本篇文章主要介绍了SpringMVC+ZTree实现树形菜单权限配置的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Java编程实现基于TCP协议的Socket聊天室示例

    Java编程实现基于TCP协议的Socket聊天室示例

    这篇文章主要介绍了Java编程实现基于TCP协议的Socket聊天室,结合实例形式详细分析了java基于TCP协议的Socket聊天室客户端与服务器端相关实现与使用技巧,需要的朋友可以参考下
    2018-01-01
  • Spring boot + mybatis + orcale实现步骤实例代码讲解

    Spring boot + mybatis + orcale实现步骤实例代码讲解

    这篇文章主要介绍了Spring boot + mybatis + orcale的实现步骤实例代码讲解,需要的朋友可以参考下
    2017-12-12
  • JMeter导入自定义的Jar包的详解教程

    JMeter导入自定义的Jar包的详解教程

    这篇文章主要介绍了JMeter导入自定义的Jar包的详解教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • 详解Spring基于xml的两种依赖注入方式

    详解Spring基于xml的两种依赖注入方式

    这篇文章主要介绍了详解Spring基于xml的两种依赖注入方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • Java圆通物流轨迹推送服务接口文档及流程

    Java圆通物流轨迹推送服务接口文档及流程

    这篇文章主要介绍了圆通物流轨迹推送服务接口Java文档,主要用来接收圆通推送的订单状态,本文给大家分享详细流程,感兴趣的朋友跟随小编一起看看吧
    2022-02-02
  • Java 实现万年历总结

    Java 实现万年历总结

    这篇文章主要介绍了Java 万年历实现代码的相关资料,需要的朋友可以参考下
    2016-09-09

最新评论