本文用一下代码说明:
简单字符串String:
package luojing;
public class StringDemo
{
public static void main(String[]args)
{
String str=new String("hello");
//调用函数改变str的值
change(str);
System.out.println(str);
}
public static void change(String str1)
{
str1+="luojing";
}
}
程序执行结果: hello
StringBuffer:
public class StringDemo
{
public static void main(String[]args)
{
StringBuffer str=new StringBuffer("hello");
//调用函数改变str的值
change(str);
System.out.println(str);
}
public static void change(StringBuffer str1)
{
str1.append("luojing");
}
}
程序运行结果 :hello luojing 这个时候str的内容就改变了。
将上面的StringBuffer换成我们自己定义的对象:
public class test
{
public static void main(String[] args)
{
Demo demo=new Demo("hello");
//调用函数该变demo.name的值
change(demo);
System.out.println(demo.getName());
}
public static void change(Demo d)
{
d.setName("luojing");
}
}
class Demo
{
private String name;
public Demo(String s)
{
name=s;
}
public String getName()
{
return name;
}
public void setName(String str)
{
name=str;
}
}
程序运行结果: luojing 和我们使用StringBuffer对象是效果相同。
我们再对change()方法做一些修改:
package luojing;
public class test
{
public static void main(String[] args)
{
Demo demo=new Demo("hello");
//调用函数该变demo.name的值
change(demo);
System.out.println(demo.getName());
}
public static void change(Demo d)
{
Demo d1=new Demo("hello java");
d=d1;
}
}
class Demo
{
private String name;
public Demo(String s)
{
name=s;
}
public String getName()
{
return name;
}
public void setName(String str)
{
name=str;
}
}
运行结果: hello
可以看到,虽然我们在change()方法中对d进行了改变,而实际的对象demo并没有改变。
class Foo {
private int x;
public Foo(int x) {
this.x = x;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
public class Submit {
static Foo fooBar(Foo foo) {
foo = new Foo(100);
return foo;
}
public static void main(String[] args) {
Foo foo = new Foo(300);
System.out.print(foo.getX() + "-");
Foo fooFoo = fooBar(foo);
System.out.print(foo.getX() + "-");
System.out.print(fooFoo.getX() + "-");
foo = fooBar(fooFoo);
System.out.print(foo.getX() + "-");
System.out.print(fooFoo.getX());
}
}
What is the output of the program shown in the exhibit?
A. 300-100-100-100-100
B. 300-300-100-100-100
C. 300-300-300-100-100
D. 300-300-300-300-100
Answer: B
涉及知识点:
1.Java中的参数传递有传值和传址两种;
2.基本类型和String型作为参数时,为传值方式,只把值传入方法,不管在方法中怎么处理这个参数,原值不变;
3.其他引用类型作为参数时,为传址方式,将指向内存中的地址传入方法,方法中此内存地址中的值发生变化时,原值也会改变;
4.例外:
(1)如果引用类型的对象通过传址方式将其指向内存中的地址传入方法后,方法中使用new关键字重新给参数赋值时,会在内存中重新开辟空间,参数指向新的内存空间,此时参数和原对象指向的就不是同一个地址了,参数值的变化不会改变原值;
(2)String型是引用类型,但是String型作为参数,是传值方式,可以通过以下两种方式来理解:
<1>String本质上是基本类型的char[],基本类型作为参数时,为传值方式;
<2> 字符串在内存中是存储在堆中的一个常量,String对象指向内存中这个常量的地址,通过传址方式将地址传入方法后,方法中如果通过字符串给参数赋值,则会重新在堆中创建一个字符串常量,并指向这个地址,原值依然指向原来的字符串常量地址,参数值的变化不会改变原值,如果通过new关键字给参数赋值,参见 (1)中的解释。
解析:
1.“Foo foo = new Foo(300);”,此时foo.getX()的值为300;
2.“Foo fooFoo = fooBar(foo);”,因为Foo是引用类型,main方法中的foo通过传址的方式将其指向的地址传给fooBar方法中的foo,此时两个foo指向同一个地址,foo.getX()的值都为300;通过“new Foo(100)”给fooBar方法中的foo赋值后,该foo重新指向了一个新的地址,foo.getX()的值为新地址中的值100,而main方法中的foo仍然指向原来的地址,foo.getX()的值没有改变,仍为 300;fooBar将foo的值返回给fooFoo,因此fooFoo.getX()的值为100;
3.“foo = fooBar(fooFoo);”,同2中的解释,foo.getX()的值变为100,fooFoo.getX()的值没有变化,仍为100;