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练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)
这道题是一道爬虫练习题,需要爬链接http://tieba.baidu.com/p/2166231880里的所有妹子图片,点进链接看一下,这位妹子是日本著名性感女演员--杉本由美,^_^好漂亮啊,赶紧 ...
- css3 loading动画 三个省略号
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- C#, VB.NET如何将Excel转换为PDF
在日常工作中,我们经常需要把Excel文档转换为PDF文档.你是否在苦恼如何以C#, VB.NET编程的方式将Excel文档转换为PDF文档呢?你是否查阅了许多资料,运用了大量的代码,但转换后的效果依 ...
- 原生态JS实现banner图的常用所有功能
虽然,用jQuery实现banner图的各种效果十分简单快捷,但是我今天用css+js代码实现了几个banner图的常用功能,效果还不错. 此次,主要想实现以下功能: 1. banner图循环不间断切 ...
- NOIP2014D2T2寻找道路
洛谷传送门 这道题可以把边都反着存一遍,从终点开始深搜,然后把到不了的点 和它们所指向的点都去掉. 最后在剩余的点里跑一遍spfa就可以了. --代码 #include <cstdio> ...
- UITableView grouped样式使用探索
UITableView的style有plain和grouped两种样式,两种样式各有不同的风格和功能,plain样式已经封装好了悬停功能,gouped样式则为我们在区头和区尾在实际项目开发中需要我们选 ...
- css过渡模块和2d转换模块
今天,我们一起来研究一下css3中的过渡模块.2d转换模块和3d转换模块 一.过渡模块transition (一)过度模块的三要素: 1.必须要有属性发生变化 2.必须告诉系统哪个属性需要执行过渡效果 ...
- git提交如何忽略某些文件
在使用git对项目进行版本管理的时候,我们总有一些不需要提交到版本库里的文件和文件夹,这个时候我们就需要让git自动忽略掉一下文件. 使用.gitignore忽略文件 为了让git忽略指定的文件和文件 ...
- hyper-v使用wifi链接网络
公司了给本屌一个thinkpad笔记本,10G内存.想不出拿来干什么...装了一个win8.1_64位,cf,qq,hyper-v. 昨天第一次玩hyper-v新建了的时候选择“第二代”坑爹就开始了, ...
- 跨语言时区处理与Epoch
国际化通用程序或标准协议通常都涉及到时区问题,比如最近项目用到的OIDC(OpenID Connect). OIDC基于OAuth2协议,其id_token中包含了exp来表达该Token的过期时间, ...