一,包装

1、基础数据类型包装类

1,基本数据类型和包装类型(Object 类)

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

2,==与equals()方法

        2.1, ==  的核心规则

==关系运算符,基本类型比,引用类型比内存地址

它的比较逻辑分两种情况:

基本数据类型(byte/short/int/long/float/double/char/boolean):直接比较变量的实际值是否相等(比如 int a=10; int b=10; a==b 结果为 true)。、

int a = 10;
int b = 10;
System.out.println(a == b); // 输出 true
 

引用数据类型(类 / 接口 / 数组 / String 等)

比较变量中存储的引用地址(即对象在堆内存中的内存地址),只有当两个引用指向同一个对象时,== 才返回 true(这就是你说的 “存储位置是否是同一个” 的场景)。

String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2); // 输出 false

//由于 str1 和 str2 指向不同的内存对象,即使内容相同,== 也会返回 false。


 

特殊情况:字符串常量池

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // 输出 true

//String 类型的字面量(直接赋值)会存储在字符串常量池中,相同的字面量可能指向同一对象:
// 此时 s1 和 s2 引用的是常量池中的同一个对象,因此 == 返回 true。

        2.2,equals()方法的核心规则

在Java中,equals()方法是用于比较两个对象是否相等的关键方法。使用equals()方法需要重写该方法和 hashCde()方法

以下是其核心规则和实现要点:

作用对象:只能用于引用数据类型(基本数据类型没有这个方法)。

equals() 是方法:默认比地址,重写后可比较对象内容(如 String、Integer 等类已重写)

对称性(Symmetry)
对于任何非空引用x和y,x.equals(y)必须与y.equals(x)返回相同的结果。如果x.equals(y)返回true,那么y.equals(x)也必须返回true。

自反性(Reflexivity)
对于任何非空引用x,x.equals(x)必须返回true。即一个对象必须等于其自身。

传递性(Transitivity)
对于任何非空引用x、y和z,如果x.equals(y)返回true且y.equals(z)返回true,那么x.equals(z)也必须返回true。

一致性(Consistency)
对于任何非空引用x和y,多次调用x.equals(y)必须一致地返回相同的结果,前提是对象中用于比较的信息未被修改。

非空性(Non-nullity)
对于任何非空引用x,x.equals(null)必须返回false。即任何对象与null比较时都应返回false。

使用==检查两个对象是否是同一个引用。如果是,直接返回true。

if (this == obj) return true;
 

检查传入的对象是否为null,或是否与当前对象的类型不匹配。

if (obj == null || getClass() != obj.getClass()) return false;
 

将传入的对象转换为当前类型,并逐个比较关键字段是否相等。对于基本类型使用==,对于引用类型使用equals()

MyClass other = (MyClass) obj;
return field1 == other.field1 && Objects.equals(field2, other.field2);
 

        2.3 ==与equals()比较

class student1 {
    private Integer age ;
    private  String name ;   

    @Override   
 public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;

        student1 class1 = (student1) o;
        return age.equals(class1.age) && name.equals(class1.name);
    }

    @Override
    public int hashCode() {
        int result = age.hashCode();
        result = 31 * result + name.hashCode();
        return result;
    }
}
 //重写equals ,hashCode方法
        ==和equals
                        ==               equals
        基本类型        值
        引用类型        内存地址          内容
 

        3 ,hashCode()方法

3.1 hashCode()

hashCode()是Java中的一个本地方法,它的定义在java.lang.Object类中:

//hashCode() 返回的是 int 类型的十进制整数,底层存储为二进制,哈希表常用十六进制处理哈希值;

定义:hashCode()Object 类中定义的一个native 方法,返回一个int 类型的整数

返回一个int 类型的整数(哈希值),这个值代表了对象在内存中的 “哈希特征”,主要用于哈希表(比如 HashMapHashSetHashTable 等 )中快速定位对象,提升查找效率。

使用hashCode()方法需要重写该方法:

因为查询的结果的默认是改数据的内存地址没有比较性

3.2equals()和hashCode()区别

equals() 用于比较两个对象的内容是否相等。默认情况下,Object 类中的 equals() 方法比较的是对象的内存地址(即引用是否相同),但可以通过重写该方法来实现基于对象属性的逻辑比较。

hashCode() 返回对象的哈希码值,用于支持哈希表(如 HashMap、HashSet)的高效操作。哈希码是一个整数,用于快速定位对象在哈希表中的存储位置。

如果两个对象equals相等,那么这两个对象的HashCode一定也相同,
两个对象的hashCode相同,不代表两个对象就相同,只能够说明这两个对象“存放在同一个篮子里”。

4,toString()方法

4.1 toString()方法的核心概念

toString() 本质是一个对象的字符串表示方法,作用是将非字符串类型(如对象、数字、数组等)转换为可读的字符串形式。

  • 在 Java 中:所有类都默认继承自 Object 类,Object 类自带 toString() 方法,默认返回 类名 类的全限定名 + @ + 对象哈希值的十六进制,通常需要重写才能得到有意义的结果。

  • 在 JavaScript 中:几乎所有数据类型(包括基本类型)都有 toString() 方法,默认实现更友好(如数字 123 调用 toString() 会返回 "123"),也可自定义对象的 toString()

4.2 使用 toString()方法

        使用 toString()方法时候一般都需要重写 ,直接输出属性内容

//重写前
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
//重写后
 
@Override
public String toString() {
    return "Person{" +
           "name='" + name + '\'' +
           ", age=" + age +
           '}';
}
 

         JavaScript 中的 toString()

// 数字转字符串
let num = 123;
console.log(num.toString()); // 输出:"123"

// 布尔值转字符串
let bool = true;
console.log(bool.toString()); // 输出:"true"

// 数组转字符串(默认用逗号分隔)
let arr = [1, 2, 3];
console.log(arr.toString()); // 输出:"1,2,3"

二,包装

1包装类

1.1包装类概述

java针对八种基本数据类型定义了相应的包装类,有了类的特点就可以调用类中的方法操作该数据,基本类型对应的包装
类如下

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

2 Integer 类

2.1Integer概述


        Integer封装了一个int类型的属性,并提供了操作该属性的方法


2.2 Integer构造方法

//传入int类型创建Integer类型
publicInteger(intvalue)
//传入String类型创建Integer类型
publicInteger(Strings)
//publicInteger(intvalue):根据int值创建Integer对象(过时)
Integeri1=newInteger(100);
System.out.println(i1);
//publicInteger(Strings):根据String值创建Integer对象(过时)
Integeri2=newInteger("100");
//Integeri2=newInteger("abc");//NumberFormatException
System.out.println(i2);

2.3 Integer成员方法

//以int类型返回该Integer的值
publicintintValue()
//以long类型返回该Integer的值
publiclonglongValue()
//以float类型返回该Integer的值
publicfloatfloatValue()
//以double类型返回该Integer的值
publicdoubledoubleValue()
//返回一个表示该Integer值的String对象
publicStringtoString(int i)
//比较两个Integer对象的值是否相等
publicbooleanequals(Object obj)
//比较两个Integer对象的值是否相等
publicintcompareTo(Integer anotherInteger)
//返回保存指定的String的值的Integer对象
publicstaticIntegervalueOf(String s)
//将字符串参数作为有符号的十进制整数进行解析
publicstaticintparseInt(String s)

2.4 int和String类型的相互转换

   int转换为String 


-方式一:直接在数字后加一个空字符串


-方式二:通过String类静态方法valueOf()

public static void main(String[]args){
//int--->String
int number=100;
//方式1
String s1 = number+"";
System.out.println(s1);
//方式2
//public static String valueOf(inti)
String s2 =String.valueOf(number);
System.out.println(s2);
System.out.println("--------");
}

String转换为int

方式一:先将字符串数字转成Integer,再调用valueOf()方法


方式二:通过Integer静态方法parseInt()进行转换

public class StringToIntDemo {
    public static void main(String[] args) {
        // String--->int
        String s = "100";
        
        // 方式1:String---Integer---int(先转包装类,再转基本类型)
        Integer i = Integer.valueOf(s);
        // public int intValue():将Integer包装类对象转为int基本类型
        int x = i.intValue();
        System.out.println(x); // 输出:100
        
        // 方式2:直接通过静态方法转为int基本类型
        // public static int parseInt(String s)
        int y = Integer.parseInt(s);
        System.out.println(y); // 输出:100
    }
}

2.5自动拆箱和自动装箱

Java 中有基本数据类型(如 int, double, boolean)和对应的包装类(如 Integer, Double, Boolean

基本类型不是对象,不能直接参与面向对象的操作(比如放入集合);包装类是对象,可以,但使用起来不如基本类型方便。

自动装箱:JVM 自动将基本数据类型转换为对应的包装类对象的过程。

自动拆箱:JVM 自动将包装类对象转换为对应的基本数据类型的过程。

自动装箱(Autoboxing)和自动拆箱(Unboxing)

public class AutoBoxingUnboxingDemo {
    public static void main(String[] args) {
        // ------------- 自动装箱 -------------
        // 场景1:基本类型赋值给包装类变量(int -> Integer)
        int basicInt = 100;
        Integer wrapperInt = basicInt; // 自动装箱:等价于 Integer.valueOf(100)
        
        // 场景2:基本类型放入集合(集合只能存对象,自动装箱)
        List<Integer> numList = new ArrayList<>();
        numList.add(200); // 自动装箱:int 200 → Integer 200
        
        // ------------- 自动拆箱 -------------
        // 场景1:包装类赋值给基本类型变量(Integer -> int)
        Integer wrapperNum = new Integer(300);
        int basicNum = wrapperNum; // 自动拆箱:等价于 wrapperNum.intValue()
        
        // 场景2:包装类参与算术运算(自动拆箱为基本类型后计算)
        Integer a = 5;
        Integer b = 10;
        int sum = a + b; // a和b先拆箱为int,再相加,结果赋值给sum
        System.out.println("a + b = " + sum); // 输出:a + b = 15
        
        // 场景3:包装类与基本类型比较(包装类拆箱后比较)
        Integer c = 100;
        int d = 100;
        System.out.println(c == d); // 输出:true(c拆箱为int后和d比较)
    }
}

 自动拆箱和装箱的底层原理:


自动装箱:是编译器调用valueOf将原始类型值转换成对象。


自动拆箱:是编译器调用intValue()这类的方法将对象转换成原始类型值。
 

//注意

//空指针风险:如果包装类对象是null,自动拆箱会抛出NullPointerException:
Integer nullInt = null;
int num = nullInt; // 运行时抛出NullPointerException

//Integer默认缓存-128~127范围内的对象,超出范围后==比较会有坑:
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // true(用缓存对象)

Integer m = 128;
Integer n = 128;
System.out.println(m == n); // false(新创建对象,==比较地址)
System.out.println(m.equals(n)); // true(equals比较值,推荐用这个)

装箱/拆箱

public class WrapperClassDetail {
    public static void main(String[] args) {
        // 1. 自动装箱/拆箱(最常用)
        int a = 10;
        Integer aWrapper = a; // 自动装箱:int → Integer
        int aBasic = aWrapper; // 自动拆箱:Integer → int

        // 2. 字符串转基础类型(核心方法:parseXxx())
        byte b = Byte.parseByte("127"); // byte范围:-128~127
        short s = Short.parseShort("32767"); // short范围:-32768~32767
        int i = Integer.parseInt("2147483647"); // int最大值
        long l = Long.parseLong("9223372036854775807"); // long最大值
        float f = Float.parseFloat("3.14");
        double d = Double.parseDouble("9.8");
        char c = Character.valueOf('A'); // Character无parseChar(),需用valueOf
        boolean bool = Boolean.parseBoolean("true"); // 非"true"(忽略大小写)都返回false

        // 3. 常用常量
        System.out.println("int最大值:" + Integer.MAX_VALUE); // 2147483647
        System.out.println("int最小值:" + Integer.MIN_VALUE); // -2147483648
        System.out.println("byte最大值:" + Byte.MAX_VALUE); // 127

        // 4. 包装类的比较(新手坑!)
        Integer num1 = 127;
        Integer num2 = 127;
        System.out.println(num1 == num2); // true(-128~127缓存池)
        
        Integer num3 = 128;
        Integer num4 = 128;
        System.out.println(num3 == num4); // false(超出缓存池,新建对象)
        System.out.println(num3.equals(num4)); // true(equals比较值,推荐用这个)
    }
}

三,字符串类

1,String类

1.1 String 类的核心特性

首先要明确String类的几个关键属性,这是理解它的基础:

不可变性:String对象一旦创建,其内容(字符序列)就不能被修改。这是String最核心的特性,底层是因为String类被final修饰,且存储字符的数组char[] value也是private final的。

字符串常量池:Java 为了节省内存,会把字符串字面量(如"hello")存储在 JVM 的常量池中,相同字面量只会创建一个对象,复用内存。

值传递:String作为引用类型,但因不可变性,实际使用中表现出 “类似基本类型” 的传递特性。

public class StringBasicDemo {
    public static void main(String[] args) {
        // 1. 字符串常量池复用
        String s1 = "hello";
        String s2 = "hello";
        System.out.println(s1 == s2); // true(指向常量池同一个对象)
        
        // 2. new String会创建新对象(堆内存),不使用常量池
        String s3 = new String("hello");
        System.out.println(s1 == s3); // false(地址不同)
        System.out.println(s1.equals(s3)); // true(值相同,equals比较内容)
        
        // 3. 不可变性:看似修改,实际是创建新对象
        String s4 = "java";
        s4 += "script"; // 不是修改原对象,而是创建新的"javascript"对象
        System.out.println(s4); // 输出:javascript
        // 原"java"对象仍存在,s4只是指向了新对象
    }
}

1.2 String 类的常用方法

public class StringMethodsDemo {
    public static void main(String[] args) {
        String str = "  Hello Java World!  ";
        
        // 1. 去除首尾空格:trim()(JDK11+可用strip(),支持全角空格)
        String trimStr = str.trim();
        System.out.println(trimStr); // 输出:Hello Java World!
        
        // 2. 按指定字符分割:split()
        String[] splitArr = trimStr.split(" ");
        for (String s : splitArr) {
            System.out.println(s); // 依次输出:Hello、Java、World!
        }
        
        // 3. 获取子串:substring(起始索引, 结束索引)(左闭右开)
        String subStr = trimStr.substring(6, 10);
        System.out.println(subStr); // 输出:Java
        
        // 4. 查找字符/字符串位置:indexOf()(找不到返回-1)
        int index = trimStr.indexOf("Java");
        System.out.println(index); // 输出:6
        
        // 5. 替换字符/字符串:replace()
        String replaceStr = trimStr.replace("Java", "Python");
        System.out.println(replaceStr); // 输出:Hello Python World!
        
        // 6. 转换大小写:toUpperCase()/toLowerCase()
        String upperStr = trimStr.toUpperCase();
        System.out.println(upperStr); // 输出:HELLO JAVA WORLD!
        
        // 7. 判断是否包含子串:contains()
        boolean isContain = trimStr.contains("World");
        System.out.println(isContain); // 输出:true
        
        // 8. 判断字符串是否为空/空白:isEmpty()/isBlank()(JDK11+)
        String emptyStr = "";
        System.out.println(emptyStr.isEmpty()); // 输出:true
        String blankStr = "   ";
        System.out.println(blankStr.isBlank()); // 输出:true(JDK11+)
        
        // 9. 获取字符串长度:length()
        int len = trimStr.length();
        System.out.println(len); // 输出:16
    }
}

1.3 字面量和构造方法的区别

字面量(Literal):直接写出值的语法形式(比如 5"hello"true),是创建数据最简洁的方式,属于 “直接量”。

  String str1 = "hello"; 直接给str1赋值

构造方法(Constructor):通过 new 类名() 的方式创建对象 / 数据,是调用类的构造函数来实例化,属于 “显式实例化”。

 String str2 = new String("hello");//创建一个str2的对象

字面量 和  构造方法 的地址

public class LiteralVsConstructor {
    public static void main(String[] args) {
        // 1. 字面量创建 String
        String str1 = "hello";
        // 2. 构造方法创建 String
        String str2 = new String("hello");

        // 核心差异1:内存位置
        // str1 存在【字符串常量池】(节省内存,复用相同值)
        // str2 存在【堆内存】(新对象,即使值相同也会新建)
        String str3 = "hello";
        System.out.println(str1 == str3); // true(常量池复用,地址相同)
        System.out.println(str1 == str2); // false(地址不同)
        System.out.println(str1.equals(str2)); // true(值相同)

        // 核心差异2:性能/内存
        // 字面量:复用常量池,内存占用少、速度快
        // 构造方法:每次new都新建对象,内存占用多、速度慢
    }
}

2StringBuffer类 和StringBuilder类

1.1StringBuffer,StringBuilder类的概述


StringBuffer,StringBuilder 是可变的字符序列,可以把它看成是一个容器能对字符串内容进行增删。

修改操作直接在原对象上进行,不会创建新对象,大幅提升字符串拼接的性能。

1.2 核心特性

可变字符序列:支持增、删、改、查等操作,直接修改内部数组。

效率略低:因为加了同步锁,单线程下性能不如 StringBuilder。

初始容量:默认初始容量是 16,若预估字符串长度,建议指定初始容量(减少数组扩容次数)。

StringBuffer

线程安全:所有方法都用 synchronized 修饰,多线程环境下操作不会出问题。

1.3 StringBuffer类 和StringBuilder类 方法

方法一样名字不同而已

public class StringBufferDemo {
    public static void main(String[] args) {
        // 1. 创建对象(指定初始容量,推荐)
        StringBuffer sb = new StringBuffer(32); // 初始容量32,避免扩容
        
        // 2. 拼接字符串(append,最常用)
        sb.append("Java");
        sb.append(8);
        sb.append(true);
        System.out.println(sb); // 输出:Java8true
        
        // 3. 插入字符串(insert)
        sb.insert(4, "SE"); // 在索引4的位置插入"SE"
        System.out.println(sb); // 输出:JavaSE8true
        
        // 4. 修改字符(setCharAt)
        sb.setCharAt(0, 'j'); // 把索引0的字符改为小写j
        System.out.println(sb); // 输出:javaSE8true
        
        // 5. 删除字符(delete)
        sb.delete(8, 12); // 删除索引8到11的字符(左闭右开)
        System.out.println(sb); // 输出:javaSE8
        
        // 6. 反转字符串(reverse)
        sb.reverse();
        System.out.println(sb); // 输出:8ESavaj
        
        // 7. 转为String类型
        String str = sb.toString();
        System.out.println(str); // 输出:8ESavaj
    }
}
public class StringBuilderDemo {
    public static void main(String[] args) {
        // 创建对象
        StringBuilder sb = new StringBuilder(); // 默认容量16
        
        // 拼接操作(和StringBuffer用法完全一致)
        sb.append("Hello")
          .append(" ")
          .append("World"); // 链式调用,更简洁
        System.out.println(sb); // 输出:Hello World
        
        // 插入
        sb.insert(5, ",");
        System.out.println(sb); // 输出:Hello, World
        
        // 替换
        sb.replace(6, 12, "Java"); // 替换索引6到11的字符为Java
        System.out.println(sb); // 输出:Hello, Java
        
        // 长度和容量
        System.out.println("字符长度:" + sb.length()); // 输出:11
        System.out.println("当前容量:" + sb.capacity()); // 输出:16(未扩容)
    }
}

3.String类 ,StringBuffer类的,StringBuilder类比较

特性	String	           StringBuffer	               StringBuilder
可变性	不可变	            可变	                   可变
线程安全	安全(不可变)	    安全(同步锁)	           不安全
效率	最低(频繁创建对象)	中等(同步开销)	           最高(无同步)
适用场景	少量字符串操作	    多线程环境下的字符串操作	   单线程环境下的字符串操作(推荐)

关键注意点

  1. 扩容机制:当字符长度超过当前容量时,会自动扩容为 原容量 * 2 + 2,并复制原数组内容,频繁扩容会损耗性能,因此预估长度并指定初始容量是优化关键。示例:new StringBuilder(100) 比默认的 16 容量更高效。

  2. 链式调用append()insert() 等方法会返回对象本身(return this),因此支持链式调用(如 sb.append("a").append("b"))。

  3. 线程安全场景:如果多线程同时修改字符串,优先用 StringBuffer;若用 StringBuilder,需手动加锁(如 synchronized)。

Logo

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

更多推荐