public class MyTest { /**
* @param args
*/
public static void main(String[] args) { //初始化
String a="aaaa";
String b=new String("bbbb");
//处理
test1(a);
test2(b);
//输出结果
System.out.println("结果A:"+a);
System.out.println("结果B:"+b);
}
public static void test1(String a)
{
a="111111";
}
public static void test2(String b)
{
b=new String("22222");
}}
[/code]
输出结果
结果A:aaaa
结果B:bbbb
--------------------------------------------------------------------------这里我疑惑 我认为b方法传的是引用 那么 b引用应该指向了2这个对象 ,大家认为呢
解决方案 »
- java
- 刚才的字符串拆分忽略引号内拆分符号题目,给分少了,结了重开
- 只是重写paint方法而不重写update方法,画图时有比较明显的闪烁
- java实现RichTextBox求助
- 急急急!高分求助,关于按钮的关联!
- 请问编程时,什么时候该用到静态方法(看起来好像调用挺方便,好像速度也快),什么时候用 非静态方法 (((很迷茫)))
- thinking in java 的例子。。在线等
- 关于《 Java与模式 》。
- JB7编译的EXE文件在有些机器上运行正常,在有些机器运行非法,不知为何??
- JBuilder7太爽了!!!
- 请高手总结的一些java比较经典的书籍?
- Java中唯一的运算符重载“+”是怎么回事?
* @param args
*/
public static void main(String[] args) { //初始化
String a="aaaa";
String b=new String("bbbb"); //处理
test1(a);
test2(b); //输出结果
System.out.println("结果A:"+a);
System.out.println("结果B:"+b);
}
public static void test1(String a)
{
a="111111";
}
public static void test2(String b)
{
b=new String("22222");
} }
{
a="111111";
}
public static void test2(String b)
{
b=new String("22222");
}
这两个方法并没有返回值.
而初始化的a,b当然就不变了.
这种理解可以帮助初学者很快记忆。但是应该看到“值传”和“引用传递”的本质。String a;这时在栈内存中有一个变量a,可以认为他是的内容是个地址,而这个地址这时还没有任何意义。
a = new String("str");这时a变量的地址指向堆内存中一块内存,该内存为"str"的实际所在。
如果有c/c++基础,这里的a变量其实就是指针。上面的理解了,然后就不要再认为有“值传”和“引用传递”,应该统一为“值传递”,即方法调用,“总”要将实参copy给形参
,所以String a的a在test1中被copy了,意味着test1中的a在栈内存中是另一份不同于实参的a,但是都指向同一个堆内存,他们只是名字相同。既然这样,那么你对test1中的a重定向,又怎么会改变实参a呢。
啰嗦了半天,希望对你有帮助。
所谓的基本类型值传递,是因为基本类型的分配是在栈内存中,int a = 1;变量a的内容保存的就是1而非地址,也就不存在指针这样的指向关系,所以方法调用就把这个整体进行了次copy。
一个引用只能指向一个对象,多个引用可以指向同一个对象~!就这么简单!
的话。。 那么test2传进来的参数应该指向了new String("22222"); 对像
请看下面内存分析:
String b=new String("bbbb");
/*内存布局如下:
这里创建一个局部变量b,b再stack里开辟一小块空间.同时再head中开辟一块空间是真正的对象String("bbbb"),同时,再stack segement里有一个"bbbb".
b这个引用指向了对象String("bbbb")*/test2(b);
/*这里的内存布局:
调用方法test2(b),在stack里创建一个局部变量b(注意:不同于上面的b)
*/public static void test2(String b)
{
b=new String("22222");
}
/*执行方法test2(b)时的内存布局:
第二次创建的局部变量b赋值为"22222"
接下来,方法test2执行完毕,stack里为test2创建的局部变量消失,也就是说第二次创建的变量b消失.
这里第二次创建的b就只是位了迷惑你.并且,test2这个方法相当于什么都没有做.(实际上当然是做了事情的)
*/System.out.println("结果B:"+b);
/*这里是要打印b这个引用了,也就是第一次创建的那个局部变量b,它指向head区的String("bbbb").所以打印出来的就是bbbb*/Ok,内存分析一步一步来,分析完再看是很简单的.
代码区:codesegement,存放代码;
数据区:datasegement,存放静态变量和字符串变量
栈:stack,存放局部变量.
堆:head,存放动态创建的东西,例如new出的东西.另外更正一下,13楼我的回复中第一句内存分析中的最后一句应该是:在datasegement里创建了一个"bbbb"
{
public static void main(String[] args)
{
B b=new B(); setAge(b); System.out.println(""+b.sex);
}
public void setAge(B myb)
{
myb.sex="sunlight";
}
}
class B
{
public int sex;
};按你那样说的话。。 那这个结果又是为什么呢
{
a="111111";
}
public static void test2(String b)
{
b=new String("22222");
a和b不要和
String a="aaaa";
String b=new String("bbbb");
看做一样的
在栈中test1和test2中的a和b实际上可以是任何字符(比如c和d)他门是局部变量,在方法体运行后会消亡
如果你在test1(a);中让a指向的对象"aaaa"发生了改变。
则因为a还是指向"aaaa",此时a指向的对象发生了改变。而在此例中,你根本没有令"aaaa"这个对象发生改变。
可以去尝试用a指向一个可以改变属性值的对象。再用test1(a);方法去改变这个对象的某些属性,这时应该能发现a指向的东西的发生了变化。
但是请务必清楚一件事情,就是a的指向不会因为方法传参而改变。
{
b=new String("22222");
} 这个方法你为什么不能写成public static void test2(String Str)
{
Str=new String("22222");
} 改成这样的话 就是b还是指向原来指向的那个对象。
str一开始指向b指向的那个的对象,然后通过赋值表达式,改变指向,指向了new String("22222")。
str不是你的b... 不能因为他们指向一个对象么,就以为他们是一个东西。
传的时候是str=b;形式传的。至少书的图是这么画的。
在仔细说,str和b都是变量名吧,这2个名字和引用是映射关系吧。引用再指向对象。是这样么...
{
a="111111";
}
public static void test2(String b)
{
b=new String("22222"); //这里的b不是String b=new String("bbbb"); 的b,所以原来的b里的内容没变
}
分析完之后,概括的说一下,这个例子中,只创建了一个实例,b一直指向这个实例.myb在它所在的那个方法存在的时间存在,并修改了这个实例.然后myb消亡,通过b访问这个实例的sex属性并打印.public class A
{
public static void main(String[] args)
{
B b=new B();
/*直接分析了,从main()的第一句开始.创建B的一个实例b,内存分布:在栈区分配给b一个空间.在堆区创建一个B的实例.b指向这个实例.*/
setAge(b);
/*调用方法setAge(B myb);首先创建一个局部变量(形式参数)myb,把b的值传递给它,这里就相当于让myb指向了b指向的实例.
进入方法体.myb.sex="sunlight";改变myb指向的实例的sex属性值为sunlight;方法结束,形式参数myb消亡.*/
System.out.println(""+b.sex);
/*System.out.println(""+b.sex);输出b.sex的值.b指向的实例还是那个实例,只不过在上面的方法中,那个实例的sex属性值被改变了,并且由于改变的是实例,所以myb的消亡没有影响这个改变的事实.所以b的sex属性也就是方法setAge()改变后的值.也就是说打印出的结果是sunlight;*/
}
public void setAge(B myb)
{
myb.sex="sunlight";
}
}
class B
{
public int sex;
};
package com.j2se.myproblem;
public class GiveAddressOrValue {
public static void main(String args[])
{
char[] ch = new char[]{'1','2','3'};
String name = "ruby";
Demo demo = new Demo("java");
run(ch,name,demo);
System.out.println(ch);
System.out.println(name);
System.out.println(demo);
}
public static void run(char[] ch,String name,Demo de){
ch = new char[]{'a','b'};
name = "solejava";
de.setName("oracle"); //使用这句,会改变main中demo的状态
//de = new Demo("oracle"); //使用该句,依然不会改变main中的demo状态
}
}
class Demo{
private String name;
public Demo(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
@Override
public String toString() {
return this.name;
}
}
/***运行结果:
123
ruby
oracle
**/
我想说的是,其实所有的方法调用传递的都是值传递,也就是说方法的形参就是实参的一个副本而已,关键在于形参和实参是什么类型的,如果形参是对象引用类型,那么传递的就是实参的一个对象副本。
相信大家在看到上面的demo和de之后,及其在方法执行之后对各自的影响。其余就不多说了,大家自己试试就知道了。
{
a="111111";
}
public static void test2(String b)
{
b=new String("22222");
}
在这两个方法中的变量a,b并不是类的成员变量,而是这个方法的局部变量,在上面红色部色定义的.所以在方法内部即使改变了a,b的引用,当这两个方法调用完之后,这两个局部变量在栈空间中分配的空间就消失了.
而在输出时:
System.out.println("结果A:"+a);
System.out.println("结果B:"+b);
a,b为类的成员变量和这个类似
class A {
int a;
int b;
A(int a,int b){
this.a = a;
this.b = b;
}
}
如果在构造方法中不写this,那就是把局部变量的值a给局部变量a