一、Object 类

Object 是 Java 中所有类的根父类,默认位于java.lang包,无需手动导入。Java 里每一个类,无论是否显式继承,都会直接或间接继承Object,这也意味着Object中定义的所有方法,全体 Java 对象都能直接使用。同时Object类型的引用变量,可以接收任意类型的对象实例。

1. 核心常用方法详解

(1)getClass()

该方法会返回对象运行时的真实类型,常用来判断两个引用指向的对象是否为同一类型。

class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}

public class Test {
    public static void main(String[] args) {
        Animal a1 = new Cat();
        Animal a2 = new Dog();
        // 判断实际对象类型是否一致,此处输出 false
        System.out.println(a1.getClass() == a2.getClass());
    }
}
(2)hashCode()

作用是返回对象的哈希码值。底层逻辑是将对象在堆内存中的十六进制地址转为十进制整数。正常情况下,不同对象的哈希码不重复,该方法在集合框架(如 HashMap)中使用频率极高。

(3)toString()

用于返回对象的字符串描述,是开发中重写频率最高的方法之一。

  • 默认实现:直接返回类名@哈希码格式的字符串,可读性极差;
  • 重写规则:一般将类中所有成员属性拼接成字符串返回,方便打印对象信息;
  • 区分:getter方法只返回单个属性、不改变数据类型;toString整合全部属性,统一转为字符串。

示例重写:

class Student{
    private String name;
    private int age;
    // 构造器、get/set 省略
    @Override
    public String toString() {
        return "姓名:" + name + ",年龄:" + age;
    }
}
(4)equals (Object obj)【面试高频】

这是对象内容比较的核心方法,必须和==区分使用。

  1. == 运算符规则
    • 比较基本数据类型:判断两侧数值是否相等;
    • 比较引用数据类型:判断两个引用是否指向堆中同一个对象(比较内存地址)。
  2. 原生 equals 方法 Object中原生的equals本质就是==,依旧比较内存地址:
    public boolean equals(Object obj) {
        return (this == obj);
    }
    
  3. 自定义类重写 equals 规范 开发中我们需要用equals比较对象内容,因此必须手动重写,标准流程如下:
    1. 自反性判断:当前对象和目标对象为同一个,直接返回true
    2. 空值判断:目标对象为null,直接返回false
    3. 类型判断:两个对象实际类型不一致,返回false
    4. 强制类型转换:向下转型,准备对比属性;
    5. 属性逐一对比:基本类型用==,引用类型调用equals
(5)finalize()

JVM 垃圾回收机制相关方法。当一个对象没有任何引用指向时,就会成为垃圾对象。垃圾回收器(GC)回收对象前,会自动调用该方法。

  • 触发时机:内存不足时 GC 自动回收;也可通过System.gc()手动提醒 GC 执行(执行时机仍不可控);
  • 开发建议:该方法执行节点完全由 JVM 控制,不要在其中编写核心业务代码,仅作了解即可。

面试总结:== 和 equals 的区别

  1. ==:基本类型比数值,引用类型比内存地址;
  2. equals:原生实现等价于==,重写后用于对比对象内容,是字符串、自定义对象内容比较的首选。

二、基本类型的 “外衣”:包装类

Java 的 8 种基本数据类型不属于对象,无法直接参与面向对象的操作,包装类就是为每种基本类型匹配对应的引用类型,全部位于java.lang包。

1. 基本类型与包装类对照表

表格

基本数据类型 对应包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

2. 数据类型相互转换

(1)基本类型 ↔ 包装类
// 基本类型 → 包装类(装箱)
Integer num1 = new Integer(10);
Integer num2 = Integer.valueOf(10);

// 包装类 → 基本类型(拆箱)
int n = num1.intValue();
(2)字符串 ↔ 数值类型

这是项目中最常用的转换逻辑:

// String → int(重点),要求字符串必须是纯数字,否则抛出 NumberFormatException
int age = Integer.parseInt("20");

// int → String 两种方式
String s1 = 20 + "";
String s2 = Integer.toString(20);

3. 自动装箱与自动拆箱(JDK 5+ 新特性)

JDK5 之后,编译器自动完成基本类型和包装类的转换,简化代码书写:

// 自动装箱:底层调用 Integer.valueOf(int)
Integer a = 12;
// 自动拆箱:底层调用 intValue()
int b = a;
经典面试题:Integer 常量池

Integer内部存在常量池(缓存区),缓存范围为 -128 ~ 127。当使用自动装箱创建该区间内的Integer对象时,会直接从缓存中获取实例,不会新建对象;超出范围则会new新对象。

Integer i1 = 12;
Integer i2 = 12;
System.out.println(i1 == i2); // true,取自常量池,同一对象

Integer i3 = 150;
Integer i4 = 150;
System.out.println(i3 == i4); // false,超出缓存范围,两个新对象

4. 实战使用场景

在实体类、数据库映射场景中,建议将属性定义为包装类。原因:包装类可以赋值为null,能区分 “无数据” 和 “数值为 0” 两种状态,而基本类型默认值固定,无法区分无效数据。

三、字符串王者:String 类

String是 Java 中使用频率最高的类,用于存储和操作字符串,具备不可变性这一核心特性,也是面试必考知识点。

1. 两种创建方式与内存区别

  1. String s1 = "hello"; 仅在字符串常量池创建 1 个对象,后续重复使用该字符串会直接复用池中的实例。
  2. String s2 = new String("world"); 会创建两个对象:堆内存中的String实例 + 常量池中的字符串对象;若常量池已存在对应字符串,则只在堆中创建对象。

2. 常用核心方法

String str = "  Java Study  ";
// 1. charAt(int index):根据下标获取字符,下标越界抛出 StringIndexOutOfBoundsException
char c = str.charAt(2);

// 2. length():获取字符串长度(数组是 .length 属性,注意区分)
int len = str.length();

// 3. contains(String s):判断是否包含子串
boolean hasJava = str.contains("Java");

// 4. equals():比较字符串内容,字符串对比必须使用该方法,禁止用 ==
boolean same = "Java".equals(str.trim());

// 5. trim():去除字符串首尾空格(中间空格保留)
String newStr = str.trim();

// 6. split():按照指定规则拆分字符串,返回字符串数组
String[] arr = "1,2,3".split(",");

3. String 不可变性

字符串的内容一旦定义,就无法被修改。所有拼接、截取等操作,都不会改动原字符串,而是在内存中生成新字符串。

  • 弊端:频繁拼接字符串时,会产生大量临时垃圾对象,性能低下;
  • 特殊优化:String s = "a" + "b",编译器在编译阶段直接优化为"ab",仅生成一个常量池对象。

四、可变字符串:StringBuilder & StringBuffer

为解决String拼接效率低的问题,Java 提供了两个可变字符串类StringBuilderStringBuffer,二者底层都是可变字符数组,内容修改不会生成新对象。

1. 两者核心区别

表格

类名 版本 线程安全 运行效率
StringBuffer JDK 1.0 线程安全(加锁) 较慢
StringBuilder JDK 5.0 线程不安全(无锁) 极快

2. 常用方法

核心方法为append(),用于字符串拼接,支持任意数据类型:

StringBuilder sb = new StringBuilder();
sb.append("Java").append(" 实战").append(2026);
System.out.println(sb); // 输出:Java 实战2026

面试题:String、StringBuilder、StringBuffer 三者区别

  1. String:不可变字符串,拼接效率低,线程安全,适合少量字符串定义;
  2. StringBuilder:可变字符串,拼接效率最高,线程不安全,单线程场景首选
  3. StringBuffer:可变字符串,拼接效率中等,线程安全,多线程并发场景使用

五、高精度数值运算:BigDecimal

Java 中floatdouble存在浮点精度丢失问题,无法用于金融、计费等高精度场景。java.math.BigDecimal专门用来解决浮点数运算精度问题。

1. 构造方法

推荐使用字符串参数构造器,避免浮点初始就丢失精度:

// 推荐写法
BigDecimal num1 = new BigDecimal("0.1");
BigDecimal num2 = new BigDecimal("0.2");

2. 四则运算方法

BigDecimal不支持+、-、*、/运算符,必须调用专用方法:

// 加法
BigDecimal addRes = num1.add(num2);
// 减法
BigDecimal subRes = num1.subtract(num2);
// 乘法
BigDecimal mulRes = num1.multiply(num2);
// 除法:参数(除数,保留小数位数,取舍规则),ROUND_HALF_UP 代表四舍五入
BigDecimal divRes = num1.divide(num2, 2, BigDecimal.ROUND_HALF_UP);
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐