String的特殊性

来源:互联网 发布:网络运营助理岗位职责 编辑:程序博客网 时间:2024/06/11 13:40

书上都说string是引用类型,但事实上我所看到的string和所谓的值类型没有什么区别,但通过看以下的文章,明白了:

1、string a="abc";之后,如果a="xy",则是a并没有改变内存中已经存在的"abc",而是又创建了另外一个实例。实际上相当于:string a=new String("abc");a=new String("xy");但如果是StringBuffer,则:StringBuffer a=new StringBuffer("abc"); 这是如果再想改变a,则:a.append("xy");值变为"abcxy",其中并没有new。

2、以上中:string a="abc"; b=a; a="xy"; 则b还是"abc"。
但如果是:StringBuffer a=new StringBuffer("abc"); StringBuffer b=a; a=a.append("xy"); 则b变为:"abcxy"。

3、虽然string确实是引用类型,但我想我还是基本把他看成是值类型,因为他引用的内存中的值并不会改变,也应该不会说当另外一个应用改变了内存中的值,从而会导致这个值的改变,不会的。但stringBuffer却可以。还有数组等。

4、数据分为2种,一种是值类型,一种是引用类型。但方法的传递方式却是三种,默认的一般书上不写,即值传递(val),另外2种是:ref 和 out。

5、事实上,所有的值类型数据包括所谓的引用类型的string,在值参数时,其方法中都无法不从根本上改变其本质,因为任何常用的赋值都省略了new .....。只有数组、StringBuffer以及其他类在改变其中的部分内容是可以不改变其本质,如stringbuffer.append()、intArray[2]=100等,要改变他们的本质好像只能用new的形式。这也是为何我们经常分不清string是否是引用类型,以及传递参数时的种种疑惑的根源。举个Array的例子:


void aa(int() array,int x,string z)
...{
   array[2]=array[2]+100;
    array=new int[]...{5,6,7}

   x=100;
   z="zz";
}

void bb( ref int[] array ,int x,string z)
...{
   array[2]=array[2]+100;
   array=new int[]...{5,6,7}

   x=100;
   z="zz";

}

int[] a=new int[] ...{1,2,3};
int xx=9;
string zy="zy";

那么上面的结论中,如果是第一aa方法,只有数组会改变其值,而且只会执行第一行命令,结果为103,但不会new,而变为{5,6,7}。在ref方法中,数组会变为{5,6,7},xx和zy也会变的。以上是我的心得。

以下是在JAVA中的结论。

2. String类的特殊性


1) String s1 = “Hello”; //产生一个String ”Hello”对象,并产生该对象的一个别名s1来引用该对象
String s2 = “Hello”; //又产生一个别名s2来引用上面的”Hello”对象
s1 == s2 = true;   //由于是同一个对象所以“==”返回为true
s1 = “World”; //产生一个String ”World”对象, s1的引用不再指向“Hello”而是指向对象”World”
s1 == s2 = false;   //由于不是同一个对象所以“==”返回为false
s1 = “Hello”; //同上面的String s2 = “Hello”; 现在s1又指向对象”Hello”, 因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。
s1 == s2 = true;   //由于是同一个对象所以“==”又返回为true了
s1 = s1 + “World”; //这时又产生一个对象”HelloWord”,s1不再指向”Hello”而是指向”HelloWord”
s1 == s2 = false; //不是一个对象当然是false拉
s1 = s1+ "a"+"b"+"c"+…; // String不停的创建对象,影响性能,这种易变的String用StringBuffer会得到更好的性能
StringBuffer s3 = new StringBuffer(“Hello”); 
s3.append(“a”); //没有生成新的对象,而是将s3引用的对象内容改为”Helloa”

//说明: String类用来表示那些创建后就不会再改变的字符串,它是immutable的。而StringBuffer类用来表示内容可变的字符串,并提供了修改底层字符串的方法。
StingBuffer是一个可变的字符串,它可以被更改。同时StringBuffer是Thread safe的, 你可以放心的使用.

因为String被设计成一种安全的字符串, 避免了C/C++中的尴尬。因此在内部操作的时候会频繁的进行对象的交换, 因此它的效率不如StringBuffer。 如果需要频繁的进行字符串的增删操作的话最好用StringBuffer。 比如拼SQL文, 写共函。 另: 编绎器对String的+操作进行了一定的优化。 
x = "a" + 4 + "c"
会被编绎成
x = new StringBuffer().append("a").append(4).append("c").toString()
但:
x = “a”;
x = x + 4;
x = x + “c”;
则不会被优化。 可以看出如果在一个表达式里面进行String的多次+操作会被优化, 而多个表达式的+操作不会被优化。
摘自:《Java API Using, Tips And Performance Tuning》
2) Integer、Boolean等wrapper类以及BigInteger、BigDecimal是immutable的,所以也有与String类似的地方,不过没有IntegerBuffer之类的东西。不过Float, Double,Boolean比较特殊。如
T a1 = 10; //T代指Byte,Integer,Short,Long
T a2 = 10;
if (f1 == f2)
System.out.println(true);
else
System.out.println(false);
这时总是true,和String有点类似

T a1 = (T)10.0; //T代指Float,Double
T a2 = (T)10.0;
if (f1 == f2)
System.out.println(true);
else
System.out.println(false);
这时总是false

Boolean a1 =true; 
Boolean a2 =true;
if (f1 == f2)
System.out.println(true);
else
System.out.println(false);
这时总是false
总之如果比较两个Wrapper类的值用equals,以免不必要的麻烦
3) 再看
String s1 = new String(“Hello”);
String s2 = new String(“Hello”);
s1 == s2 = false;
//因为new的时候JVM不管heap中有没有”Hello”对象都会产生一个新的”Hello”对象
String s3 = “Hello”; //重新创建对象”Hello”, 并令s3指向对象”Hello”
s3 == s1 = false; //不同对象当然false
String s4 = “Hello”; 
s3 == s4 = true; //故伎重演,jvm清楚的知道哪些用了new,哪些没用new
//Integer等整型wrapper类也有同样的特性
3. 方法的参数传递中都是以reference传递,而primitive传递的是副本,但如果传递的是Integer、Boolean等wrapper类和String类的Object则是以immutable方式传递。示例:
import java.awt.Point;
class HelloWorld
{
public static void modifyPoint(Point pt, String j, int k, Integer m, Boolean b)
{
    pt.setLocation(5,5);                                      
    j = "15";
    k = 25;
    m = 35;
    b = true;
    System.out.println("During modifyPoint " + "pt = " + pt +
                       " and j = " + j+ " and k = "+ k+ 
                       " and m = "+ m+ " and b = "+ b);
}

public static void main(String args[])
{
    Point p = new Point(0,0);                                 
    String i = "10";
    int k = 20;
    Integer m = 30;
    Boolean b = false;
    System.out.println("Before modifyPoint " + "p = " + p +
                       " and i = " + i+ " and k = "+ k+ 
                       " and m = "+ m+ " and b = "+ b);
    modifyPoint(p, i, k, m, b);                                        
    System.out.println("After modifyPoint " + "p = " + p +
                       " and i = " + i+ " and k = "+ k+ 
                       " and m = "+ m+ " and b = "+ b);
}
}
输出结果:
Before modifyPoint p = java.awt.Point[x=0,y=0] and i = 10 and k = 20 and m = 30 and b = false
During modifyPoint pt = java.awt.Point[x=5,y=5] and j = 15 and k = 25 and m = 35 and b = true
After modifyPoint p = java.awt.Point[x=5,y=5] and i = 10 and k = 20 and m = 30 and b = false

来源于:http://hi.baidu.com/erics%5Flele/blog/item/4959a0fb2168dc204e4aea47.html

0 0
原创粉丝点击