String源码
来源:互联网 发布:制作报价单软件 编辑:程序博客网 时间:2024/05/01 01:24
public final class String implements java.io.Serializable,Comparable<String> CharSequence{
private final char value[];//维护了一个字符数组,s1.contcat()方法底层原理就是数组复制
private final int offset;//记录开始
private final int count;//字符的个数
private int hash;
}
concat
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
compareTo
public int compareTo(String paramString)
{
int i = this.value.length;
int j =paramString.length;
int k =Math.min(i,j);
char[] arrayOfChar1 = this.value;
char[] arrayOfChar2 = paramString.value;
for(int m = 0;m<k;m++){
int n =arrayOfChar1.length;
int i1 = arrayOdChar2 ,length;
if(n !=i1)
return n-i1;
}
return i-j
}
equals
public boolean equals(Object paramObject)
{
if(this == paramObject){
return true;
}
if(paramObject instanceof String)
{
String str =(String) paramObject;
int i = this.value.length;
if( i == str.value.length){
char[] arrayOfChar1 = this.value;
char[] arrayOfChar2 = str.value;
for(int j = 0;i-- !=0;j++)
if(arrayOfChar1[j] !=arrayOfChar2[j])
return false;
return true;
}
}
return false;
}
indexOf
getBytes
split*以及自己如何实现一个split方法,利用反射
substring
String s="123abc";
String ss=s+"";//变量运算在运行期执行,产生新对象
System.out.println(s==ss);//flase
System.out.println(s.equals(ss));//true
String s1="123abc";
String s2="123"+"abc";//字面量常量运算在javac时候优化
System.out.println(s1==s2);//true
System.out.println(s1.equals(s2));//true
String s3="1"+"23"+"abc";//123abc
String s4='1'+'2'+'3'+"abc";//150abc
System.out.println(s3);
System.out.println(s4);
System.out.println(s3==s4);//flase
System.out.println(s3.equals(s4));//false
String s5=1+"23abc";//123abc
String s6=1+2+"3abc";//33abc
System.out.println(s5);
System.out.println(s6);
System.out.println(s5==s6);//false
System.out.println(s5.equals(s6));//false
String s7=new String("123abc");
String s8=new String("123"+"abc");//new String("123abc");
System.out.println(s7);
System.out.println(s8);
System.out.println(s7==s8);//false
System.out.println(s7.equals(s8));//true
字符串常量:static final修饰的变量
1. 声明String对象
- String s = "abcd";
- String s2 = s;
- s = s.concat("ef");
- // s = s + "ef"; // 等价
一个String对象在 堆内存 中创建以后, 就不能被改变了. 请注意String对象的所有方法都不会改变其本身,而是会返回一个新的String对象.
如果我们需要可改变的字符串,则需要使用 StringBuffer 或者 StringBuilder. 否则每次创建一个新String对象的话,就会造成大量的内存浪费,需要耗时来执行垃圾回收。
为什么设计为不可变?
什么是不可变对象?
如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。
区分对象和对象的引用
- String s = "ABCabc";
- System.out.println("s = " + s);
- s = "123456";
- System.out.println("s = " + s);
打印结果为:
s = 123456
为什么String对象是不可变的?
- public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence
- {
- /** The value is used for character storage. */
- private final char value[];
- /** The offset is the first index of the storage that is used. */
- private final int offset;
- /** The count is the number of characters in the String. */
- private final int count;
- /** Cache the hash code for the string */
- private int hash; // Default to 0
- public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence {
- /** The value is used for character storage. */
- private final char value[];
- /** Cache the hash code for the string */
- private int hash; // Default to 0
由以上的代码可以看出, 在Java中String类其实就是对字符数组的封装。JDK6中, value是String封装的数组,offset是String在这个value数组中的起始位置,count是String所占的字符的个数。在JDK7中,只有一个value变量,也就是value中的所有字符都是属于String这个对象的。这个改变不影响本文的讨论。 除此之外还有一个hash成员变量,是该String对象的哈希值的缓存,这个成员变量也和本文的讨论无关。在Java中,数组也是对象(可以参考我之前的文章java中数组的特性)。 所以value也只是一个引用,它指向一个真正的数组对象。其实执行了String s = “ABCabc”; 这句代码之后,真正的内存布局应该是这样的:
- String a = "ABCabc";
- System.out.println("a = " + a);
- a = a.replace('A', 'a');
- System.out.println("a = " + a);
打印结果为:
a = aBCabc
- String ss = "123456";
- System.out.println("ss = " + ss);
- ss.replace('1', '0');
- System.out.println("ss = " + ss);
打印结果:
ss = 123456
String对象真的不可变吗?
- public static void testReflection() throws Exception {
- //创建字符串"Hello World", 并赋给引用s
- String s = "Hello World";
- System.out.println("s = " + s); //Hello World
- //获取String类中的value字段
- Field valueFieldOfString = String.class.getDeclaredField("value");
- //改变value属性的访问权限
- valueFieldOfString.setAccessible(true);
- //获取s对象上的value属性的值
- char[] value = (char[]) valueFieldOfString.get(s);
- //改变value所引用的数组中的第5个字符
- value[5] = '_';
- System.out.println("s = " + s); //Hello_World
- }
打印结果为:
s = Hello_World
需要综合内存,同步,数据结构以及安全等方面的考虑:
1. 字符串常量池的需要
字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
如下面的代码所示,将会在堆内存中只创建一个实际String对象.
- String s1 = "abcd";
- String s2 = "abcd";
假若字符串对象允许改变,那么将会导致各种逻辑错误,比如改变一个对象会影响到另一个独立对象. 严格来说,这种常量池的思想,是一种优化手段.
请思考: 假若代码如下所示,s1和s2还会指向同一个实际的String对象吗?
- String s1= "ab" + "cd";
- String s2= "abc" + "d";
2. 允许String对象缓存HashCode
Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。
字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码. 在String类的定义中有如下代码:
- private int hash;//用来缓存HashCode
String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。
假如有如下的代码:
- boolean connect(string s){
- if (!isSecure(s)) {
- throw new SecurityException();
- }
- // 如果在其他地方可以修改String,那么此处就会引起各种预料不到的问题/错误
- causeProblem(s);
- }
4.因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。
5.类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。譬如你想加载java.sql.Connection类,而这个值被改成了myhacked.Connection,那么会对你的数据库造成不可知的破坏。
StringBuffer 和 StringBulider 共同父类AbstractStringBulider StringBuffer是线程安全的里面的方法是synchronized
append insert
- String 源码
- String源码
- String 源码
- 【源码】String
- JAVA源码解析-String源码
- string函数源码
- string.h源码
- java 源码 String
- jdk源码学习------String
- 【Java源码】String类
- JDK源码-String
- String源码分析
- JAVA源码String学习
- c语言string源码
- string - strlen源码
- string - strncpy源码
- string - strncmp源码
- string - strrchr源码
- ContentProvider使用
- Gridview隐藏列的部分内容,鼠标移到该单元格显示内容
- 数据窗口横向滚动时用PB锁定某列
- TCP与UDP在socket编程中的区别
- jquery 禁止用户点击浏览器后退键。
- String源码
- 构建安装问题
- 求任意一天是星期几
- leetcode 321. Create Maximum Number
- 添加商品动画
- android Broadcast学习
- Android笔记:invalidate()和postInvalidate() 的区别及使用
- Misson Planner增加mavlink消息并显示在status中
- 从Theano到Lasagne:基于Python的深度学习的框架和库