Java8 String的底层实现
2017-08-28 00:50
429 查看
String类的一个最大特性是不可修改性,而导致其不可修改的原因是在String内部定义了一个常量数组,因此每次对字符串的操作实际上都会另外分配分配一个新的常量数组空间(这片空间位于jvm的静态方法区)
初始化
实例化字符串
查找字符串某个位置的字节
将字节数组转换成字符串
注意:System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)是在底层操作中经常用到的一个数组复制方法
获取字符串的长度
判断string是否为空
判断两个字符串是否相等(在string中重写了equals的方法,object的equals方法相当于“==”)
注意:在重写equals()时也必须要重写hashCode()方法,以保证相同对象的hash值也是一样的,否则会出现意想不到的问题的。因为如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象, 当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,导致混淆
获得某个字符的所在位置
获得子字符串(注意这里是不会在原来的字符串修改的,修改之后也是放到一个新的字符数组中)
连接两个字符串
将字符串储存到字节数组中
最后补充一点:
StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都 会引发新的String对象的生成;StringBuilder则是可变类,任何对它所指代的字符串的改变都不会产生新的对象,而StringBuilder则是线程安全版的StringBuilder。
初始化
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { //数组定义为常量,不可修改 private final char value[]; public String() { this.value = new char[0]; }
实例化字符串
public String(String original) { this.value = original.value; this.hash = original.hash; }
查找字符串某个位置的字节
public char charAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; }
将字节数组转换成字符串
void getChars(char dst[], int dstBegin) { System.arraycopy(value, 0, dst, dstBegin, value.length); }
注意:System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)是在底层操作中经常用到的一个数组复制方法
获取字符串的长度
public int length() { return value.length; }
判断string是否为空
public boolean isEmpty() { return value.length == 0; }
判断两个字符串是否相等(在string中重写了equals的方法,object的equals方法相当于“==”)
public boolean equals(Object anObject) { if (this == anObject) { return true; } //先判断是不是sring类型 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; } //重写equals是需要重写hashCode方法 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; }
注意:在重写equals()时也必须要重写hashCode()方法,以保证相同对象的hash值也是一样的,否则会出现意想不到的问题的。因为如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象, 当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,导致混淆
获得某个字符的所在位置
public int indexOf(int ch) { return indexOf(ch, 0); } public int indexOf(int ch, int fromIndex) { final int max = value.length; if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { // Note: fromIndex might be near -1>>>1. return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { return indexOfSupplementary(ch, fromIndex); } }
获得子字符串(注意这里是不会在原来的字符串修改的,修改之后也是放到一个新的字符数组中)
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); } //注意这里是以长度取子字符串,因此endIndex最后一位不会被娶上 return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); }
连接两个字符串
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字符串的内容按照长度获取放进buf数组中 str.getChars(buf, len); return new String(buf, true); }
将字符串储存到字节数组中
public char[] toCharArray() { char result[] = new char[value.length]; System.arraycopy(value, 0, result, 0, value.length); return result; }
最后补充一点:
StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都 会引发新的String对象的生成;StringBuilder则是可变类,任何对它所指代的字符串的改变都不会产生新的对象,而StringBuilder则是线程安全版的StringBuilder。
相关文章推荐
- Java源码之String.hashCode的底层实现
- 关于一道J笔试或者机试题的Java实现:从键盘输入一串字符,翻转后输出(要求不使用string相关类即对象)
- Java实现从IP和端口列表List<String>获取分离的IP和端口值
- C#中如何实现JAVA中的String.replaceAll()方法功能
- java实现统计输入一行string中统计其中各个字符出现的次数
- C#中如何实现JAVA中的String.replaceAll()方法功能
- java里面InputStream类型转换成String类型怎么实现?
- HttpUrlConnection底层实现和关于java host绑定ip即时生效的设置及分析
- 在Android上使用LocalSocket实现上层Java和底层C++的通信
- java string 转date方法如何实现
- HttpUrlConnection底层实现和关于java host绑定ip即时生效的设置及分析
- JS正则表达式怎样实现Java中String.replaceAll的效果
- JS正则表达式怎样实现Java中String.replaceAll的效果
- java String实现加,减,乘,除运算。
- 问题1:java中没有实现这种“byte a = 0xB2 --> String b = “B2””转换的简单实现需要自己实现。 答:自己编写的转换函数,思路将byte的高低4位分开,分别转换为对应的字符然后合成返回的字符串。 java 代码 1.
- 关于一道J笔试或者机试题的Java实现:从键盘输入一串字符,翻转后输出(要求不使用string相关类即对象)
- 算法【1】:Java实现String 统计
- java调用windows DLL实现底层处理(C++编程)
- android、Java下判断两个String是否相等 、EditText输入是否为空,限定输入数字的实现 总结
- Java对String字符串对象的创建,管理和“+”运算符的实现