String型变量的定义与引用

来源:互联网 发布:小米盒子网络共享设备 编辑:程序博客网 时间:2024/05/21 08:49

String型变量的定义与引用

大家都在讲, 在Java中,变量是按引用传递,除了基本数据类型和String。基本数据类型没有什么可讲的,那么String到底有什么特殊的地方。

提到String,就得提StringBuffer,下面通过几个例子来说明他们的区别。

public class Test {
    public static void main(String[] args) {
     String A="aaa";
     String B="bbb";
     
     System.out.println(A.equals(B));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
     B=A;
     System.out.println(A.toString().equals(B.toString()));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
    }
}

输出结果为:

false
false
96321
97314
true
true
96321
96321
大家都应该能预测到这个结果,因为我们把A赋值给了B。

让我们稍微改动一下,用B="aaa"代替B=A。

public class Test {
    public static void main(String[] args) {
     String A="aaa";
     String B="bbb";
     
     System.out.println(A.equals(B));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
     B="aaa";
     System.out.println(A.toString().equals(B.toString()));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
    }
}

再来看输出结果,

false
false
96321
97314
true
true
96321
96321

有些想不到吧,和B=A是一样的。再做一下改动,把B="aaa"改成B="aa“+”a",

public class Test {
    public static void main(String[] args) {
     String A="aaa";
     String B="bbb";
     
     System.out.println(A.equals(B));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
     B="aa"+"a";
     System.out.println(A.toString().equals(B.toString()));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
    }
}

结果仍然是,

false
false
96321
97314
true
true
96321
96321

看到了吧,这就是String和其他对象类型不一样的地方。不管你怎么定义或赋值,只要字符串变量的内容是相同的,他们指向的就是同一个字符串对象。
比如上面的例子,不管B的值是从A赋过来的,还是自己定义的,只要他的值是‘aaa’,他和A指向的就是同一个对象。
这样做的好处嘛,我只想到一点儿,节省资源。比如你有10个变量的值都是'aaa',那么这10个变量指向的是同一个对象,而不是10个对象。

再来看看StringBuffer,差不多的一个例子,

public class Test {
    public static void main(String[] args) {
     StringBuffer A=new StringBuffer("aaa");
     StringBuffer B=new StringBuffer("bbb");
     
     System.out.println(A.equals(B));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
     B=A;
     System.out.println(A.toString().equals(B.toString()));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
    }
}


输出结果,

false
false
3526198
7699183
true
true
3526198
3526198


稍微改动一下,B=A替换为B=new StringBuffer("aaa"),

public class Test {
    public static void main(String[] args) {
        //(Man.getMan()).printName();
        //System.out.println((Man.getMan()));
     StringBuffer A=new StringBuffer("aaa");
     StringBuffer B=new StringBuffer("bbb");
     
     System.out.println(A.equals(B));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
     B=new StringBuffer("aaa");
     System.out.println(A.toString().equals(B.toString()));
     System.out.println(A==B);
     System.out.println(A.hashCode());
     System.out.println(B.hashCode());
    }
}

输出结果为,

false
false
3526198
7699183
true
false
3526198
14285251

怎么样,看到StringBuffer和String是不一样的啦吧,虽然A和B的值相同,但是指向的是不同的对象。StringBuffer和其他对象类型一样,是按引用传递的。


String和StringBuffer的其他区别:
1. StirngBuffer是可以变话的,如果改变了StringBuffer变量的长度或内容,不会改变对这个对象的引用。
2. String是固定的,如果改变了String变量的长度或内容,就会新建一个String对象,原来的String变量会指向新的String对象。

 

下面是根据‘会飞的鱼’网友的建议做的补充,

因为在 java 中 String 是一个非常特殊的对象,在内存在存在一个String pool 的内存池,用于保存String 常量,而采用 new 关键字进行生成的对象,是保存在堆中的。这两个是不一样的。

public class StringTest {

 /**
 * @param args
 */
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 String s = new String("abc");
 String s1= "abc"; String s2 = new String("abc");
 System.out.println(s.hashCode());
 System.out.println(s1.hashCode());
 System.out.println(s2.hashCode());
 System.out.println(s==s1); ///输出值是什么? ---false
 System.out.println(s==s2); ///输出值是什么? ---false
 System.out.println(s1==s2); ///输出值是什么? ---false
 //// == 两边判断的是引用的地址是否一样。

 String hello = "hello";
 String hel = "hel";
 String lo = "lo";
 System.out.println(hello.hashCode());
 System.out.println(("hel"+lo).hashCode());
 System.out.println(hello=="hel"+"lo"); ///输出值是什么? ----true
 System.out.println(hello=="hel"+lo); ///输出值是什么? --- false

 }

 }

输出结果为:

96354
96354
96354
false
false
false
99162322
99162322
true
false

 

补充总结:

1. 使用new 关键字生成的对象,是保存在堆中的。每使用一次new,就会生成一个新的引用对象(分配新的内存地址)。

2. 使用new和直接赋值生成的String对象的引用地址是不用的,即使他们的hashcode相同。

3. == 两边判断的是引用的地址,而不是hashcode。

4. Object.hashcode()方法返回的是内存地址,但是String类改写了hashcode()方法。所以String对象的hashcode值并不是内存地址。 

原创粉丝点击