day13——Java常用API(一):Object、包装类、字符串处理

Java API是提升开发效率的关键武器,本文将全面解析Object类、包装类、字符串处理工具等核心API的使用技巧与底层原理

一、API概述与学习路径

API(应用程序编程接口) 是Java预先编写好的程序模块(类、方法等),开发者可直接调用解决特定问题。Java进阶需掌握以下核心API:
在这里插入图片描述
今天学习的内容:

常用API
Object类
Objects工具类
包装类
字符串处理
StringBuilder
StringBuffer
StringJoiner

学习建议

  • 理解每个API的设计目的
  • 掌握关键方法的使用场景
  • 通过实践对比不同API的性能差异
  • 善用IDE的源码查看功能(Ctrl+点击类名)

二、Object类:Java的祖宗类

作为所有类的超类,Java中所有类的对象都可以直接使用Object类中提供的一些方法:
在这里插入图片描述

1. toString()方法

作用:返回对象的字符串表示形式
toString()方法存在的意义就是为了被子类重写,以便返回对象具体的内容。

// 默认实现
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

// 正确实践:重写示例
@Override
public String toString() {
    return "Student{name='" + name + "', age=" + age + "}";
}

开发规范

  • 所有实体类必须重写toString()
  • 输出内容应包含关键属性值
  • 避免在方法内进行复杂计算
2. equals()方法

作用:比较对象是否相等
直接比较两个对象的地址是否相同完全可以用“==”替代equals,equals存在的意义就是为了被子类重写,以便子类自己来定制比较规则(比如比较对象内容)。

// 默认实现(等价于==)
public boolean equals(Object obj) {
    return (this == obj);
}

// 正确重写步骤:
@Override
public boolean equals(Object o) {
    // 1. 地址相同直接返回true
    if (this == o) return true;
    
    // 2. 处理null和类型不匹配
    if (o == null || getClass() != o.getClass()) return false;
    
    // 3. 类型转换后比较字段值
    Student student = (Student) o;
    return age == student.age && 
           Objects.equals(name, student.name);
}

// 可以使用Alt+Insert选择生成equals()和hashCode()

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

关键点

  • 重写equals()必须同时重写hashCode()
  • 比较逻辑应满足自反性、对称性、传递性
  • 优先使用Objects.equals()比较可能为null的属性
3. clone()方法(了解)

当某个对象调用这个方法时,这个方法会复制一个一模一样的新对象返回。
对象克隆的两种实现方式

克隆类型特点实现方式
浅克隆引用类型字段共享地址super.clone()
深克隆完全独立的对象副本递归调用clone()
// 深克隆实现
@Override
protected Object clone() throws CloneNotSupportedException {
    User cloned = (User) super.clone();
    cloned.scores = scores.clone(); // 数组深拷贝
    return cloned;
}

内存示意图

浅克隆:
原对象 --> [基本类型值]
          [引用类型地址] --> 共享数据

深克隆:
原对象 --> [基本类型值]
          [新引用地址] --> 独立数据副本

在这里插入图片描述

三、Objects工具类

在这里插入图片描述
可以用s1.equals(s2) 和 Objects.equals(s1,s2) 判断是否相等,那为什么idea自动创建equals 方法重写时用 Objects.equals(name, student.name) 呢?

解决对象操作中的空指针问题:

// 安全比较(自动处理null)
Objects.equals(null, "test"); // false
null equals("test") //会报错,不安全,不好用

// 空检查
Objects.isNull(obj);   // 替代 obj == null
Objects.nonNull(obj);  // 替代 obj != null

// 源码解析
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

使用场景

  • 方法参数校验
  • 避免级联null检查
  • 比较用户输入等不可控对象

在这里插入图片描述

四、包装类:基本类型的对象化

1. 包装类体系
基本类型包装类缓存范围
byteByte-128~127
shortShort-128~127
intInteger-128~127
longLong-128~127
floatFloat无缓存
doubleDouble无缓存
charCharacter0~127
booleanBooleantrue/false
2. 自动装箱/拆箱
// 自动装箱(编译器优化)
Integer a = 100; 
// 等价于→ Integer.valueOf(100)

// 自动拆箱
int b = a; 
// 等价于→ a.intValue()

注意事项

  • 包装类对象不可变(修改值会创建新对象)
  • 数值比较使用equals()而非==
  • 警惕NPE:Integer num = null; int n = num; // 抛出NullPointerException
3. 类型转换
// String → 基本类型
int age = Integer.parseInt("25");
double score = Double.parseDouble("89.5");

// 基本类型 → String
String s1 = Integer.toString(100);
String s2 = String.valueOf(3.14f);
String s3 = 200 + ""; // 不推荐(产生临时对象)

在这里插入图片描述

五、高性能字符串处理

1. StringBuilder vs String

在这里插入图片描述

性能对比实验

// 错误示范:字符串拼接
String result = "";
for (int i = 0; i < 100000; i++) {
    result += "a"; // 每次循环创建新对象
}

// 正确做法
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    sb.append("a"); // 修改内部char[]
}
return sb.toString();

性能差异

  • 10万次拼接:StringBuilder约5ms vs String约8秒
  • 原因:String不可变性导致大量临时对象

对于字符串相关的操作,如频繁的拼接、修改等,建议用StringBuidler,效率更高!
注意:如果操作字符串较少,或者不需要操作,以及定义字符串变量,还是建议用String。

2. StringBuilder核心API
// 链式调用
sb.append("Hello")
  .append(" ")
  .append("World!")
  .insert(5, ",")
  .reverse();

// 容量管理
sb.ensureCapacity(100); // 预分配空间
sb.trimToSize();        // 释放多余空间

在这里插入图片描述

3. StringBuffer线程安全版

StringBuffer的用法与StringBuilder是一模一样的

// 用法相同但线程安全
StringBuffer safeBuffer = new StringBuffer();
safeBuffer.append("Thread-Safe");

// 实现原理
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

选型建议

  • 单线程环境:StringBuilder(速度更快)
  • 多线程环境:StringBuffer(线程安全)
  • 少量操作:String(代码简洁)

六、StringJoiner:结构化拼接

JDK8提供的增强型字符串工具:跟StringBuilder一样,也是用来操作字符串的,也可以看成是一个容器,创建之后里面的内容是可变的。

好处:不仅能提高字符串的操作效率,并且在有些场景下使用它操作字符串,代码会更简洁

用法:
public StringJoiner (间隔符号)
public StringJoiner (间隔符号,开始符号,结束符号)

// 基础用法
StringJoiner sj = new StringJoiner(", ", "[", "]");
sj.add("Apple").add("Orange").add("Banana");
// 输出:[Apple, Orange, Banana]

// 替代StringBuilder的集合拼接
List<String> list = Arrays.asList("Java", "Python", "C++");
String result = String.join("|", list); // Java|Python|C++

优势场景

  • CSV文件生成
  • SQL IN条件拼接
  • JSON数组构造
  • 带前缀后缀的格式化输出

七、实战应用案例

1. 对象比较工具
public static boolean safeEquals(Object a, Object b) {
    return Objects.equals(a, b);
}
2. 数组格式化输出
public static String formatArray(int[] arr) {
    if (arr == null) return "null";
    
    StringJoiner sj = new StringJoiner(", ", "[", "]");
    for (int num : arr) {
        sj.add(String.valueOf(num));
    }
    return sj.toString();
}
3. 深克隆工具方法
public static <T extends Serializable> T deepClone(T obj) {
    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(bos)) {
        
        oos.writeObject(obj);
        
        try (ByteArrayInputStream bis = 
                new ByteArrayInputStream(bos.toByteArray());
             ObjectInputStream ois = new ObjectInputStream(bis)) {
            
            return (T) ois.readObject();
        }
    } catch (Exception e) {
        throw new RuntimeException("Clone failed", e);
    }
}

八、总结与最佳实践

  1. Object类

    • 重写toString()提供可读信息
    • 重写equals()/hashCode()保证对象比较正确性
    • 慎用clone(),优先考虑复制构造器
  2. 包装类

    • 集合存储必须使用包装类
    • 数值比较用equals()而非==
    • 注意自动装箱的性能开销
  3. 字符串处理

    • 循环内拼接必须用StringBuilder
    • 预分配容量(new StringBuilder(500))
    • 复杂格式化使用StringJoiner
  4. 性能陷阱规避

    // 反面示例
    String str = "Start";
    for (Data item : bigList) {
        str += item;  // 产生大量临时对象
    }
    
    // 正面示例
    StringBuilder sb = new StringBuilder(1024);
    sb.append("Start");
    for (Data item : bigList) {
        sb.append(item);
    }
    

掌握这些核心API的使用哲学,将使你的Java代码更加健壮高效。记住:正确的API选择比盲目优化代码更重要!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值