Java源码赏析(三)初识 String 类
由于String类比较复杂,现在采用多篇幅来讲述
这一期主要从String使用的关键字,实现的接口,属性以及覆盖的方法入手。省略了大部分的字符串操作,比如split()、trim()、replace()、contains()、matches()等。
在Java源码赏析(五)中,会增加对String类中的字符串操作进行详细描述,敬请期待。
今后,还会介绍StringBuffer、StringBuilder两个类。
/**
* 精简的String结构,便于我们初步的理解, 省略了大部分构造方法和字符串操作
* 使用了final关键字,说明此类是最终类,无法继承
* 实现了序列化接口,排序接口,CharSequence接口
*/
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; private int hash; // Default to 0 private static final long serialVersionUID = -6849794470754667710L; /** 指明需要实例化的字段 */
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0]; /** 省略CaseInsensitiveComparator()的实现,主要是用于按ASCII码的排序规则进行排序 */
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator(); /** 实现Comparable<String>,可用于集合类的排序功能 */
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value; int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
} /** 覆盖hashCode(),可以用于switch以及Map,Set的查询 */
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
} /** 覆盖父类equal(),实现了值比较 */
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
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;
} /** 覆盖父类toString() */
public String toString() {
return this;
} /**
* 实现CharSequence接口
* 共有length(), charAt(int index), subSequence(int beginIndex, int endIndex) 等
* 在实现subSequence()方法时使用了String中substring()方法
*/ /** 获取字符串长度 */
public int length() {
return value.length;
} /** 获取index位置的字符 */
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
} /** 获取字符串子串 */
public CharSequence subSequence(int beginIndex, int endIndex) {
return this.substring(beginIndex, endIndex);
} /** 从索引位置beginIndex到endIndex处获取子串 */
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);
}
}
/** 若不存在,将字符串存入常量池并返回在常量池的引用;若已存在,则直接返回字符串的引用 */
public native String intern();
阅读一个类的源码,首先要定性。
1. 它是一个final的类,说明不可继承,
2. value为final,说明值创建后不可更改。
好处在于简单(不用考虑并发问题),安全(不用考虑子类、值被修改等问题),高效(由于不可变可以设计常量池的处理)等。
大概了解了String的属性和方法,我们回顾源码赏析一、二的内容,发现前两篇内容无一不体现在这个类中。希望大家可以结合前两篇来看待这个经典的类。
一、Object中的重写方法 equals()、 hashCode()、 toString()
二、常见的接口Serializable, Comparable的实现
除了上面两点之外,还实现了CharSequence这个字符串的通用接口。StringBuffer、StringBuilder也实现了此接口。
还有需要注意的一点是,字符串拥有 “操作符重载” 了 "+"。我们可以方便的使用这个操作符进行一些处理。
比如 连接字符串
String a = "hello";
String b = ", world";
//输出 hello, world
//
System.out.println(a + b);
注, “+” 最后不好放在for循环之中(第一种写法创建了100个对象),而第二种只创建了1个对象
String s = new String();
for(int i=0; i<100; i++) {
s = s + i;
}
//等效于
StringBuilder s1 = new StringBuilder();
for(int i=0; i<100; i++) {
StringBuilder one = new StringBuilder(i);
s1.append(one).toString();
}
//高效写法
StringBuilder s2 = new StringBuilder();
for(int i=0; i<100; i++) {
s2 = s2.append(i);
}
同理,频繁使用的String也可以直接写出 String s3 = "a";,不需要new出来 String s4 = new String("a");,这样能让这个值存在于常量池里(可以当成存在缓存)。
Java源码赏析(三)初识 String 类的更多相关文章
- Java源码赏析(五)再识 String 类
在 Java源码赏析(三)初识 String 类 中,我们已经大概理解了String的接口,接下来我们描述一下String的常用工具方法. /** * 为了精简的String结构,之前提到的方法省 ...
- Java源码赏析(六)Class<T> 类
目的 Class 类是每一个程序员都必须了解的,也是使用反射机制的基础. 这篇文章将Class 类的公共方法大致介绍了一遍(省略了安全.枚举.断言.注解相关代码). 代码 package java.l ...
- Mybatis源码解析(三) —— Mapper代理类的生成
Mybatis源码解析(三) -- Mapper代理类的生成 在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...
- Java源码赏析(四)Java常见注解
元注解 @Target :标识注解的目标,默认为所有 ElementType.TYPE(用于类) ElementType.FIELD(用于域,包括enum) ElementType.METHOD(用于 ...
- Java 源码赏析 - java.lang - Void
被人鄙视了,于是也来读读源码... package java.lang; /** * The Void class is an uninstantiable placeholder class to ...
- Java源码赏析(六)Java String 三顾
在大致了解了String之后,可能有的读者发现了,我们并没有谈到CharSequence接口. 原因是在这一节,CharSequence要和StringBuilder(Java1.5).StringB ...
- Java源码赏析(一)Object 类
写这个系列的原因,其实网上已经有无数源码分析的文章了,多一篇不多,少一篇不少,但为什么还要写这部分文章呢?于私,其一,上班族已经很久没有打过完整的一整段有意义的话,算是锻炼个人的书写.总结能力,其二, ...
- Java源码赏析(二)Java常见接口
一.Comparable接口 package java.lang; import java.util.*; public interface Comparable<T> { /** * i ...
- [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析
String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识, ...
随机推荐
- golang rpc demo
RPC工作流程图 1.调用客户端句柄:执行传送参数 2.调用本地系统内核发送网络消息 3.消息传送到远程主机 4.服务器句柄得到消息并取得参数 5.执行远程过程 6.执行的过程将结果返回服务器句柄 7 ...
- 基于 abp vNext 微服务开发的敏捷应用构建平台 - 文章目录
系列文章: <基于 abp vNext 微服务开发的敏捷应用构建平台 - 设计构想> [点击查看] <基于 abp vNext 微服务开发的敏捷应用构建平台 - 文章目录> [ ...
- 你还在用a标签吗?——用button替代a
前言:a标签,不止你在用,我也在用.但某些时候我们可以考虑用button替代a. 在多页应用中,a标签很常见,我们常用来作为一个普通超链接,进行页面跳转. 而在单页应用中,我们使用路由进行页面切换,a ...
- element-ul二次封装table表格
在项目中el的表格使用的地方太多了,若不进行封装,使用的时候页面会显得非常的冗余且难以维护,有时表格样式还不能做到一致:今天分享一个在工作中封装的表格 由于大多代码都在页面有介绍,就不在外面解释了 一 ...
- android开发之dip,dp与px像素之间的转换工具,可能用的不多,但是有总比没有好吧。
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985,转载请说明出处. 下面是介绍: 免积分下载地址:http://download.csdn.net/de ...
- C#垃圾代码随机生成器
直接上代码: using UnityEngine; using System.Collections.Generic; using UnityEditor; using System.IO; usin ...
- Transform与Vector3 的API
Transform.InverseTransformDirection(Vector3 direction) Vector3.ProjectOnPlane(Vector3 vector, Vector ...
- 深入了解Netty【一】BIO、NIO、AIO简单介绍
引言 在Java中提供了三种IO模型:BIO.NIO.AIO,模型的选择决定了程序通信的性能. 1.1.使用场景 BIO BIO适用于连接数比较小的应用,这种IO模型对服务器资源要求比较高. NIO ...
- Java使用POI的SXSSFWorkbook与HSSFWorkbook导出复杂表头
一.HSSFWorkbook与SXSSFWorkbook的区别: HSSFWorkbook是对Excel2003以前的版本进行操作的,即后缀名为.xls SXSSFWorkbook时对Excel200 ...
- vueRooter的总结
这一周学习了Vue的脚手架的结构,最重要的router 该进行总结和回忆了. 1首先是router的安装,用npm命令npm install vue-router --save 2装完后,在main. ...