网站首页 > java教程 正文
说到Java源码,我相信小伙伴们或多或少都有接触,比如util包中常见的ArrayList、HashMap、LinkedHashMap,还有前面我们学过的多线程相关类,如:Executors、CountDownLatch、CyclicBarrier,又或者是lang包中的Object、Integer、String、Thread等。
这些都是我们比较常见的类,不过对于他们的实现原理,我们有时候并不能说出个所以然来,甚至有些人写了四五年代码,连最最常见的String如何实现都没有看过,还总是抱怨每天总是搬砖、前途迷茫。说实话,学习源码并不仅仅是为了应对面试,更重要的是我们通过阅读源码的过程,学习它的设计思想,这种思想在我们项目中完全可以实践出来。
总结来说,阅读源码有以下几点好处:
- 学习优秀的设计思想;
- 增加面试实力,横扫一片;
- 代码日常评审时大秀肌肉。
二、String源码分析
String在日常开发中的使用频率相当高,所以今天就要扒开String的外衣,看看它究竟为什么这么受欢迎,本章为。
2.1 不可变性
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
...
}
从代码中可以看到,String类由final关键字修饰,这也意为着String类不可被继承,创建后不能被修改。
String类同时实现了三个接口:
- Serializable:实现序列化,标记接口,用于标识序列化,未实现该接口无法被序列化。
- Comparable:对两个实例化对象比较大小
- CharSequence:String本质是个char数组,该接口为只读的字符序列。
2.2 成员变量
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
?
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
?
/**
* Class String is special cased within the Serialization Stream Protocol.
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
String 中保存数据的是一个 char 的数组 value, value 同样也是被 final 修饰,这就意外着该数组无法被修改,同时value 的访问权限是 private ,外部访问不到该变量,String 也没有提供 value 的相关操作方法,所以 value 一旦生成就无法再被被修改。
2.3 常见方法
接下来看String类中几个常见的方法是如何实现的
- equals
public boolean equals(Object anObject) {
//内存地址是否相同
if (this == anObject) {
return true;
}
//目标对象是否为String类,不是的话直接返回false
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
//判断两者长度是否相等
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//比较两者中每一个字符是否相等
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
- 截取字符串:substring
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
通过源码可以看到,对于满足条件的起始/终止下标,该方法会调用new String()构成器,而该构造器最终通过System.arraycopy生成一个新的字符串返回,这也就意为着该方法并不会在原有字符串基础上进行修改。
同样的,我们可以查看replace、concat等方法源码,他们都会不会修改原有字符串,而是会生成一个新的字符串对象返回,这也是String不可变的表现。
作者:JavaGieGie
链接:https://juejin.cn/post/7011887760587882527
- 上一篇: 对象的内存布局,怎样确定对象的大小
- 下一篇: 懵了!面试官问我:String 长度有限制吗?是多少?
猜你喜欢
- 2024-11-27 正确理解和使用JAVA中的字符串常量池
- 2024-11-27 面试Java岗 Integer和String必问知识点,你必须精通
- 2024-11-27 JAVA基础&String&StringBuffered&StringBuilder
- 2024-11-27 Java 17 I/O StringWriter 篇
- 2024-11-27 高端面试必备:一个Java对象占用多大内存?
- 2024-11-27 Java基础类String学习分析
- 2024-11-27 懵了!面试官问我:String 长度有限制吗?是多少?
- 2024-11-27 对象的内存布局,怎样确定对象的大小
- 2024-11-27 「Java技术探索」带你进入String类的易错点和底层本质分析
- 2024-11-27 面试中被问到HashMap的结构,1.7和1.8有哪些区别,彻底懵了
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)