源码学习-String类
最近在扫描CodeDex时报了一个不能使用String.intern()的字符串来做锁对象的告警,对这个问题有疑问查了些资料,顺便学习一下String类的源码。
1.类定义 String 被final修饰,是叶子类,不能不继承。实现了Serializable,Comparable,CharSequence 接口
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {...}
Serializable:实现此接口来支持序列化和反序列化,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的
Comparable:实现此接口的对象列表(和数组)可以通过 Collections.sort (和 Arrays.sort )进行自动排序
CharSequence:字符序列,String本质是通过字符数组实现的

2.属性

2.1 value final的数组,用来储存String对象的字符
2.2 hash String对象的HashCode
2.3 serialPersistentFields ?在序列化流协议中String类会被特别包装,String对象会被写入到一个ObjectOutputStream...
3.构造方法

3.1 无参数构造方法默认返回空的字符串,因为String是不可变的,所有没有必要使用此构造函数
1 public String() {
2 this.value = "".value;
3 }
3.2
1 public String(String original) {
2 this.value = original.value;
3 this.hash = original.hash;
4 }
3.3
1 public String(char value[]) {
2 this.value = Arrays.copyOf(value, value.length);
3 }
3.4
public String(byte bytes[]) {//用默认的charset进行decode
this(bytes, 0, bytes.length);
}
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null)
throw new NullPointerException("charset");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charset, bytes, offset, length);
}
3.5 把此String对象的字符copy到dst数组,dst数组中从dstBegin的位置开始放置,此方法不进行任何边界校验
void getChars(char dst[], int dstBegin) {
System.arraycopy(value, 0, dst, dstBegin, value.length);
}
3.6 比较此对象从toffset位置的len长度字符数组是否和other对象的ooffset位置的len长度字符数组是同一个数组
/*
*比较本对象从toffset位置开始的len长度的char数组是否和other对象的ooffset位置开始的len长度的char数组是同一个数组
*/
public boolean regionMatches(int toffset, String other, int ooffset,
int len) {...}
/*
*带boolean参数的表示是否忽略大小写
*/
public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len) {...}
/*
*在equalsIgnoreCase方法中调用了带boolean参数的regionMatches
*/
public boolean equalsIgnoreCase(String anotherString) {
...
}
3.7 是否以特定的字符串开头和结尾
public boolean startsWith(String prefix, int toffset) {...}
public boolean endsWith(String suffix) {...}//endsWith调用的startsWith
3.8 indexOf系列
3.9
public String substring(int beginIndex) {...}
3.10 concat() 本对象之后连接字符串,返回新生成新的字符串
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
3.11 校验字符串是否符合正则表达式
public boolean matches(String regex) {...}
3.12 delimiter做连接符连接字符串列表或数组
public static String join(CharSequence delimiter, CharSequence... elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
// Number of elements not likely worth Arrays.stream overhead.
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
e.g.
public static void main(String[] args)
{
List<String> names=new ArrayList<String>();
names.add("1");
names.add("2");
names.add("3");
System.out.println(String.join("-", names)); String[] arrStr=new String[]{"a","b","c"}; System.out.println(String.join("-", arrStr));
}
输出:

3.13 去除字符串前后空格返回生成的新的子字符串
public String trim() {...}
3.14 格式化字符串
3.14.1 方法签名
public static String format(String format, Object... args) {...}
3.14.2 转换符
|
说 明 |
示 例 |
|
|
%s |
字符串类型 |
"mingrisoft" |
|
%c |
字符类型 |
'm' |
|
%b |
布尔类型 |
true |
|
%d |
整数类型(十进制) |
99 |
|
%x |
整数类型(十六进制) |
FF |
|
%o |
整数类型(八进制) |
77 |
|
%f |
浮点类型 |
99.99 |
|
%a |
十六进制浮点类型 |
FF.35AE |
|
%e |
指数类型 |
9.38e+5 |
|
%g |
通用浮点类型(f和e类型中较短的) |
|
|
%h |
散列码 |
|
|
%% |
百分比类型 |
% |
|
%n |
换行符 |
|
|
%tx |
日期与时间类型(x代表不同的日期与时间转换符 |
3.14.3 e.g.
System.out.println(String.format("现在的时间是:%d-%d-%d %d:%d:%d",2011,1,2,15,29,30));
输出结果:

3.15 valueOf
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
3.16 String类私有维护的String pool 初始化时是空的,当对象s调用intern方法时,如果pool中已存在与之equals为true的t对象,那么池中存在的t对象会被返回,否则新的String对象会被加入到pool中,然后返回这个String对象的引用。
此得出结论:只要s.equals(t),s.intern() == t.intern() 为true
public native String intern();
当使用String s = "abc"方式创建字符串时,字符串会自动加入常量池,而当使用String s = new String("abc")方式创建时,只有调用了s.intern()方法才会把s加入常量池
String pool default size:
7u40之前:1009,
7u40+ to 8:60013
java6的时候存在PermGen区,容易造成oom,java7之后改为存在Heap区
7u02之后可以用-XX:StringTableSize=100003 设置JVM参数
(参考http://java-performance.info/string-intern-in-java-6-7-8/)
源码学习-String类的更多相关文章
- JDK源码学习--String篇(二) 关于String采用final修饰的思考
JDK源码学习String篇中,有一处错误,String类用final[不能被改变的]修饰,而我却写成静态的,感谢CTO-淼淼的指正. 风一样的码农提出的String为何采用final的设计,阅读JD ...
- JDK1.8源码学习-String
JDK1.8源码学习-String 目录 一.String简介 String类是Java中最常用的类之一,所有字符串的字面量都是String类的实例,字符串是常量,在定义之后不能被改变. 二.定义 p ...
- JDK源码之String类解析
一 概述 String由final修饰,是不可变类,即String对象也是不可变对象.这意味着当修改一个String对象的内容时,JVM不会改变原来的对象,而是生成一个新的String对象 主要考虑以 ...
- THINKPHP源码学习--------验证码类
TP3.2验证码类的理解 今天在学习中用到了THINKPHP验证码,为了了解究竟,就开始阅读TP验证码的源码. 源码位置:./ThinkPHP/Library/Think/Verify.class.p ...
- [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析
String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识, ...
- java基础源码 (1)--String类
这个是String类上面的注释,我用谷歌翻译翻译的,虽然有点语法上的问题,但是大概都可以翻译出来 /** * The {@code String} class represents character ...
- JDK源码学习--String篇(四) 终结篇
StringBuilder和StringBuffer 前面讲到String是不可变的,如果需要可变的字符串将如何使用和操作呢?JAVA提供了连个操作可变字符串的类,StringBuilder和Stri ...
- JDK源码学习--String篇(三) 存储篇
在进一步解读String类时,先了解下内存分配和数据存储的. 数据存储 1.寄存器:最快的存储区,位于处理器的内部.由于寄存器的数量有限,所以寄存器是按需分配. 2.堆栈:位于RAM中,但是通过堆栈指 ...
- [Android FrameWork 6.0源码学习] LayoutInflater 类分析
LayoutInflater是用来解析XML布局文件,然后生成对象的ViewTree的工具类.是这个工具类的存在,才能让我们写起Layout来那么省劲. 我们接下来进去刨析,看看里边的奥秘 //调用i ...
随机推荐
- bzoj 1055: [HAOI2008]玩具取名【区间dp】
不难想,就是处理起来比较麻烦 设f[i][j][k]为是否可以把区间(i,j)合并为k,初始状态是f[i][j][s[i]]=1,转移的话另一段枚举长度x,向(i-x,j),(i,j+x)转移 把四个 ...
- bzoj 3961: [WF2011]Chips Challenge【最小费用最大流】
参考:https://blog.csdn.net/Quack_quack/article/details/50554032 神建图系列 首先把问题转为全填上,最少扣下来几个能符合条件 先考虑第2个条件 ...
- 微信支付接口调用问题(android正常,iphone调不起)
转自:http://blog.csdn.net/tt123123/article/details/53897035 碰到的问题 :根据微信提供的示例代码(ASP.NET),配置好一切后, 用andro ...
- socket servlet webservice 区别及使用场景
原文地址: http://blog.csdn.net/sdjkjsdh/article/details/51569481 1. Socket:使用TCP/IP或者UDP协议在服务器与客户端之间进行传输 ...
- 【react native】rn踩坑实践——从输入框“们”开始
因为团队技术栈变更为react native,所以开始写起了rn的代码,虽然rn与react份数同源,但是由于有很多native有关的交互和变动,实际使用还是碰到蛮多问题的,于是便有了这个系列,本来第 ...
- Poj 2112 Optimal Milking (多重匹配+传递闭包+二分)
题目链接: Poj 2112 Optimal Milking 题目描述: 有k个挤奶机,c头牛,每台挤奶机每天最多可以给m头奶牛挤奶.挤奶机编号从1到k,奶牛编号从k+1到k+c,给出(k+c)*(k ...
- Lync客户端证书安装
安装完Lync客户端后,运行时Lync客户端时,报出如下错误: [原因解析] Lync客户端没有正确安装CA证书链. [解决办法] 第一种方法:将计算机加入域. 第二种方法:不加入域的处理方法: 1. ...
- 树莓派 VNC 远程桌面 同一个桌面
如何在ssh登录的情况下配置好vino 1.传输文件 2.ssh sudo dpkg -i ~/swap/deb/tight* sudo cp ~/swap/vino.desktop /etc/xdg ...
- (五)SpringIoc之Bean的作用域
此文转自 https://blog.csdn.net/icarus_wang/article/details/51586776# 有状态bean和无状态bean请看 https://blog.csdn ...
- (四)SpringIoc之Bean装配
在pom.xml的依赖 <dependencies> <!--测试包--> <dependency> <groupId>junit</groupI ...