java基础知识【java核心类】

万物都是相同的,只要你把一个能力掌握好了,你会发现其他的东西都是万变不离其宗。

面向对象基础

模块

一、模块的核心概念

  1. 解决依赖问题

    • Java 9 前:jar包仅作为 class 文件的容器,不管理依赖,需手动通过-cp指定依赖,易引发ClassNotFoundException
    • Java 9 后:模块是自带依赖关系的 class 容器 ,通过module-info.class声明依赖,确保编译和运行时自动定位依赖模块。
  2. JDK 标准库模块化

    • rt.jar被拆分为数十个.jmod模块(如java.base.jmod),位于$JAVA_HOME/jmods,所有模块直接或间接依赖根模块java.base
    • 模块支持多版本和 JNI 二进制扩展,比 jar 包功能更强大。

二、编写模块

  1. 模块描述文件module-info.java

    • 声明模块名(如module hello.world)和依赖(requires java.xml),默认依赖java.base可省略。
    • 可通过exports 包名导出包,供其他模块访问(模块内权限控制增强,未导出的包对外不可见)。
  2. 编译与打包

    • 编译:javac -d bin src/module-info.java src/...,生成module-info.class
    • 打包为可运行 jar:jar --create --file hello.jar --main-class 主类 -C bin .
    • 转为模块文件(.jmod):jmod create --class-path hello.jar hello.jmod(主要用于打包 JRE)。

三、运行模块与打包 JRE

  1. 运行模块

    • 使用--module-path指定模块路径,--module指定模块名:

      bash

      arduino 复制代码
      java --module-path hello.jar --module hello.world
    • .jmod文件不能直接运行,需通过jlink工具处理。

  2. 精简 JRE 打包(jlink)

    • 按需提取所需模块(包括自定义模块),生成轻量 JRE,减少分发体积:

      bash

      css 复制代码
      jlink --module-path hello.jmod --add-modules java.base,java.xml,hello.world --output jre/
    • 分发时只需包含该jre目录,无需完整 JDK。

四、模块的访问权限

  • 模块内权限:继承 Java 原有的 public/protected/private/ 包访问权限,但仅在模块内有效。
  • 模块间访问 :需通过exports 包名显式导出包,否则其他模块无法访问该包内的类(如java.xml模块导出java.xml包后,外部才能使用其中的类)。

五、核心优势与小结

  • 依赖管理:模块显式声明依赖,避免手动配置 classpath 的繁琐和错误。
  • JRE 瘦身 :通过jlink按需打包,大幅减小运行时环境体积,方便部署。
  • 代码隔离:导出机制增强了模块间的封装性,提升系统安全性和可维护性。

java核心类

字符串和编码

一、String 基础特性与不可变性
  1. 本质与创建

    • String 是引用类型,底层通过 char[](早期 JDK)或优化的byte[](新版本,存储 ASCII 字符时节省空间)存储,支持字面量"..."和构造函数new String(char[])创建。
    • 不可变性 :内部字段private final修饰,所有修改操作(如toUpperCase())均返回新字符串,原字符串不变。
二、字符串比较规则
  1. 内容 vs 引用

    • equals() :比较字符串内容是否相同(需忽略大小写时用equalsIgnoreCase())。
    • == :仅比较引用是否指向同一对象(常量池优化可能导致==true,但属特例,不可依赖)。
    • 示例new String("a") == "a"false,因前者在堆中,后者在常量池。
三、常用操作方法详解
  1. 子串与搜索

    • 包含:contains(CharSequence);索引:indexOf()/lastIndexOf();首尾匹配:startsWith()/endsWith()
    • 提取:substring(start, end)(左闭右开,索引从 0 开始)。
  2. 空白处理

    • trim():移除首尾空格、\t、\r、\nstrip():额外处理全角空格\u3000isEmpty()(长度为 0)与isBlank()(全空白)。
  3. 替换与分割

    • 普通替换:replace(char/CharSequence);正则替换:replaceAll(String regex, String replacement)(如replaceAll("[\,\;\s]+", ","))。
    • 分割:split(String regex)(传入正则,如split("\,")按逗号分割,注意正则元字符需转义,如.需写为\.)。
  4. 拼接与格式化

    • 拼接:String.join(separator, array)(高效,避免+操作的性能损耗)。
    • 格式化:formatted()String.format(),占位符%s(字符串)、%d(整数)、%.2f(两位小数浮点数)等。
  5. 类型转换

    • 转字符串:String.valueOf()(自动适配类型);转基本类型:Integer.parseInt()/Boolean.parseBoolean()(注意getInteger()获取系统变量)。
四、字符编码原理与 Java 实现
  1. 编码基础

    • ASCII:1 字节(0-127),仅英文字符。
    • Unicode :统一编码(2 字节或更多),解决多语言冲突(如中文'中'的 Unicode 为0x4E2D)。
    • UTF-8:变长编码(1-4 字节),英文兼容 ASCII(1 字节),中文 3 字节,传输容错性强(推荐使用)。
  2. Java 编码转换

    • String/char内存中为 Unicode,转字节数组:getBytes("UTF-8")(避免默认编码,推荐用StandardCharsets.UTF_8)。
    • 字节数组转字符串:new String(byte[], charset)(指定编码如GBK/UTF-8,确保一致性)。
五、最佳实践与注意事项
  1. 不可变性设计

    • 构造方法中避免直接引用外部可变数组,需复制(如this.scores = Arrays.copyOf(scores, scores.length)),防止外部修改影响内部状态。
  2. 性能优化

    • 频繁拼接用StringBuilder/StringJoiner,减少临时对象创建;split()replaceAll()谨慎使用正则,避免不必要的转义。
  3. 编码规范

    • 始终明确指定编码(如 UTF-8),确保跨平台兼容性;处理用户输入时,注意编码转换可能导致的乱码问题。
六、核心总结
  • 不可变性:String 操作返回新对象,安全且线程友好,但需注意性能开销。
  • 比较规则 :内容比较用equals(),引用比较用==,常量池优化是特例而非通用规则。
  • 编码转换 :内存中为 Unicode,通过getBytes()和构造函数与字节数组交互,UTF-8 是首选编码。
  • 工具方法 :熟练掌握trim()substring()format()等,结合正则提升灵活性,同时避免常见陷阱(如错误转义)。

一、StringBuilder 核心作用

  1. 高效字符串拼接

    • 解决String不可变导致的性能问题:String拼接时每次生成新对象,循环中大量创建临时对象浪费内存、影响 GC 效率。
    • StringBuilder是可变对象,可预分配缓冲区,通过append()等方法直接修改内部字符数组,避免临时对象创建。
  2. 适用场景:循环内高频字符串拼接(如日志生成、SQL 语句构造等)。

二、核心特性与用法

  1. 链式操作

    • 方法(如append()insert())返回this,支持连续调用,代码更简洁。
    • 示例:

    java

    go 复制代码
    new StringBuilder()
        .append("Hello, ")
        .append("Bob")
        .insert(0, "Mr "); // 结果:Mr Hello, Bob
  2. 源码原理 :通过返回当前实例(return this)实现链式调用,用户可模仿设计自定义链式操作类(如计数器Adder)。

三、与 StringBuffer 的对比

特性 StringBuilder StringBuffer
线程安全 非线程安全(无同步) 线程安全(方法加synchronized
性能 更高(无同步开销) 较低(同步导致性能损耗)
推荐场景 单线程或非并发场景 早期多线程场景(现完全被StringBuilder替代,无需使用)

四、实践与注意事项

  1. 编译器优化 :普通String拼接(非循环中)会被编译器优化为StringConcatFactory操作,无需手动改写为StringBuilder

  2. 练习示例 :构造INSERT语句时,通过循环拼接字段和占位符?,避免硬编码,提高通用性。

    • 正确实现思路:

    java

    scss 复制代码
    static String buildInsertSql(String table, String[] fields) {
        StringBuilder sb = new StringBuilder();
        sb.append("INSERT INTO ").append(table).append(" (");
        for (int i = 0; i < fields.length; i++) {
            sb.append(fields[i]);
            if (i < fields.length - 1) sb.append(", "); // 非最后一个字段添加逗号
        }
        sb.append(") VALUES (");
        for (int i = 0; i < fields.length; i++) {
            sb.append("?");
            if (i < fields.length - 1) sb.append(", "); // 生成占位符
        }
        sb.append(")");
        return sb.toString();
    }

练习

java 复制代码
public class Main {
    public static void main(String[] args) {
        String[] fields = { "name", "position", "salary" };
        String table = "employee";
        String insert = buildInsertSql(table, fields);
        System.out.println(insert);
        String s = "INSERT INTO employee (name, position, salary) VALUES (?, ?, ?)";
        System.out.println(s.equals(insert) ? "测试成功" : "测试失败");
    }

    static String buildInsertSql(String table, String[] fields) {
        StringBuilder sb = new StringBuilder(1024);
        sb.append("INSERT INTO ")
                .append(table);
        sb.append(" (");
        for (int i = 0; i < fields.length; i++) {
            sb.append(fields[i]+ (i < fields.length - 1 ? ", " : ")"));
        }
        sb.append(" VALUES (");
        for (int i = 0; i < fields.length; i++) {
            sb.append("?"+ (i < fields.length - 1 ? ", " : ")"));
        }
        return sb.toString();
    }
}

StringJoiner的教程,主要介绍StringJoiner的用法、与相关方法的对比及练习,具体内容如下:

  • 核心功能:用于高效拼接带分隔符的字符串,可附加固定的开头和结尾字符串,简化字符串拼接逻辑,避免手动处理分隔符和首尾字符。

  • 基本用法

    • 构造函数StringJoiner(分隔符):创建仅包含分隔符的 Joiner,如new StringJoiner(", ")StringJoiner(分隔符, 开头, 结尾):创建包含分隔符、开头和结尾的 Joiner,如new StringJoiner(", ", "Hello ", "!")
    • 核心方法add(String element):向 Joiner 中添加元素,自动用分隔符连接。toString():返回最终拼接的字符串。
  • String.join()对比

    • String.join(分隔符, 数组):静态方法,内部使用StringJoiner,适用于简单的分隔符拼接(无需开头 / 结尾),代码更简洁。
    • StringJoiner:支持自定义开头和结尾,灵活性更高,适合复杂拼接场景(如 SQL 语句构造)。
  • 示例代码

    • 基础拼接 :通过StringJoiner循环添加元素,自动处理分隔符。
    • 带首尾字符串:在构造函数中指定开头(如 "SELECT")和结尾(如 "FROM table"),直接生成完整语句。

包装类型

转换为包装类型的目的是说,可以调用包装类型的静态方法。

Java 包装类型详解

一、基本概念
  1. 数据类型分类

    • 基本类型 (8 种):byteshortintlongbooleanfloatdoublechar不能赋值为null
    • 引用类型 :所有classinterface,可赋值为null
  2. 包装类型定义

    • 为基本类型提供对应的引用类型(java.lang包下),如Integer对应intBoolean对应boolean等,便于将基本类型视为对象操作。
二、自动装箱与拆箱(JDK 1.5+)
  1. 核心机制

    • 自动装箱 :编译期自动将基本类型转为包装类型(如Integer n = 100;等价于Integer.valueOf(100))。
    • 自动拆箱 :编译期自动将包装类型转为基本类型(如int x = n;等价于n.intValue())。
  2. 注意事项

    • 效率影响 :装箱拆箱发生在编译期,但运行时仍需执行对应方法(如valueOf()intValue()),频繁操作会影响性能。
    • 空指针风险 :拆箱时若包装类型为null,会抛出NullPointerException(如Integer n = null; int x = n;)。
三、不变类特性
  1. 不可变性

    • 所有包装类型均为不变类 (如Integervalue字段为final),实例创建后值不可修改。
  2. 对象比较

    • 禁止使用== :包装类型是引用类型,==比较引用地址而非值。
    • 必须使用equals() :即使值相同,不同实例的==可能为true(如小整数缓存优化),但需统一用equals()保证语义正确。
    • 缓存优化Integer.valueOf()-128~127的整数返回缓存实例,超出范围则创建新实例,但代码逻辑不应依赖此优化。
四、常用方法与功能
  1. 创建实例

    • 推荐静态工厂方法Integer.valueOf(int)Integer.valueOf(String),而非new Integer()(后者在 Java 9 + 被弃用,且无法利用缓存)。
  2. 进制转换

    • 解析字符串Integer.parseInt("100")(十进制)、Integer.parseInt("100", 16)(十六进制)。
    • 格式化为字符串Integer.toString(n, 36)(36 进制)、toHexString(十六进制)、toBinaryString(二进制)等。
  3. 静态变量与工具方法

    • 极值:Integer.MAX_VALUEInteger.MIN_VALUE
    • 类型信息:Long.SIZE(位数)、Long.BYTES(字节数)。
    • 无符号转换:Byte.toUnsignedInt(-1)byte-1转为无符号255(适用于byte/short/int转更高位无符号类型)。
  4. 继承体系

    • 整数和浮点数包装类型继承自Number,可转换为多种基本类型(如Number num = new Integer(999); int n = num.intValue();)。
五、最佳实践
  1. 对象创建 :优先使用静态工厂方法(如valueOf()),而非new操作符,以便库实现优化(如缓存)。
  2. 对象比较 :始终用equals()比较包装类型值,避免依赖==的缓存优化特性。
  3. 数据处理:利用包装类提供的工具方法(进制转换、无符号运算等),分离数据存储与显示逻辑。

javaBean

可以理解为只是一种协议规定。

一、JavaBean 定义与规范
  1. 基本定义

    • 符合特定命名规范的 Java 类,通常包含:

      • private 修饰的实例字段
      • public 修饰的字段读写方法(Getter/Setter)
    • 示例:

      typescript 复制代码
      public class Person {
          private String name;
          private int age;
          // Getter 和 Setter 方法
          public String getName() { return name; }
          public void setName(String name) { this.name = name; }
      }
  2. 命名规范

    • 普通字段

      • 读方法(Getter):getXyz()(首字母大写,前缀 get
      • 写方法(Setter):setXyz(Type value)(前缀 set
    • 布尔字段

      • 读方法通常为 isXyz()(如 isChild()
    • 属性类型

      • 读写属性:同时有 Getter 和 Setter
      • 只读属性 :仅有 Getter(如 getAge()
      • 只写属性:仅有 Setter(不常见)
    • 特殊说明 :属性可通过方法逻辑计算(不一定对应实际字段),例如 isChild() 可根据 age 计算返回值。

二、JavaBean 的作用
  1. 核心用途

    • 数据封装与传输:将相关数据组合为一个对象,便于在组件间传递(如 Web 开发中的参数传递)。
    • IDE 工具支持:通过 IDE(如 Eclipse、IntelliJ IDEA)自动生成 Getter/Setter,提升开发效率。
  2. 工具使用示例

    • 在 Eclipse 中,右键点击类文件,通过 Source -> Generate Getters and Setters 快速生成方法。
三、枚举 JavaBean 属性(反射 API)

通过 Java 核心库的 Introspector 类可动态获取 JavaBean 的属性信息:

  1. 关键类与方法

    • BeanInfo info = Introspector.getBeanInfo(Class<?> clazz):获取类的元信息。
    • PropertyDescriptor:封装属性名称、Getter 和 Setter 方法。
  2. 示例代码

    java 复制代码
    import java.beans.*;
    public class Main {
        public static void main(String[] args) throws Exception {
            BeanInfo info = Introspector.getBeanInfo(Person.class);
            for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
                System.out.println("属性名: " + pd.getName());
                System.out.println("读方法: " + pd.getReadMethod());
                System.out.println("写方法: " + pd.getWriteMethod());
            }
        }
    }
  3. 注意事项

    • 会包含从 Object 继承的 getClass() 方法对应的 class 属性,需按需过滤。
四、核心要点总结
  1. 本质 :通过 Getter/Setter 命名规范定义属性的 Java 类,非 Java 语法强制,而是编程约定。

  2. 核心优势

    • 数据封装性强,符合面向对象设计原则。
    • 兼容反射机制,便于框架(如 Spring)或工具动态操作属性。
  3. 最佳实践

    • 使用 IDE 自动生成 Getter/Setter,避免手动编写冗余代码。
    • 通过 Introspector 实现框架级属性解析(如序列化、配置绑定)。

BigInteger

一、概述
  • 用途 :处理超过 Java 原生long类型(64 位)范围的大整数运算,支持任意精度的整数。
  • 实现 :通过java.math.BigInteger类实现,内部使用int[]数组模拟大整数。
二、核心特性
  1. 不可变类 :与IntegerLong类似,实例一旦创建不可修改。
  2. 继承自Number :支持转换为基本数值类型(如byteshortintlongfloatdouble)。
  3. 无范围限制 :突破long类型的数值范围限制,但运算速度较原生类型慢(因需软件模拟)。
三、基本用法与运算
  1. 创建实例

    ini 复制代码
    BigInteger bi = new BigInteger("1234567890"); // 直接通过字符串初始化
  2. 算术运算

    • 加法:add(BigInteger val)

    • 乘法:multiply(BigInteger val)

    • 幂运算:pow(int exponent)

    • 示例:

      csharp 复制代码
      BigInteger sum = i1.add(i2); // 加法运算
      System.out.println(bi.pow(5)); // 计算5次幂
  3. 与原生类型对比

    • long运算速度快但范围有限(±9e18),BigInteger范围无限但速度慢。
四、类型转换
  1. 普通转换方法(可能丢失精度或溢出):

    • byteValue()shortValue()intValue()longValue()floatValue()doubleValue()
    • 例:longValue()BigInteger转为long,超出范围时截断高位。
  2. 精确转换方法(超出范围时抛异常):

    • intValueExact()longValueExact()等,若结果超出目标类型范围,抛出ArithmeticException
  3. 特殊场景

    • BigInteger值超过float最大范围(3.4×10³⁸)时,floatValue()返回Infinity

BigDecimal

一、BigDecimal 核心特性

  1. 精确表示小数

    • 用于任意精度的浮点运算,避免float/double的精度丢失问题,常见于财务计算。
    • 内部通过BigInteger(整数部分)和scale(小数位数)表示。
  2. 不可变对象 :所有运算(如加减乘除)均返回新的BigDecimal实例,原对象不变。

二、创建与初始化

  • 推荐使用字符串构造器

    java 复制代码
    BigDecimal bd = new BigDecimal("123.4567"); // 精确初始化,避免浮点精度误差

    ❗ 避免使用new BigDecimal(double),因double本身存在二进制精度丢失(如new BigDecimal(0.1)实际存储值为0.10000000149)。

三、小数位数与格式处理

  1. 获取小数位数(scale)

    • scale()方法返回小数位数:
    java 复制代码
    new BigDecimal("123.45").scale(); // 2  
    new BigDecimal("1234500").scale(); // 0(整数无小数位)  
  2. 去除末尾零(stripTrailingZeros)

    • 移除小数末尾的零,可能改变scale,若结果为整数且末尾有零,scale为负数(如1234500.stripTrailingZeros().scale() = -2,表示末尾有 2 个零)。

四、算术运算

  1. 基础运算(加、减、乘)

    • 直接调用对应方法,精度不丢失:
    java 复制代码
    BigDecimal result = d1.add(d2); // 加法  
    result = d1.multiply(d2); // 乘法  
  2. 除法(divide)

    • 必须指定精度和舍入模式 ,否则除不尽时抛出ArithmeticException
    java 复制代码
    // 保留10位小数,四舍五入  
    BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP);  
    • 常用舍入模式:RoundingMode.HALF_UP(四舍五入)、RoundingMode.DOWN(直接截断)。
  3. 除法与余数(divideAndRemainder)

    • 返回数组[商, 余数],商为整数(小数部分为 0),余数绝对值小于除数:
    ini 复制代码
    BigDecimal[] dr = n.divideAndRemainder(m);  
    if (dr[1].signum() == 0) { // 余数为0,n是m的整数倍  
    }  

五、精度调整(setScale)

  • 设置指定小数位数,支持舍入或截断:
java 复制代码
BigDecimal d1 = new BigDecimal("123.456789");  
d1.setScale(4, RoundingMode.HALF_UP); // 123.4568(四舍五入)  
d1.setScale(4, RoundingMode.DOWN); // 123.4567(直接截断)  

六、比较操作

  • 值比较(忽略 scale 差异) :使用compareTo(),返回 - 1(小于)、0(等于)、1(大于):
java 复制代码
BigDecimal d1 = new BigDecimal("123.456");  
BigDecimal d2 = new BigDecimal("123.45600");  
d1.compareTo(d2); // 0(值相等,忽略末尾零)  
  • 严格相等(值和 scale 均相同) :使用equals(),但实际开发中很少用,因业务场景更关注值是否相等:
java 复制代码
d1.equals(d2); // false(scale不同,d1.scale=3,d2.scale=5)  

Java 常用工具类

一、核心工具类概述

Java 核心库提供了多个常用工具类,用于数学计算、进制转换、随机数生成等场景,显著提升开发效率。以下是重点介绍的工具类:

二、工具类详解
1. Math 类
  • 功能:提供数学运算的静态方法和常量。

  • 常用方法

    • 基础运算abs()(绝对值)、max()/min()(最值)、pow(x, y)(x 的 y 次方)、sqrt()(平方根)。
    • 指数与对数exp(x)(e 的 x 次方)、log()(自然对数)、log10()(以 10 为底的对数)。
    • 三角函数sin()cos()tan()等。
    • 随机数random()生成[0, 1)的随机数,可通过公式扩展到指定区间。
  • 常量Math.PI(圆周率)、Math.E(自然对数底数)。

  • 注意 :与StrictMath的区别在于Math针对平台优化性能,而StrictMath保证跨平台计算结果一致。

2. HexFormat 类(Java 17+)
  • 功能 :简化byte[]数组与十六进制字符串的转换,支持格式定制。

  • 常用方法

    • 编码formatHex(byte[] data)将字节数组转为十六进制字符串,可通过ofDelimiter()withPrefix()withUpperCase()定制格式(如添加分隔符、前缀、大写字母)。
    • 解码parseHex(String hex)将十六进制字符串转为字节数组。
  • 示例
    HexFormat.of().formatHex("Hello".getBytes())48656c6c6f

3. Random 类
  • 功能:生成伪随机数,序列由初始种子决定。

  • 特点

    • 若不指定种子,默认使用系统时间戳,每次运行结果不同。
    • 指定种子(如new Random(12345))时,生成固定序列的伪随机数。
  • 常用方法

    • nextInt()/nextLong()/nextFloat()/nextDouble(),支持指定范围(如nextInt(10)生成[0, 10)的整数)。
  • 注意Math.random()内部调用Random,但无法指定种子。

4. SecureRandom 类
  • 功能:生成安全的随机数,用于密码学等对随机性要求高的场景。

  • 特点

    • 种子由系统提供的安全熵(如 CPU 热噪声、磁盘 I/O 事件)生成,不可预测。
    • 提供高强度实现(getInstanceStrong())和普通实现(new SecureRandom()),前者可能因熵不足阻塞线程。
  • 常用方法

    • nextInt()生成安全随机整数,nextBytes(byte[] buffer)填充安全随机字节。
  • 注意必须用于安全场景 ,绝不能用Random替代(后者种子可预测,存在安全风险)。

三、核心区别对比
工具类 随机性类型 种子来源 应用场景
Math 伪随机数(通过 Random) 系统时间戳(默认) 普通数学计算、非安全随机
Random 伪随机数 自定义或系统时间 非安全场景(如游戏随机)
SecureRandom 安全随机数(基于熵) 系统安全熵 密码学、加密密钥生成
相关推荐
赤橙红的黄5 分钟前
Spring BeanPostProcessor
java·spring
楽码12 分钟前
概率算法的空乘就坐问题
后端·算法·机器学习
程序员岳焱15 分钟前
Spring AI 2025重磅更新!Java程序员的AI时代正式开启
人工智能·后端·openai
程序员爱钓鱼15 分钟前
Go语言 并发编程基础:Goroutine 的创建与调度
后端·go·排序算法
jym的梦之独白16 分钟前
OAuth 2.0 客户端凭据授予流程
后端
闲情煮粥17 分钟前
《记一次Chromadb踩坑实录:藏在源码里的"秘密通道"》
后端
EMQX22 分钟前
驶向智能未来:车载 MCP 服务与边缘计算驱动的驾驶数据交互新体验
人工智能·后端
hola25 分钟前
解决Required request part 'file' is not present
后端
AI悦创Python辅导26 分钟前
我是如何爱上 __init__.py 的:一个简单易懂的指南
人工智能·后端·python
都叫我大帅哥26 分钟前
从HotSpot角度看synchronized的底层结构
java