我看还是我来回答吧。 注意了!!Java大虾到!!
首先啊,你要知道Java方法调用都是传值的,其次要知道基本类型和对象的区别。
我们来一个个分析你就明白了。
int n=1;
String s="abc";
supper sp=new supper();
这三个量中有一个基本类型,两个对象对吧?那你知到他们有什么区别么?
我来简单的说一下吧。
基本类型很简单,比如整型n就是四字节空间,那这个n存在哪里呢?
存在栈里面(因为他是局部变量)。
由于是传值,那么他就把n的值传过去了,那边的形参也是个局部变量,也存在栈里面(f1调用栈),所以本质上main的n1和f1中的n1是俩n1,所以你改变fi中的n1后mian里面的n1显然不会变。
对象也是传值!!不要说对象是传引用的,如果你老师这样叫你那只能说他不真正理解Java内存结构。
对象是什么?或者说s和sp到底是个什么?
我跟你说,他们首先是个局部变量,存在哪里?和n一样存在main栈里。占多大空间?4个字节!!
撒意思?意思就是所谓对象,实质上就是一指针变量!(Java语法上没指针,但Java实现上有的)
指针的内容或说指针指向哪里?指向堆中的两个对象空间。至于撒是对象空间,我就不细说了,与本问题无关。
所以对象s和sp有两层含义,一是指两个局部变量,而是指这两变量对应的对象空间。
再回到传值的问题上。
调f2、f3同样是传值!!但因为s、sp本身就一指针,所以传的值就是俩对象的内存地址。
好吧,继续分析为什么s不变而sp变。
s不变的原因归结于字符串这个类的特性。不知道你老师告诉过你没有,字符串是不可变的!不知道也没关系,我们看看s的处理过程:
s+="def"; 等价于s = s+"def"
s+"def"怎么处理的你知道么?是把def放入s对象空间中么?不是的。
过程是这样滴:先算出s的长度和def的长度,然后在堆里面开辟一对象空间,之后把s、def都拷进去。而s = s+"def"撒意思呢?那就是考进去之后再把这个新开辟对象的地址放入变量s中去(说过了s是f2的一局部指针类型的变量)。
看看,看看!
main的s把值(对象空间地址)给了f2的s,而你“一不小心”通过s = s+"def"把s中存储的值换成一个新对象的值了。那么f2的s和main的s还指向同一个对象么???不是的。既然不是的,main的s当然不会变?
现在在看看sp
同里,main的sp把自己存的地址拷贝给f3的sp,而你呢?显然没有重新给sp赋值,这也就意味着虽然俩sp是两个局部变量,但这两个变量指向的对象空间是一样滴。
因此,你通过f3的sp操作其成员num,当然会影响main的sp了。
明白了??不明白?我都快累死了你还不明白?去死!
:)
首先 这段代码是有问题的,应该是封装在类里面的才对
然后,static 是静态标志,他能够在对象实例化之前就分配内存,所以 n ,s 这样的就可以打印出结果来。而对于第三个是调用对象,再方法中对对象引用赋值为3 然后打印这个值。supper()类应该是存在的。
你是想知道怎么样变化的,给你简单分析下把值直接传入用
public static void f1(int n){ //main()方法调用f1(n) n=1;
n++;//1++等于2
// System.out.println("n>>>>>>>:"+n); //n>>>>>>>:2
}
public static void f2(String s){ //f2(s); s="abc"
s+="def"; //s=s加"def" s="abcdef"
System.out.println("s>>>>>>>>>>>>:"+s); //s>>>>>>>>>>>>:abcdef
}
public static void f3(supper s){
s.num=3;
System.out.println("supper's num>>>>>>:"+s.num); //supper's num>>>>>>:3
}
public static void main(String[] args) {
int n=1;
f1(n);
System.out.println(n);
String s="abc";
f2(s);
System.out.println(s);
supper sp=new supper();
f3(sp);
System.out.println(sp.num);
}