以前看过一些资料说:
java 方法传递参数时,
如果参数类型是基本类型,java采用值传递,方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值;
如果参数类型为对象类型,java采用引用传递,也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。但今天本人遇到了一个问题,很迷惑,请各位解释下,问题:public class Book { private String name = null; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}public class ParseHtml {
public void bookxiugai(Book book){
book = new Book();
}
public static void main(String[] args) {
ParseHtml p = new ParseHtml();
Book book = null;
p.bookxiugai(book);//方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,
System.out.println(book);
}
}问题:p.bookxiugai(book);//方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,可是打印却为null,为什么?
请高手不吝赐教!!!!
java 方法传递参数时,
如果参数类型是基本类型,java采用值传递,方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值;
如果参数类型为对象类型,java采用引用传递,也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。但今天本人遇到了一个问题,很迷惑,请各位解释下,问题:public class Book { private String name = null; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}public class ParseHtml {
public void bookxiugai(Book book){
book = new Book();
}
public static void main(String[] args) {
ParseHtml p = new ParseHtml();
Book book = null;
p.bookxiugai(book);//方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,
System.out.println(book);
}
}问题:p.bookxiugai(book);//方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,可是打印却为null,为什么?
请高手不吝赐教!!!!
book = new Book();
}你给new出来了
book = new Book();
}
不是传递的问题,是作用域的问题。book的定义,你在一个方法内定义。
代码的写的有问题,变量的作用域。
不是new不new的问题。
你在这个方法体内,输出week,它不是空的。
他传得这个对象的引用,充当了方法体内的变量。
作用域的问题。
// this is the contructor of Book class
public Book(String bookName)
{
this.name = bookName
}
// main class
public static void main (String [] args){ Book book = new Book("Harry Porter");
}// understand?
你再看看Object的toString方法就知道了
return getClass().getName() + "@" + Integer.toHexString(hashCode());
如果不是按引用传递,应该报空指针的。
book = null;
这个时候,book这个引用对应的是一个空地址2. 在方法里,你使用new Book();
这个时候,你复制参数book引用地址发生了变化,而你原来的那个book地址是没有发生变化的,依然是null。
class Book { private String name = null; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}public class ChanSu { public void bookxiugai(Book book) {
book.setName("affff");
} public static void main(String[] args) {
ChanSu p = new ChanSu();
Book book = new Book();
p.bookxiugai(book);// 方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,
System.out.println(book.getName());
}
}结果打印出:affff就知道这个形参的改变影响了实参的。
如果按照“实际上引用传递是要在对象为非null的情况下。”
public static void main(String[] args) {
ParseHtml p = new ParseHtml();
Book book = new Book();
p.bookxiugai(book);//方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,
System.out.println(book);
}
那么p.bookxiugai(book),这句话就有问题了,地址给他了不是空的,而且我又新new了一个对象给他,
对象的引用理所应当会被改变。
那么在main方法体内的,book是指向同一对象吗?
答案则不是。
当形参传入后,在方法体内当做变量使用的时候,它的性质就改变了,它就变成了,这个方法体内的一个
引用。
也就是说,
当形参传入后,作为变量使用的时候,它就重新的开辟了一个空间(引用),
这跟 空 和 非空 没有关系。
主要的是,在内存中,不是同一空间。 引用也会分配内存的。
public static void main(String args[]) {
ParseHtml p = new ParseHtml();
Book book = null;
p.param(book);
}
public void param(Book book) {
book = null;
}
在空引用的情况下,如何确认这两个空引用,不是在内存的同一空间中。 我知道是因为作用域的问题,可是我就像明白,怎么证明。
变量在堆栈上,出了作用域就被销毁了。
main 方法体内的book的作用域只在main 方法中。当方法
public void param(Book book) {
book = new Book();//当作为一个变量存放在方法体内的话,book的引用已经被销毁了。而book作为了一个变量,则有了自己的内存空间。则是一个新的引用。
}其实说了半天,都是作用域的问题。
建议好好看一下java的变量内存分布。
地址传递的前提是计算机语言支持指针java不支持指针,谈不上地址传递引用传递就是引用传递,引用是别名,也就类似于硬链接
把你的代码改如下
更容易理解public class Book {
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}public class ParseHtml {
private Book book;
public void bookxiugai(Book book){
this.book = book;
this.book = null;
}
public static void main(String[] args) {
ParseHtml p = new ParseHtml();
Book book = new Book();
p.bookxiugai(book);
/*方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为null*/
System.out.println(book);}
}
book = new Book();
}
你把申明 出来的book做参数传进去之后 是栈中的book 只想null 然后在new book 在指向new的对象
方法结束后 book 系统回收 . new 的对象没有引用 也等着GC回收. So 最后book 就是null 了
第一方面是变量作用域方面的,上面已经有人讲解过了。
另一方面是对引用变量和对象的理解。
Book book = null;
你只是声明了一个Book类型的引用变量,并且没有用它指向任何对象。
你传进去了以后,显然它还是什么都没有指。
然后就是作用域的问题了。你在bookxiugai里面new出来的那个对象,在这个函数结束后就出作用域了,然后就被GC回收了。
另外楼主的英语要加强啊修改可以用modify,哪怕change也比直接用拼音好呀~~
学软件你很有可能要参考很多英文资料。英文不好的话会影响你的进一步发展的。
建议你以后写代码的时候打开个有道词典之类的东西,单词不会的话就花个半分钟去查一下。
如果你看了《代码大全》你会知道用拼音去命名是绝对禁止的。
return name;
} public void setName(String name) {
this.name = name;
}
}public class ParseHtml {
public Book book = null; public void bookxiugai(Book _book){
_book = new Book();
} public static void main(String[] args) {
ParseHtml p = new ParseHtml();
p.bookxiugai(book);//方法参数是对象,按说应该是引用传递,方法的修改应该影响实际参数book,打印结果应该为非null,
System.out.println(book);
}
}
public void bookxiugai(Book book){
book = new Book();
}
例如,int a = 0; 这种情况下 假如a的内存地址是 0x00001 但这个地址存放的值是 0
假如将这个值传入一个方法
void test(int a){}
test(a);
在这个方法内部 接受到的 a的内存地址可能是 0x00002 但是它的值保存的是 0x00001这个地址保存的值,也就是0
这个时候你去修改 a = 1 实际上修改的是 0x00002 这个地址对应的值,所以方法外面的值是不会改变的对象引用传递:
例如 Object obj = new Object(); 假如obj的内存地址是 0x00001 但这个内存中存放的值是另外一个内存地址,也就是obj对象对应在堆中的地址 假如为 0x00003
加入将obj传入一个方法
void test(Object obj){}
test(obj);
这个时候,在方法内部接收到的 obj的内存地址可能是 0x00004(绝对不会是0x00001,0x00003) 但传入的值是0x00003
然后在方法内不些 obj = new Object(); 这个时候创建的对象在堆中地址假设是 0x00008
这条语句也就会设置 0x00004 的值为0x00008 ,实际上修改不了 0x00001也就是你传入进来的参数说的不是太清楚,不知道你是否能理解
首先:以下说法本人认为是正确的。
java 方法传递参数时,
如果参数类型是基本类型,java采用值传递,方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值;
如果参数类型为对象类型,java采用引用传递,也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。其次:
如果参数类型为对象类型,java采用引用传递,也称为传地址......影响实际参数的值;其意思说的是:影响的是对象的内容,和对象的引用改变是两码事;Book book = null; 和 book = new Book();的区别改变的是引用的值改变了,book 变量开始指向 null(暂且这样理解)后来指向 Book 对象的堆内存。所以:
Book book = null; 和 book = new Book(); 和 Book 对象内容的改变是两码事;是我刚开始理解错了。希望大家能够理解。本人结贴!