字符串创建于存储的机制
String s1 = new String(“abc”) 和 String s2 = new String(“abc”)两个引用对象不一样,只要用到了new都会生成新的对象。
public class StringtTest {
public static void main(String[] args) {
String s1 = "abc"; //把"abc"放到常量区,在编译时产生
String s2 = "abc"; //s2引用常量区中的对象,因此不会创建新的对象
String s3 = "a" + "bc"; //转换成字符串常量"abc"放到常量区
String s4 = new String("abc"); //在堆中创建新的对象
String s5 = new String("abc"); //在堆中又创建了一个新的对象
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //true
System.out.println(s1 == s4); //false
System.out.println(s4 == s5); //false
}
}
“==”、equals和hashCode
- “==”比较两个变量的值是否相等。对于基本数据类型,直接比较对应的值是否相等。对于引用类型,比较的是变量s1和s2所对应内存(栈)中存储的数值,即对象占用的那块内存(堆)的首地址。
- equals是Object类提供的方法之一。Object类中定义的equals方法直接使用”==”比较两个对象。所以可以通过覆盖equals方法使它不是比较引用而是比较数据内容。
- hashCode()是从Object类继承过来的,也用来鉴定两个对象是否相等。Object类中的hashCode返回的是对象在内存中地址转化成的一个int值。
通常,一般覆盖equals()方法的同时也要覆盖hashCode()方法。
equals返回true,则hashCode返回的Int值也相等;equals返回false,则hashCode返回值不确定。hashCode返回值不等,则equals返回false;反之则不确定。
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;
}
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;
}
String、StringBuffer、StringBuilder和StringTokenizer
- String属于不可变类,所以String字符串的修改实际上都是创建新的字符串对象,影响程序的性能。
- StringBuffer是线程安全的,StringBuilder非线程安全,但是效率最高。
public class StringtTest {
public static void testString() {
String s = "hello";
String s1 = "world";
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
s+=s1;
}
long end = System.currentTimeMillis();
long runTime = end - start;
System.out.println(runTime);
}
public static void testStringBuilder() {
StringBuilder s = new StringBuilder("hello");
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
s.append("world");
}
long end = System.currentTimeMillis();
long runTime = end - start;
System.out.println(runTime);
}
public static void main(String[] args) {
testString(); //504
testStringBuilder(); //1
}
}
StringTokenizer是用来分割字符串的工具类:
public class StringtTest {
public static void main(String[] args) {
StringTokenizer st = new StringTokenizer("ni hao, welocome to my home");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
}
}
**output:**
ni
hao,
welocome
to
my
home
Java中的数组也是对象
public class StringtTest {
public static void main(String[] args) {
int[] a = {1, 2, 2};
System.out.println(a instanceof int[]);
}
}
数组的初始化方式
public class StringtTest {
public static void main(String[] args) {
int[][] a = {{1, 2}, {1, 2, 3}};
int[][] arr = new int[2][];
arr[0] = new int[]{1, 2};
arr[1] = new int[]{1, 2, 3};
System.out.println(a); //[[I@60e53b93
System.out.println(arr); //[[I@5e2de80c
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.println(a[i][j]);
}
}
}
}
length属性和length()方法
- 数组提供了length属性
- String提供了length()方法