目录
思维脑图
思维脑图:要学习的知识和心理路程
规划知识体系。
笔记
首先,在开始今天的学习前,我先把我的笔记放在这里,大家可以看一眼,对今天所学内容有个初步理解。
git代码笔记链接https://gitee.com/Simon_7758521/simon.-test-001
包装类
回忆:基本数据类型和引用数据类型
为什么要有包装器语言?
java是面向对象语言,要面向对象处理。
//自动装箱---装一个箱子里了。范围(-128,+127),大小相同装为一箱
//因为在这个范围内的整数常见,所以有一个运行常量池用来缓存(-128,127)内的值。
Integer c=10;
Integer d=10;
System.out.println("c==d:"+(c==d));//true
//在范围且不相等
Integer c1=-128;
Integer d1=127;
System.out.println("c1==d1:"+(c1==d1));//false
//不在范围但相等
Integer c2=128;
Integer d2=128;
System.out.println("c2==d2:"+(c2==d2));//false
Object类
是所有类的超级父类。可以被所以类继承
类中定义的所有非私有方法,其他类都可使用
常用方法:
toString();:输出对象时,自动调用对象.toString();
equals();对象.equals(另一个对象);判断传入的两个对象地址值是否相等。
getClass();不可以重写
Java 中 Object 类的一个方法,用于返回对象运行时的类(Class 对象)。
它的使用场景通常是在需要获取对象实际类型信息的时候
String类
介绍:
引用数据类型的一种
用于表示字符串
是java中最常用的类之一
String对象是不可变的,一但创建他们的值就不可被修改-----li05
等同于:数组的长度一旦创建就不能被改变(堆内存的值不可更改)
String s1=new String("123");
System.out.println(s1);//相当于输出s1.toString();
s1="345";
我们只是创造了一个新的空间,改变了指向(具体可看内城图)
常量池---------节省内存,提高性能
String常量池
在我们创建时,会先检查是否有相同字符串,若有则返回该字符串的引用。(里面存放的是之前创的)
字符串常量池与其他对象常量一样,都储存在堆内存中
如何放入常量池:----通过new出来的对象直接在堆内存中new出一个对象,不加intern();不会放入常量池也不会从常量池中取
//1: String str1="Hello";
//2: String str2=new String("!").intern();
+号链接的结果也被当做常量//String s1="a"+"b"; 但如果链接的是两个对象,则是false: String st5=st1+st2;
Integer常量池
存放的是固定的[-128,127]无论用不用
一、从基本类型到包装类:Java 的 "装箱魔法"
我们都知道 Java 有 8 种基本数据类型,比如 int、double 等,它们不是对象。但 Java 是面向对象的语言,很多场景下我们需要将这些基本类型当作对象来处理。这就像我们去旅行时,总要把零散的物品装进行李箱一样,Java 为每种基本类型都准备了一个 "行李箱"—— 包装类。
public class Test {
public static void main(String[] args) {
int i=10;
//i.toString();
//将基本数据类型的值转换为对象
//int->Integer类
Integer integer=new Integer(i);
String sI= integer.toString();
System.out.println("sI:"+sI);
//包装类能够存放静态成员
System.out.println(integer.MAX_VALUE);
System.out.println(integer.MIN_VALUE);
//包装器类型能够提供一些常用的方法
int min =Integer.min(10, 20);
System.out.println("min:"+min);
//将String类型的值转成int
String s="100";
int iS=Integer.parseInt(s);
}
}
这段代码是对我们包装类的一个简单介绍,方便大家开展接下来的学习。
1.1 手动装箱:原始的包装方式
在 JDK 1.5 之前,我们需要手动完成装箱操作:
int i = 10;
// 手动装箱:把基本类型int包装成Integer对象
Integer integer = new Integer(i);
这就像我们亲手把衣服折叠好放进箱子里,虽然有点麻烦,但很直观。
//基本数据类型-栈空间
int a=10;
int b=10;
System.out.println("a==b:"+(a==b));//true
//引用数据类型-对象-栈空间-堆空间
//手动装箱
Integer a1=new Integer(10);
Integer b1=new Integer(10);
System.out.println("a1==b1:"+(a1==b1));//false
//输出哈希值不等
System.out.println(a1);
System.out.println(b1);
System.out.println("a1的哈希值:"+System.identityHashCode(a1));//a1的哈希值:989110044
System.out.println("b1的哈希值:"+System.identityHashCode(b1));//b1的哈希值:424058530
1.2 自动装箱:JDK 的语法糖
JDK 1.5 引入了自动装箱特性,让代码更简洁:
// 自动装箱:编译器帮我们完成了包装工作
Integer c = 10;
Integer d = 10;
大家注意看这个有趣的现象:
System.out.println("c == d: " + (c == d)); // 输出true
为什么两个不同的对象用==
比较会返回 true 呢?这就要提到 Integer 的常量池机制了。
1.3 Integer 常量池:共享的 "常用物品"
Java 设计者发现,-128 到 127 之间的整数在日常开发中使用频率极高。为了提高效率,他们建立了一个 "共享储物柜"—— 常量池,提前缓存了这个范围内的 Integer 对象。
// 在常量池范围内且值相等
Integer c = 10;
Integer d = 10;
System.out.println("c == d: " + (c == d)); // true
// 在常量池范围内但值不相等
Integer c1 = -128;
Integer d1 = 127;
System.out.println("c1 == d1: " + (c1 == d1)); // false
// 超出常量池范围
Integer c2 = 128;
Integer d2 = 128;
System.out.println("c2 == d2: " + (c2 == d2)); // false
这就像图书馆里的热门书籍,图书馆会多准备几本供大家共享,而冷门书籍可能只有一本,需要时才会购买新的。
大家可以具体看内存图:
1.4 自动拆箱:从箱子里取东西
有装箱就有拆箱,自动拆箱让包装类可以自动转换为基本类型:
Integer o = 10;
int io = o; // 自动拆箱
注意:自动装箱 / 拆箱不支持跨类型转换:
Double a = 1; // 错误!不能把int直接装箱为Double
这就像你不能把衣服放进食品保鲜盒里一样,类型必须匹配。
1.5 Integer 的实用方法
Integer 类提供了很多实用方法,比如类型转换:
// 字符串转整数
String s = "100";
int iS = Integer.parseInt(s);
// 进制转换
System.out.println("十进制: " + Integer.toString(123, 10));
System.out.println("二进制: " + Integer.toString(123, 2));
System.out.println("十六进制: " + Integer.toString(123, 16));
这些方法不会改变原始值,只是返回一个新的结果,就像复印文件不会改变原件一样。
二、Object 类:Java 世界的老祖宗
在 Java 中,所有类都直接或间接继承自 Object 类,它是整个类层次结构的根。就像家族中的老祖宗,Object 类定义的方法,所有后代类都可以使用。
2.1 toString ():对象的自我介绍
Object 类的 toString () 方法默认返回对象的地址信息,这通常没什么用。我们可以重写它,让对象能 "自我介绍":
public class Student {
private String name;
private int age;
@Override
public String toString() {
return "我叫" + name + ",今年" + age + "岁";
}
}
当我们打印对象时,会自动调用 toString () 方法:
Student s = new Student("张三", 20);
System.out.println(s); // 输出:我叫张三,今年20岁
2.2 equals ():对象的身份验证
Object 类的 equals () 方法默认比较对象地址,但我们通常需要比较对象内容:
@Override
public boolean equals(Object obj) {
if (obj instanceof Student) {
Student other = (Student) obj;
// 比较姓名和年龄是否相同
return this.name.equals(other.name) && this.age == other.age;
}
return false;
}
使用示例:
Student s1 = new Student("张三", 20);
Student s2 = new Student("张三", 20);
System.out.println(s1.equals(s2)); // 输出true
这就像两个人虽然是不同的个体,但如果姓名、年龄等信息都一样,我们可能会认为他们是同一个人。
2.3 getClass ():获取对象的类型
getClass ()方法返回对象的运行时类型,这个方法不能被重写:
if (obj.getClass() == Student.class) {
System.out.println("这是一个Student对象");
}
这就像每个人都有自己的身份证,getClass () 方法就是获取对象的 "身份信息"。
三、String 类:不可变的字符序列
String 类是 Java 中最常用的类之一,用于表示字符串。它有一个非常重要的特性:不可变性。
3.1 字符串的不可变性
一旦创建了 String 对象,它的值就不能被改变:
String s1 = "123";
s1 = "345"; // 不是修改原有字符串,而是创建了新字符串
内存图:
这就像我们写在纸上的字,不能直接修改,只能重新写一张。这种设计让字符串更安全,也更高效。
3.2 字符串常量池:字符串的共享空间
为了节省内存,Java 为字符串设立了常量池:
// str1和str2指向常量池中的同一个对象
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // true
// 通过new创建的字符串不使用常量池
String str3 = new String("Hello");
System.out.println(str1 == str3); // false
// 使用intern()方法将字符串放入常量池
String str4 = new String("Hello").intern();
System.out.println(str1 == str4); // true
这就像图书馆的藏书,如果每个人都将自己的看完的书本收纳如图书馆,那么后面来的人便不用再买书,直接从图书馆获取即可。
3.3 字符串拼接的奥秘
字符串拼接有一些有趣的特性:
//面试进阶问法
String st1="a";
String st2="b";
String st3="ab";
String st4="a"+"b";
String st5=st1+st2;
在掌握了上述字符串常量池的特性后你能否应对面试官的询问?
//问:st3==st4吗?
//问:st4==st5吗?
//问:st3==st4吗?
System.out.println(st3==st4);//true ----------- +号链接的结果也被当做常量
//问:st4==st5吗?
System.out.println(st4==st5);//false------------- 但如果链接的是两个对象,则是false
如果,我创建一个st6:
String st6=(st1+st2).intern();
System.out.println(st4==st6);//请问结果是false还是true
如果面试官问大家这个问题,大家是否能解答呢?