String
string 三个构造函数
public String() {
this.value = "".value;
this.coder = "".coder;
}
/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
@HotSpotIntrinsicCandidate
public String(String original) {
this.value = original.value;
this.coder = original.coder;
this.hash = original.hash;
}
/**
* Allocates a new {@code String} so that it represents the sequence of
* characters currently contained in the character array argument. The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.
*
* @param value
* The initial value of the string
*/
public String(char value[]) {
this(value, 0, value.length, null);
}
public String(byte[] bytes) {
this(bytes, 0, bytes.length);
}
/**
* Allocates a new string that contains the sequence of characters
* currently contained in the string buffer argument. The contents of the
* string buffer are copied; subsequent modification of the string buffer
* does not affect the newly created string.
*
* @param buffer
* A {@code StringBuffer}
*/
public String(StringBuffer buffer) {
this(buffer.toString());
}
/**
* Allocates a new string that contains the sequence of characters
* currently contained in the string builder argument. The contents of the
* string builder are copied; subsequent modification of the string builder
* does not affect the newly created string.
*
* <p> This constructor is provided to ease migration to {@code
* StringBuilder}. Obtaining a string from a string builder via the {@code
* toString} method is likely to run faster and is generally preferred.
*
* @param builder
* A {@code StringBuilder}
*
* @since 1.5
*/
public String(StringBuilder builder) {
this(builder, null);
}
stringbuilder stringbuffer区别
string 是不可变的所以字符串拼接用stringbuffer ,它用synchronized保证线程安全,提供了append 和insert
它的性能不是很高所以后来就有了stringbuilder 去掉了synchronized
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
String 重写了equals方法
String compareTo 方法也是比较字符串和equals方法区别在于String的equals(Object) ,而compareTo(String)
同时他们返回的结果也不相同一个是boolean ,compareTo返回0才表示两个字符串相同
问题1:为什么String用final修饰?
1.final修饰的类代表不可继承的类,final修饰的方法无法被重写,但是该类可以被继承,final修饰的变量无法修改
2.java语言之父James Gosling 说final 可以缓存结果,当我们传参是不需要考虑谁会去修改他的值,如果是可变类的话,可能需要拷贝出来一个新值再进行传参,性能上会有一定的损失。(高效)
3.当调用一些系统操作指令之前可能会有一系列的校验,如果是可变类的话,可能在校验之后,它内部的值又改变了,可能引起系统崩溃问题(安全)
问题2:== 和equals区别
==对于基本数据类型来说,用于比较“值”是否相等,而对于引用类型来说是比较地址是否相同。
Object中equals()
public boolean equals(Object obj) {
return (this == obj);
}
从上面可以看出Object中的equals就是==,而string重写了equals
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
问题3:String的intern()方法含义
String 一般有直接赋值和new String()两种,直接赋值是现在常量池里看看是否存在,存在就直接把地址指向该常量,如果不存在就在常量池中创建一个,然后再把引用指向此值。
new String()则是先在堆中创建一个字符串对象,intern()则会去常量池中寻找此字符串的值是否存在,存在就指向字符串,不存在则在常量池中创建一个字符串,然后再指向改值。
String s1 = new String();
String s2 = s1.intern();
String s3 = "java";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true
但是JDK 1.7后,intern方法还是会先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,这一点与之前没有区别,区别在于,如果在常量池找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用。简单的说,就是往常量池放的东西变了:原来在常量池中找不到时,复制一个副本放到常量池,1.7后则是将在堆上的地址引用复制到常量池。