62,615
社区成员
发帖
与我相关
我的任务
分享
class Test
{
String temp = "123";
}
public class MyClass
{
public static void main( String args[])
{
Test t1 = new Test();
System.out.println(t1.temp);
fun(t1);
System.out.println(t1.temp);
}
public static void fun(Test t)
{
t.temp = "456";
}
}
public class MyClass
{
public static void main( String args[])
{
String s = "123";
System.out.println(s);
fun(s);
System.out.println(s);
}
public static void fun(String t)
{
t = "456";
}
}
String s = "123";
这样的代码,实际上是java提供的语法糖,他表示的真实含义是String s = new String("123").intern();
这句代码什么意思呢?他表示,先去方法区的常量池中搜索有没有字符串常量"123",如果有,则直接返回"123"在常量池中的引用地址;如果没有,则在方法区中扩展常量池增加"123"字符串的对象,并返回引用地址。
而String ss = new String("123");则是显式的在堆区新建对象,返回引用。如下代码 String s = new String("123").intern();
String ss = new String("123");
String sss = "123";
System.out.println(s==ss);
System.out.println(s==sss);
其中==操作符表示比较引用地址。自己尝试下结果。
明确了以上三个概念。解释你的两段代码就很容易了。
public static void fun(Test t)
{
t.temp = "456";
}
这里的"456"在常量池中创建新的对象并返回引用,为t.temp赋了新的引用地址,指向常量区"456"。
public static void main( String args[])
{
String s = "123";
System.out.println(s);
fun(s);
System.out.println(s);
}
public static void fun(String t)
{
t = "456";
}
其中fun方法中的参数String t的生命周期只在这一次方法调用。方法载入时,传参将s指向的地址值赋给了t。
fun方法同样在常量池中创建新的对象(称为c)并返回引用,但将引用地址赋给了我们这里的String t,也就是说,t的指向地址从s指向的地址值变为了c所指向的地址值。这并不影响s。所以发生了,你看到的现在这个现象。
如果对第二段代码还不是很理解,可以把你第一段代码稍加改造,就能理解的非常透彻。
class Test
{
String temp = "123";
}
public class MyClass
{
public static void main( String args[])
{
Test t1 = new Test();
System.out.println(t1.temp);
fun(t1);
System.out.println(t1.temp);
}
public static void fun(Test t)
{
t. = new Test(); //仅增加这一行
t.temp = "456";
}
}
如此,看看打印的结果,理解了么?
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
StringBuffer类里面的value
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
////////////////////////
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
this.id=id;
如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的 值不会改变原始的值.
如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的 值,那么在函数内的改变会影响到传入的参数。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的 地址,所以不会改变参数的值。
你第一个是传一个对象的引用过去。
还把这个对象的值改变了。
第二个,String 自己new了个。
只在方法内有效。
比如下面代码:
public class Test5 {
public static void main(String[] args) {
List<People> list = new ArrayList<People>();
People people = new People();
people.id = 1;
list.add(people);
people.id = 2;
list.add(people);
for (People p : list) {
System.out.println(p.id);
}
}
}
class People {
public int id;
}
你觉得会输出1,2 吗?