String源码解析(二)
方法的主要功能看代码注释即可,这里主要看函数实现的方式。
1.getChars(char dst[], int dstBegin)
/**
* Copy characters from this string into dst starting at dstBegin.
* This method doesn't perform any range checking.
*/
void getChars(char dst[], int dstBegin) {
System.arraycopy(value, 0, dst, dstBegin, value.length);
}
该方法将调用该方法的字符串拷贝到字符数组dst中,从dstBegin开始存放,拷贝length字节。
该方法默认是包范围的,而且不进行边界检查。
2.getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
/**
* Copies characters from this string into the destination character
* array.
* <p>
* The first character to be copied is at index {@code srcBegin};
* the last character to be copied is at index {@code srcEnd-1}
* (thus the total number of characters to be copied is
* {@code srcEnd-srcBegin}). The characters are copied into the
* subarray of {@code dst} starting at index {@code dstBegin}
* and ending at index:
* <blockquote><pre>
* dstBegin + (srcEnd-srcBegin) - 1
* </pre></blockquote>
*
* @param srcBegin index of the first character in the string
* to copy.
* @param srcEnd index after the last character in the string
* to copy.
* @param dst the destination array.
* @param dstBegin the start offset in the destination array.
* @exception IndexOutOfBoundsException If any of the following
* is true:
* <ul><li>{@code srcBegin} is negative.
* <li>{@code srcBegin} is greater than {@code srcEnd}
* <li>{@code srcEnd} is greater than the length of this
* string
* <li>{@code dstBegin} is negative
* <li>{@code dstBegin+(srcEnd-srcBegin)} is larger than
* {@code dst.length}</ul>
*/
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
该方法先对srcBegin、srcEnd进行了边界检查,然后调用System.arraycopy实现复制。
3.getBytes()
/**
* Encodes this {@code String} into a sequence of bytes using the named
* charset, storing the result into a new byte array.
*
* <p> The behavior of this method when this string cannot be encoded in
* the given charset is unspecified. The {@link
* java.nio.charset.CharsetEncoder} class should be used when more control
* over the encoding process is required.
*
* @param charsetName
* The name of a supported {@linkplain java.nio.charset.Charset
* charset}
*
* @return The resultant byte array
*
* @throws UnsupportedEncodingException
* If the named charset is not supported
*
* @since JDK1.1
*/
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, value, 0, value.length);
}
/**
* Encodes this {@code String} into a sequence of bytes using the given
* {@linkplain java.nio.charset.Charset charset}, storing the result into a
* new byte array.
*
* <p> This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement byte array. The
* {@link java.nio.charset.CharsetEncoder} class should be used when more
* control over the encoding process is required.
*
* @param charset
* The {@linkplain java.nio.charset.Charset} to be used to encode
* the {@code String}
*
* @return The resultant byte array
*
* @since 1.6
*/
public byte[] getBytes(Charset charset) {
if (charset == null) throw new NullPointerException();
return StringCoding.encode(charset, value, 0, value.length);
}
/**
* Encodes this {@code String} into a sequence of bytes using the
* platform's default charset, storing the result into a new byte array.
*
* <p> The behavior of this method when this string cannot be encoded in
* the default charset is unspecified. The {@link
* java.nio.charset.CharsetEncoder} class should be used when more control
* over the encoding process is required.
*
* @return The resultant byte array
*
* @since JDK1.1
*/
public byte[] getBytes() {
return StringCoding.encode(value, 0, value.length);
}
这个三个方法都是将String编码为byte序列存储到byte数组后返回,都是调用StringCode.encode方法实现。
方法的不同之处是字符集指定方式,分别是字符集名字、字符集和平台默认字符集。
4.equals(Object anObject)
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
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;
}
此方法将字符串与指定的对象anObject比较。
从代码中我们可以看出:
先使用==进行判断,这是对字节码进行判断,如果二者相同则返回true;
然后再判断anObject是否是一个String的一个实例,这是继续向下比较的条件;
如果anObject是一个String实例,则转换为String;
接下来比较两个字符串的长度,如果长度相等,再将两个字符串转换为char数组,对比相应位置上的元素。
只有类型、长度和元素都相等的情况下才返回true。
5.contentEquals(StringBuffer sb)
/**
* Compares this string to the specified {@code StringBuffer}. The result
* is {@code true} if and only if this {@code String} represents the same
* sequence of characters as the specified {@code StringBuffer}. This method
* synchronizes on the {@code StringBuffer}.
*
* @param sb
* The {@code StringBuffer} to compare this {@code String} against
*
* @return {@code true} if this {@code String} represents the same
* sequence of characters as the specified {@code StringBuffer},
* {@code false} otherwise
*
* @since 1.4
*/
public boolean contentEquals(StringBuffer sb) {
return contentEquals((CharSequence)sb);
}
该方法将字符串与一个StringBuffer对象进行比较,具体的比较操作是调用contentEquals()方法实现的。
6.contentEquals(CharSequence cs)
/**
* Compares this string to the specified {@code CharSequence}. The
* result is {@code true} if and only if this {@code String} represents the
* same sequence of char values as the specified sequence. Note that if the
* {@code CharSequence} is a {@code StringBuffer} then the method
* synchronizes on it.
*
* @param cs
* The sequence to compare this {@code String} against
*
* @return {@code true} if this {@code String} represents the same
* sequence of char values as the specified sequence, {@code
* false} otherwise
*
* @since 1.5
*/
public boolean contentEquals(CharSequence cs) {
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// Argument is a String
if (cs instanceof String) {
return equals(cs);
}
// Argument is a generic CharSequence
char v1[] = value;
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
}
}
return true;
}
该方法的参数是一个字符序列cs,只进行内容的比较:
如果cs是AbstractStringBuilder实例但不是StringBuffer实例,直接调用方法nonSyncContentEquals()进行比较;
如果cs是StringBuffer实例,也是调用方法nonSyncContentEquals()实现比较,但是需要synchronized同步;
如果cs不是AbstractStringBuilder实例,但是一个String实例,调用方法equals()实现比较;
如果cs只是一个普通的字符序列,比较序列长度和对应位置字符相等就可以了。
7.nonSyncContentEquals(AbstractStringBuilder sb)
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
char v1[] = value;
char v2[] = sb.getValue();
int n = v1.length;
if (n != sb.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != v2[i]) {
return false;
}
}
return true;
}
这是一个私有方法。
从方法名就可以看出这是一个非同步比较方法,参数是AbstractStringBuilder类型。
比较时,也只是从AbstractStringBuilder取出字符数组,然后和调用者的字符数组进行比较。
综上,我们可以看到,不同的equals函数实现不同的判等方式,比如:
只进行存储内容的判断,而不比较类类型;
不但进行类型的判断,还要对存储内容进行判断;
...
String源码解析(二)的更多相关文章
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- Sentinel源码解析二(Slot总览)
写在前面 本文继续来分析Sentinel的源码,上篇文章对Sentinel的调用过程做了深入分析,主要涉及到了两个概念:插槽链和Node节点.那么接下来我们就根据插槽链的调用关系来依次分析每个插槽(s ...
- RxJava2源码解析(二)
title: RxJava2源码解析(二) categories: 源码解析 tags: 源码解析 rxJava2 前言 本篇主要解析RxJava的线程切换的原理实现 subscribeOn 首先, ...
- jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...
- Common.Logging源码解析二
Common.Logging源码解析一分析了LogManager主入口的整个逻辑,其中第二步生成日志实例工厂类接口分析的很模糊,本随笔将会详细讲解整个日志实例工厂类接口的生成过程! (1).关于如何生 ...
- element-ui 源码解析 二
Carousel 走马灯源码解析 1. 基本原理:页面切换 页面切换使用的是 transform 2D 转换和 transition 过渡 可以看出是采用内联样式来实现的 举个栗子 <div : ...
- iOS即时通讯之CocoaAsyncSocket源码解析二
原文 前言 本文承接上文:iOS即时通讯之CocoaAsyncSocket源码解析一 上文我们提到了GCDAsyncSocket的初始化,以及最终connect之前的准备工作,包括一些错误检查:本机地 ...
- erlang下lists模块sort(排序)方法源码解析(二)
上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...
- ArrayList源码解析(二)
欢迎转载,转载烦请注明出处,谢谢. https://www.cnblogs.com/sx-wuyj/p/11177257.html 自己学习ArrayList源码的一些心得记录. 继续上一篇,Arra ...
- React的Component,PureComponent源码解析(二)
1.什么是Component,PureComponent? 都是class方式定义的基类,两者没有什么大的区别,只是PureComponent内部使用shouldComponentUpdate(nex ...
随机推荐
- (转)Python 遍历List三种方式
转自: http://www.cnblogs.com/pizitai/archive/2017/02/14/6398276.html # 方法1 print '遍历列表方法1:' for i in l ...
- memcached分布式缓存
1.memcached分布式简介 memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能.Memcache集群主机不能够相互通信传输数据,它的“分布式”是基于客户端的程序逻辑算 ...
- Linux常用命令快查
一.读取配置文件中某一个变量的值 假如有一个配置文件dubbo.properties,需要读取dubbo.application.name的值: dubbo.application.name=book ...
- js中元素(图片)切换和隐藏显示问题
这个知识点其实也简单,(当然是在理清思路的情况下),在没预习的情况下听的还真是艰难,上课以来唯一的一次懵逼了一天,感觉乱乱的,全是新属性,所以今晚的我破天荒的熬夜敲代码,一定要弄懂! 现在就来梳理下头 ...
- 【BFS + Hash】拼图——携程2017春招编程题2
写在前面 前天参加了携程的网测--还是感觉自己太!渣!了! _(:з」∠)_ 时光匆匆啊,已经到了开始思考人生的时候了(算了不矫情了)--总之写个博客来督促一下自己.之前太懒了,很多时候都是输在 ...
- CSS空白符处理!
在CSS中有一个非常重要但对于初学者又非常容易忽略的属性: white-space:nowrap; //文本不换行属性 这里附带说一下W3Cschool中对white-space的解释: white- ...
- 懵懂oracle之存储过程
作为一个oracle界和厨师界的生手,笔者想给大家分享讨论下存储过程的知识,因为在我接触的通信行业中,存储过程的使用还是占据了一小块的地位. 存储过程是什么?不得不拿下百度词条的解释来:"存 ...
- JS实现排序
排序算法可以分为内部排序和外部排序.内部排序是数据记录在内存中进行排序,外部排序是因排序的数据很大,一次不能够容纳全部的排序记录,在排序中需要访问外存.常见的内部排序算法有插入排序,选择排序,冒泡排序 ...
- [Git]01 如何安装和配置
简单地说,Git 究竟是怎样的一个系统呢? 请注意,接下来的内容非常重要,若是理解了 Git 的思想和基本工作原理,用起来就会知其所以然,游刃有余.在开始学习 Git 的时候,请不要尝试把各种概 ...
- PHP学习笔记-1
PHP基本语法 php脚本可以放在文档的任意位置: php脚本以<? php开始,以?>结束: php文件通常包括Html标签和一些php脚本代码: 举个栗子: <!DOCTYPE ...