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类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识, ...
随机推荐
- 面试28k职位,老乡面试官从HashCode到HashMap给我讲了一下午!「回家赶忙整理出1.6万字的面试材料」
作者:小傅哥 博客:https://bugstack.cn 目录 一.前言 二.HashCode为什么使用31作为乘数 1. 固定乘积31在这用到了 2. 来自stackoverflow的回答 3. ...
- SpringBoot项目 使用Jenkins进行自动化部署 gitlab打tag 生产测试环境使用 含配置中心
脚本 node('master') { def mvnHome = tool 'maven11-free' def gitUrl = "http://gitlab.wdcloud.cc:10 ...
- google protocol buffer——protobuf的使用特性及编码原理
这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们展示了 ...
- Netty之旅二:口口相传的高性能Netty到底是什么?
高清思维导图原件(xmind/pdf/jpg)可以关注公众号:一枝花算不算浪漫 回复netty01即可. 前言 上一篇文章讲了NIO相关的知识点,相比于传统IO,NIO已经做得很优雅了,为什么我们还要 ...
- spring如何创建RESTful Service
REST REST,是指REpresentational State Transfer,有个精辟的解释什么是RESTful, 看url就知道要什么 看method就知道干什么 看status code ...
- Android开发之AlertDialog警告提示框删除与取消 详解代码
package cc.jiusansec.www; import android.app.Activity; import android.app.AlertDialog; import androi ...
- Fitness - 05.11
倒计时234天 从本周开始改变运动模式 跑步换到每周二.四.六进行. 每周一.三.五增加瑜伽的练习,周日山地车骑行~~~~ 久违的瑜伽课,瑜伽老师居然是男的,第一次看到这么柔软的男生~! 平时感觉不到 ...
- vue-devtools-4.1.4_0.crx及Vue.js not detected的问题
谷歌-更多工具-扩展程序 Vue.js not detected的问题
- Java实现内嵌浏览器
创建项目 ----> 导入需要的jar ----> 代码实现 需要的jar: https://pan.baidu.com/s/1MEZ1S0LnKSMGQm24QWgmCw 代码: ...
- Python多行缩进反向缩进快捷键
1.Python增加缩进快捷键:Ctrl+Alt+] 或tab键或shift+tab键 2.Python减少缩进快捷键:Ctrl+Alt+[