没有合适的资源?快使用搜索试试~ 我知道了~
3160104734_沈子衿_homework31
需积分: 0 0 下载量 175 浏览量
2022-08-03
17:14:40
上传
评论
收藏 647KB PDF 举报
温馨提示
试读
29页
第三种,用于实现同其他数据结 第四种,用于其他底层支持,如Objects类 第二个hash变量用于存储这个字符串的哈希值(默认为0),其目的 第三个变量seri
资源详情
资源评论
资源推荐
姓名 学号 班级
沈子衿 3160104734 软件工程1601
《Java应用技术》第三次作业
1.String, StringBuffer, StringBuilder源码分析
1.1 String类
Java的String类相关代码可以通过对String.class反编译得到,主流IDE也大多提供了直接反编译查看.class文件对应
源代码的支持。本次作业,我们使用Eclipse作为工具,来对String类进行分析。
外部引用
在文件的开头,可以看到String类的打包信息和引用的外部包,如下:
package java.lang;
// 将String类打包到java.lang.*下
import java.io.ObjectStreamField;
//I/O包,负责对可序列化字段的处理
import java.io.UnsupportedEncodingException;
//I/O包,负责在数据编码不支持的情况下抛出异常
import java.nio.charset.Charset;
//java字符集支持
import java.util.ArrayList;
//java ArrayList类支持
import java.util.Arrays;
//java Arrays类支持
import java.util.Comparator;
// 比较器,用于排序、分组等功能
import java.util.Formatter;
// 格式化类,可用于数字、日期、时间等的格式化
import java.util.Locale;
// 提供多地区、文化支持
import java.util.Objects;
//java Objects类
import java.util.StringJoiner;
// 用于构造一个由分隔符分隔的字符序列
import java.util.regex.Matcher;
//正则匹配
import java.util.regex.Pattern;
// 正则编译支持
import java.util.regex.PatternSyntaxException;
// 处理正则表达式编译可能出现的语法错误
总体来说,String类引用的外部包主要有四种用途:第一种,用于底层数据结构和数据内容(如编码等)的组织,
如Charset类、StringJoiner类和ObjectStreamField类,第二种,用于实现字符串的一些基本操作和功能(剪裁、
匹配、排序、分组、格式化等)如Comparator类、Foramtter类和两个regex类;第三种,用于实现同其他数据结
构的互动与相互转化,如Arrays和ArrayList类;第四种,用于其他底层支持,如Objects类。不同的用途均有其对
应的异常处理支持。
在类主体开始之前,我们看到了注释中有指向StringBuffer和StringBuilder类的链接:
这体现了三个类之间密不可分的关系。
成员变量
这之后,我们开始分析String类的具体实现,首先观察类头:
这说明String类调用了java.io.Serializable, Comparable, CharSequence这三个接口。
进入类体,首先是三个String类最核心的四个成员变量:
从注释中我们可以了解到,第一个value数组用来储存字符串中的字符信息,是String类的核心存储数据结构,注意
到这个变量是private的且被final修饰,因此我们不能直接通过成员访问符访问value变量,也不能修改他的值,这
便是String类生成的字符串不可更改的原因;第二个hash变量用于存储这个字符串的哈希值(默认为0),其目的
是暂存hashCode方法的值,避免反复调用这一具有巨大时间复杂度的方法。第三个变量serialVersionUID用于在
序列化验证中判断类的版本一致性,确保版本更新不会导致相关引用出错;第四个变量也是用于序列化验证的,同
本文主题不一致,相关资料中的叙述也比较繁琐,故略去不表。
构造方法
接下来,源代码描述了String类的几个主要的构造方法:
/* @author Lee Boynton
* @author Arthur van Hoff
* @author Martin Buchholz
* @author Ulf Zibis
* @see java.lang.Object#toString()
* @see java.lang.StringBuffer
* @see java.lang.StringBuilder
* @see java.nio.charset.Charset
* @since JDK1.0
*/
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];
本方法是String的默认构造方法。在创建对象且没有初始值的的情况下,调用该构造方法,创建一个空字符串。
本方法接收一个现有字符串,创建一个和源字符串完全相同的新字符串。注意,该字符串是原来的复制,而非一个
引用。看似新字符串的value是原字符串value的引用,但考虑到字符串的不可更改性,所以直接让value数组复制
源字符串的引用,并没有什么不妥的。
本方法接收一个字符数组,创建一个和字符数组中各字符对应的字符串。
本方法接受一个字符数组、一个偏移量以及一个计数变量,其功能是将字符数组中从offset开始的count个字符摘
取出来,组成一个字符串。如果count等于0且偏移量不大于value的长度,返回空字符串。其他异常情况,抛出下
标异常。不支持负向拷贝。
public String() {
this.value = "".value;
}
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
public String(int[] codePoints, int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
本方法分配一个新的String,其中包含Unicode codePoint数组参数的子数组中的字符。 offset参数是子数组的第
一个codePoint的索引,count参数指定子数组的长度。 子数组的内容转换为char s; 该int数组的后续修改不会影响
新创建的字符串。
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= codePoints.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > codePoints.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
final int end = offset + count;
// Pass 1: Compute precise size of char[]
int n = count;
for (int i = offset; i < end; i++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
continue;
else if (Character.isValidCodePoint(c))
n++;
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: Allocate and fill in char[]
final char[] v = new char[n];
for (int i = offset, j = 0; i < end; i++, j++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
v[j] = (char)c;
else
Character.toSurrogates(c, v, j++);
}
this.value = v;
}
@Deprecated
public String(byte ascii[], int hibyte, int offset, int count) {
checkBounds(ascii, offset, count);
char value[] = new char[count];
if (hibyte == 0) {
for (int i = count; i-- > 0;) {
value[i] = (char)(ascii[i + offset] & 0xff);
}
接下来,代码还描述了两个过往版本的构造方法。考虑到当前版本中(JDK1.1之后)官方已经不推荐使用(带有
@Deprecated标记),故略去不表。两个方法提供的byte数组转化为字符串的解决方案已经为以下的方法所取
代:
} else {
hibyte <<= 8;
for (int i = count; i-- > 0;) {
value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
}
}
this.value = value;
}
@Deprecated
public String(byte ascii[], int hibyte) {
this(ascii, hibyte, 0, ascii.length);
}
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null)
throw new NullPointerException("charsetName");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charsetName, 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);
}
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
public String(byte bytes[], Charset charset) {
this(bytes, 0, bytes.length, charset);
}
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
public String(byte bytes[]) {
this(bytes, 0, bytes.length);
}
剩余28页未读,继续阅读
林祈墨
- 粉丝: 31
- 资源: 326
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0