? ? ? ? ? ?今天看erlang,看到一个最基本的问题,就是方法调用或函数调用时,参数传递的方式,大家都知道在Java中,基本类型是通过按值传递的方式,来实现参数传递,而对象类型则是通过按引用地址传递的,但是这个里面有一个Java里面被作为基本类型的对象,就是string,在其他语言中,基本上是没有String基本类型的,比如c++,erlang等,所以Java中,String这个对象比较特殊,他传递参数时候也比较特殊。
? ? ? ? 下面一个例子:
? ? ? ?
class="java" name="code">public class StringTest { public static void main(String[] args) { String value = "Hello World"; String newValue = new String("Hello World2"); System.out.println("change before value is:"+value); System.out.println("change before new value is:"+newValue); change(value); change(newValue); System.out.println("===================================="); System.out.println("change after value is:"+value); System.out.println("change after new value is:"+newValue); } public static void change(String value){ value = value+" change"; } }
? ? ? 上面的程序运行结果为:
? ? ? ? ?change before value is:Hello World
? ? ? ? ?change before new value is:value
? ? ? ? ?====================================
? ? ? ? change after value is:Hello World
? ? ? ? change after new value is:value
?
? ? ?从上面的运行结果可以看出来,不管string是直接通过 “=”赋值,或者是通过new的方式赋值,方法调用之后,他的值都没有改变,也就是说,不管这个string是在常量池中或者堆内存中,他的值都不会改变,这样string的参数传递就和其他的基本类型不一样了,虽然Java中string类型是基本类型。
? ? 为什么会有上面的结果呢,网上有人说,string的值是在常量池中,所以不会改变,但是我们用new的方式,他也是没有改变呢。其实解释这个原因很简单,简单到看一下源码就行了。以下是string的源码:
? ? ? ?
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count; /** Cache the hash code for the string */ private int hash; // Default to 0 /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L; /** * Class String is special cased within the Serialization Stream Protocol. * * A String instance is written initially into an ObjectOutputStream in the * following format: * <pre> * <code>TC_STRING</code> (utf String) * </pre> * The String is written by method <code>DataOutput.writeUTF</code>. * A new handle is generated to refer to all future references to the * string instance within the stream. */ private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; /** * Initializes a newly created {@code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. */ public String() { this.offset = 0; this.count = 0; this.value = new char[0]; }
? ? 从源码中可以知道,string的实现是通过char[] 数组的形式,之所以String对象不管怎么整都不会改变是因为,String对象是一个final对象,就是不变的对象,里面的属性也是不变的对象,所以不管你怎么弄他都是不变的,这个就是String基本类型和其他基本类型不一样的地方,所以网上说各种原因的,看一下源码就知道为什么了。
? ?通过caozuofu.html" target="_blank">操作符 “+”,来实现string对象的相加,这个就是有点c++重的操作符重载的意思了,编译的时候,String的相加会有优化,这个优化就是如果常量池中有同样的string就会给他赋为这个变量的地址,如果没有就会通过new的方式创建一个char[],还有string中的所有有关两个string的操作比如concat这种方法,都是通过new String的方式返回新的String对象。