@pastqing
2015-09-28T09:34:40.000000Z
字数 4992
阅读 3335
java
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash; // Default to 0
}
补充: final关键字的几个意义:
1. 如果final修饰类的话, 那么这个类是不能被继承的。
2. final修饰方法的话, 那么这个方法是不能被重写。
3. final修饰变量的话, 那么这个变量在运行期间时不能被修改的。
这里应该重点理解第三点
public static void main(String[] args) {
final StringBuffer a = new StringBuffer("松哥");
final StringBuffer b = new StringBuffer("songgeb");
System.out.println("未改变: " + a);
System.out.println("a的地址: " + a.hashCode());
a = b; //这里编译就会报错了~~
a.append("帅") ;
System.out.println("改变: " + a);
}
/*
通过上面的例子, 我们对第三点的理解应该是这样:
1. 若变量是基本类型, 则它的值是不能变的
2. 若变量是对象, 则它的引用所指的堆栈区中的内存地址是不能变得, 而内容时可以变滴。
*/
/*
java中的每个类从根本上都是继承自object, 因此容器类都有toString这个方法, 例如ArrayList, 调用它的toStirng方法会遍历其中包含的每一个对象, 调用每个对象的toString方法。 下面的例子是要打印每个对象的内存地址, 这时就会陷入无意识的递归。
*/
public class demo_3 {
public String toString() {
return "address: " + this + "\n" ;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
List<demo_3> a = new ArrayList<demo_3>();
for( int i =0 ; i < 5; ++i){
a.add(new demo_3());
}
System.out.println(a);
}
}
public class demo_4 {
public static void main(String[] args) throws UnsupportedEncodingException {
/*
* \u1D56属于增补字符范围
*/
String a = "\u1D56B";
String b = "\uD875\uDD6B";
System.out.println(a);
System.out.println(a.length());
System.out.println(b);
System.out.println(b.length());
//也就是说length返回的是代码单元的数量
}
}
下面是String其中的一个构造函数:
public String(int[] codePoints, int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// 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: 计算字符数组的大小, 以分配空间
int n = count;
for (int i = offset; i < end; i++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))//这里是判断这个字符是不是属于bmp范围
continue;
else if (Character.isValidCodePoint(c))//判断是否越界
n++;
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: 填充value
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;
}
//可以看出, 构造的思路很简单, 但是必须要考虑的很全面。 像以前写c++时, 要考虑一个类能不能被复制, 赋值, 等等情况。
public static void main(String[] args) {
String x = new String("java"); //创建对象x,其值是java
String y = new String("java"); //创建对象y,其值是java
System.out.println(x == y); // false, 使用关系相等比较符比较对象x和y
System.out.println(x.equals(y)); // true, 使用对象的equals()方法比较对象x和y
String m = "java"; //创建对象m,其值是java
String n = "java"; //创建对象n,其值是java
System.out.println(m == n); // true, 使用关系相等比较符比较对象m和n
System.out.println(m.equals(n)); // true, 使用关对象的equals()方法比较对象m和n
}
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) { // 判断是不是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;
}
String a = "Hello World" ;
public static void main(String [] args ){
String a = "Hello" ;
String b = "Hello" + " World" ;
String c = "Hello World" ;
}
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String Hello
2: astore_1
3: ldc #3 // String Hello World
5: astore_2
6: ldc #3 // String Hello World
8: astore_3
9: return
}
public static void main(String [] args ){
String a = "Hello" ;
String b = new String("Hello");
}
用javap -c 返回的自己码为:
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String Hello
2: astore_1
3: new #3 // class java/lang/String
6: dup
7: ldc #2 // String Hello
9: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
12: astore_2
13: return
}