【黑马程序员】Java中方法的参数传递问题

2024-09-14

【黑马程序员】Java中方法的参数传递问题(精选5篇)

【黑马程序员】Java中方法的参数传递问题 第1篇

【黑马程序员】Java中方法的参数传递问题

最近有很多同学,就算是就业班毕业之后,还依然在问 java方法的调用中值的传递问题,实际参数究竟什么时候才会改变?接下来我们先由一个例子来引出大家的问题,请看如下例子,并回答 下面代码中的四个问题 public class Demo { public static void main(String[] args){ int a = 10;change(a);System.out.println(a);// 1:请问输出什么?

String str = “abc”;change(str);System.out.println(str);// 2:请问输出什么?

Student s = new Student(“张三”,13);System.out.println(s);// 输出 Student [name=张三, age=13] change(s);System.out.println(s);// 3:请问输出什么? change1(s);System.out.println(s);// 4:请问输出什么? }

public static void change(String s){ s = s+“def”;} public static void change(int a){ a = a + 10;} public static void change(Student s){ s = new Student(“李四”,14);} public static void change1(Student s){ s.setName(“李四”);s.setAge(14);} } 大家看完上面的题目之后,估计有很多同学能回答出前两问,1:输出10, 2:输出abc,因为这类的参数传递在咱们java基础课程的第5天和第13天都有讲到。但是虽然讲了,但

黑马程序员济南中心 编著

是有很多同学都没有充分的理解透彻,这也就是为什么大家回答不出 第三问 和 第四问 的原因。实际上第三问的答案是 3:输出Student [name=张三, age=13] 4:Student [name=李四, age=14]。下面我就给大家讲解一下。

首先用一句话来归纳java中参数传递:不管是基本类型还是引用类型: 形式参数做赋值操作的时候,实际参数不发生改变,如果在方法里面是改变形式参数内部的一些东西的时候 那么实际参数发生改变。1.不管是基本类型还是引用类型: 形式参数做赋值操作的时候,实际参数不发生改变

(当被调用的方法开始执行的时候,就从方法区里面把方法拿到了栈内存中,形式参数变量也根据传递过

去的值进行初始化,当方法用完了,那么该方法在栈内存中的变量也消失了。在所以也就是只在栈内存

中对方法里面变量进行了改变,是不影响实际参数的。而加减乘除、赋值[就算是引用类型之间的赋值,是

不是也只是在栈内存中把地址值进行的赋值]这一系列的赋值操作都是在栈内存中对方法里面变量进行了改

变,而方法执行完毕后 从栈内存中消失了,回到了调用这个方法 的 main方法栈内存中,实际参数原来是

什么 现在依然是什么)

2.如果在方法里面是改变形式参数内部的一些东西的时候 那么实际参数发生改变

(对于引用类型,它随着参数传递到方法里面去的是地址值,指向的是堆中的对象,如果在方法里面通过

这个地址值改变对象内部的一些属性,即使方法用完了,方法里面的变量的地址值的黑马程序员济南中心 编著

指向也消失了,但是

对象内部的一些属性还是已经改变了,这些属性不会消失[因为在堆内存中],所以实际参数还是会改变。如

果是基本类型,根本在堆内存中没有指向,基本类型都在栈内存或者常量池[值更不能被改变]中,所以基本

类型形式参数的改变无论如何是改变不了实际参数的)

3.看完上面的两句话和解释,相信大家还是觉得比较抽象,下面我给大家准备了一个代码案例,每一行代码都有对应的解释,看完下面的案例后估计大家就会真正的明白java中参数传递,参数改变时机的问题了

public class Demo2 { public static void main(String[] args){

int a = 10;int b = 20;

System.out.println(a+“ ”+b);//10 20 change1(a,b);//形式参数做赋值操作的时候,实际参数不发生改变

//基本类型一般都在栈内存中(所以 堆内存中没有指向 内部也就没有东西嘛),//所以值能做一些加减乘除、赋值的操作,//而做完了这些操作,就在占内存中消失了,所以不会影响实际参数 System.out.println(a+“ ”+b);//10 20

System.out.println(“-------------------”);

Student s = new Student();System.out.println(s);//Student [name=null, age=0]

change2(s);//详见方法内部注释

//如果在方法里面是改变形式参数内部的一些东西的时候 那么实际参数发生改变 System.out.println(s);//Student [name=hehe, age=1]

System.out.println(“-------------------”);

黑马程序员济南中心 编著

String string = “abc”;System.out.println(string);//abc

change3(string);//详见方法内部注释

//形式参数做赋值操作的时候,实际参数不发生改变 System.out.println(string);//abc

System.out.println(“-------------------”);

StringBuffer sb = new StringBuffer(“hello”);System.out.println(sb);//hello

change4(sb);//详见方法内部注释

//如果在方法里面是改变形式参数内部的一些东西的时候 那么实际参数发生改变 System.out.println(sb);//helloworld

System.out.println(“-------------------”);

int[] arr ={1,2,5,8,4,3};System.out.println(Arrays.toString(arr));//[1, 2, 5, 8, 4, 3] change5(arr,0,1);//详见方法内部注释

//如果在方法里面是改变形式参数内部的一些东西的时候 那么实际参数发生改变 System.out.println(Arrays.toString(arr));//[2, 1, 5, 8, 4, 3]

Arrays.sort(arr);System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 8]

System.out.println(“-------------------”);

StringBuffer sb1 = new StringBuffer(“abcd”);StringBuffer sb2 = new StringBuffer(“efgh”);change6(sb1,sb2);//详见方法内部注释 System.out.println(sb1);//abcd

//形式参数做赋值操作的时候,实际参数不发生改变

System.out.println(“-------------------”);Student s1 = new Student(“hehe”,1);Student s2 = new Student(“haha”,20);change7(s1,s2);//详见方法内部注释

//形式参数做赋值操作的时候,实际参数不发生改变

System.out.println(s1);//Student [name=hehe, age=1]

} private static void change7(Student s1, Student s2){ //引用类型s1指向的是一个地址值,s2也是指向的地址值,那么把s2的地址值赋给了s1,这

黑马程序员济南中心 编著

时候s1指向的地址

//值改变了,而s1内部(堆内存)的东西改变了吗?没有啊,等这个方法调用完毕了,地址值的指向也都消失了,//s1还是指向原来的地址值,原来的地址值内部(堆内存)的东西还是没有改变,所以 赋值操作不会影响实际参数 s1=s2;} private static void change6(StringBuffer sb1, StringBuffer sb2){ //引用类型sb1指向的是一个地址值,sb2也是指向的地址值,那么把sb2的地址值赋给了sb1,这时候sb1指向的地址

//值改变了,而sb1内部(堆内存)的东西改变了吗?没有啊,等这个方法调用完毕了,地址值的指向也都消失了,//sb1还是指向原来的地址值,原来的地址值内部(堆内存)的东西还是没有改变,所以 赋值操作不会影响实际参数 sb1=sb2;} private static void change5(int[] arr, int i, int j){ //引用类型arr指向的其实是一个地址值,那么通过地址值将对象内部(堆内存)的值发生改变了,//即使这个方法调用完毕了,s所代表的地址的指向消失了,那么对象的内部其实已经改变了,所以形式参数改变实际参数 int temp = arr[i];[/i] [i] arr = arr[j];[/i] [i] arr[j] = temp;[/i]

[i] }[/i] [i] private static void change4(StringBuffer sb){[/i] [i] //引用类型sb指向的其实是一个地址值,那么通过地址值将对象内部(堆内存)的字符长度改变了,[/i]

[i] //即使这个方法调用完毕了,s所代表的地址的指向消失了,那么对象的内部其实已经改变了,所以形式参数改变实际参数[/i] [i] sb.append(“world”);[/i]

[i] }[/i] [i] private static void change3(String string){[/i] [i] //String也是一个引用类型,但是String的值是放在了常量池中,而且常量池中的值是不能被改变的[/i]

[i] //在方法里面这个string所代表的是常量池中值得地址值,那么我说string += “def”这句话在常量池中其实是这样的:“找有没有abcdef,如果有就把abcdef的地址值赋给string[/i]

[i] //如果没有就在常量池中创建一个abcdef 并把地址值赋给string”。然而当我方法用完了 string代表的地址值的指向也消失了,那么原来main方法中的string

黑马程序员济南中心 编著

也不发生改变[/i]

[i] string += “def”;[/i]

[i] }[/i] [i] private static void change2(Student s){[/i] [i] //引用类型s指向的其实是一个地址值,那么通过地址值将对象内部(堆内存)的属性改变了,[/i]

[i] //即使这个方法调用完毕了,s所代表的地址的指向消失了,那么对象的内部其实已经改变了,所以形式参数改变实际参数[/i] [i] s.setName(“hehe”);[/i] [i] s.setAge(1);[/i]

[i] }[/i] [i] private static void change1(int a, int b){[/i] [i] int temp = a;[/i] [i] a= b;[/i] [i] b=temp;[/i]

[i] }[/i] [i]} 当大家看完这个例子的时候,相信很多同学有一种恍然大悟的感觉,终于搞明白为什么参数传递的时候,实际参数有什么改变有时候不改变。如果大家还有什么疑问需要一起交流,请在下面直接给我留言就可以了,或者直接来济南黑马程序员找大山哥哥来咨询,我会亲自给同学讲解

黑马程序员济南中心 编著

【黑马程序员】Java中方法的参数传递问题 第2篇

在Java语言中,学好集合是非常重要的,下面简单的对集合进行总结,以便大家学习,有

问题再相互交流。

集合框架图

在集合框架图中可以看出,Collection接口中主要有两个子接口,分别是List和Set。List集合的特点是元素有序、包含重复元素,Set集合的特点是元素无序、不包含重复元素。Map集合中存储的是键值映射关系,元素都是成对出现的。Map接口的主要子接口有HashMap和TreeMap。

总结ist有顺序有重复没有排序,set无重复有排序,map的key也和set一样。

List接口

List : 特点是元素有序、可以包含重复元素。它有两个实现类分别是:ArrayList和LinkedList。

ArrayList : 内部维护一个数组结构,允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。

LinkedList : 内部维护了一个双向链表结构,即通过节点之间彼此连接来实现的,每一个节点都包含前一个节点和后一个节点的引用。当一个新节点插入时,只需要修改其中保持先后关系的节点引用即可,这样的存储结构保证了LinkedList集合在增删元素时效率非常高。

Set接口

Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面的List。实际上Set就是Collection只是行为不同,也就是说Set集合并没有对Collection接口进行扩充,只是比collection接口要求更加严了。

Set : 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。

HashSet : 为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。

TreeSet : 保存有序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。

LinkedHashSet : 具有HashSet的查询速度,且内部使用链表维护元素的顺序。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

Map接口

Map用于保存具有映射关系的数据,因此Map集合里存储两组值,一组用于保存Map里的key,另一组用于保存Map中的value,key和value都可以是任意引用类型数据,其中,作为key的值是不允许重复的,而value中可以出现重复。Map : 维护“键值对”的关联性,使你可以通过“键”查找“值”。

HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显著提高性能。HashMap集合是基于哈希表的Map接口实现,并允许使用null键null值,但必须保证键的唯一性。

LinkedHashMap : 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序。而在迭代访问时发而更快,因为它使用链表维护内部次序。

TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(顺序由Comparabel或Comparator决定)。TreeMap的特点在于,你得到的结果是经过排序的。

Hashtable线程安全,但是存取速度很慢,且不允许存放null键null值,目前基本上被hashMap类所取代。Hashtable有一个重要的子类Properties。

Properties:java.util.Properties;key和value都是String类型,用来读配置文件。继承自Hashtable,比 Hashtable 更严格 属性列表中每个键及其对应值都是一个字符串。常用方法 String getProperty(String?key)和 setProperty(String key,String value);

用法:我在D盘下建了一个名为 AA.dat 的文件,文件的内容为:

name=ch

password=12345

【黑马程序员】Java中方法的参数传递问题 第3篇

这个启动项是微软提供的一种实现应用程序的方法。

重写这个启动项:

现在,该应用程序已经可以传递参数了。

先对Form1进行重载

重载为:

这样就可以传递参数进来了。然后再对MAIN函数进行处理:

改写为:

这样就初步实现了带参数的应用程序的基本结构。

执行下看看效果,普通的执行,可以看到的提示是【普通模式】,当在CMD下面切换到改程序所在的活页夹时输入该应用程序名参数,比如:ArgExp.exeS,会提示【特殊模式】。

至此已经给应用程序带上了参数。

可是这个程序每次都要到CMD下去运行很不方便。带参数的应用程序是不是到此结束了,下面进行分析。在互联网上经常看到点击一个发送邮件的连接连接,系统就自动调用outlook来发送邮件了。而outlook也是一个应用程序。

在网页里面,超链接的格式为:mailto:test@test.com。也就是说:系统定义了一个叫MailTo的协议,然后将参数test@test.com传递给了outlook。

从注册表找到MailTo协议:将其导出。

内容如下:

到这里就找到了实现它的方法了。

于是,就重写了一个注册文件:

内容如下:

将这个导进注册表,然后编写一个Html文件

执行一下,看到了提示【特别模式】,完成了该协议Fairy4To:

然后在程序里面看MSGBOX参数,发现参数的内容是Fairy4to:-S。但是,实际上本文传递的参数应该是-S,那就应该在程序里面进行处理了。

这样就实现了通过网页的方式来传递参数。点一个连接,也可以导航到应用程序的某个Form,超链接不再是程序的专利了。

参考文献

[1]石晶,龚震宇,裘杭萍,等.一种更稳定的链接分析算法———子空间HITS算法[J].吉林大学学报:理学版,2003(1).

[2]宋建康,张礼平.Web结构挖掘算法探讨[J].华东理工大学学报,2003(5).

[3]黄英铭.Web结构挖掘及HITS算法分析[J].计算机与现代化,2007(7).

【黑马程序员】Java中方法的参数传递问题 第4篇

关键词:参数传递;传值;传地址;传引用

中图分类号:TP393.08 文献标识码:A文章编号:1007-9599 (2011) 07-0000-01

Parameters Transfer Mode Analysis in C++,Java

Wang Huiyuan

(China University of Mining&Technology,School of Computer Science&Technology,Xuzhou221008,China)

Abstract:Parameter transfer have many ways in C ++ and Java,and different ways have different effect.The paper analyzes and compares the value transfer,address transfer and reference transfer,and beginners can understand it accurately and deeply.

Keywords:Parameter transfer;Value transfer;Address transfer;Reference transfer

一、引言

一个较大的程序一般由若干程序模块组成,每个模块完成一定相对独立的功能。我们一般将这种模块成为函数。函数通过相互之间调用实现程序所要完成的任务。而在这个过程中,参数作为函数间数据交换的通道起了重要作用。因此在程序设计时,能够准确和灵活的使用函数参数传递的机制是很重要的。

二、参数传递

下面通过对C++和Java两种常用的高级语言的参数传递机制做些分析,使我们对参数传递有更明确的理解。

(一)C++参数传递机制

1.按值传递。程序执行时,在栈空间分别为主函数和被调用函数分配一定空间,实参和形参各自占有独立的存储单元,调用时将实参的值拷贝给形参,在被调用的函数执行时,访问的是形参单元,函数调用结束后,形参所占据的存储空间就被系统收回了,所以形参的变化并不会导致主函数中实参的改变。实例如下:

#include

using namespace std;

void Change(int a)

{ a=5;}

int main()

{ int a =2;

cout<<”调用函数前a的值为:”<

Change(a);

cout<<”调用函数后a的值为:”<

return 0;

}

调用函数前a=2;调用后a=2,a的值没有改变。

2.按地址传递。上述按值传递中被调函数参数的改变并不能影响实参的改变,如果我们想达到改变实参的目的,可以选择按指针传递,它的作用是将一个变量的地址传送给别调用函数的形参。

#include

using namespace std;

void Change(int *a)

{ *a=5;}

int main()

{ int a =2;

cout<<"调用函数前a的值为:"<

Change(&a);

cout<<"调用函数后a的值为:"<

return 0;

}

调用函数之前a=2;调用之后a=5。

可以看出,实参的值发生了改变。这是因为调用函数时将实参的地址传递给形参。在被调函数里,对形参的操作,实际上就是对主调函数里的实参变量进行操作。所以按地址传递通过调用函数使变量的值发生变化,在主调函数中可以使用这些改变了的值。

3.按引用传递。C++程序中函数还可以通过引用进行参数传递,使用引用传递参数与传递指针的效果一样。如果将形参定义为引用,形参相当于实参的别名,所以对形参的操作等同于对实参变量的操作。系统没有为形参分配内存空间,形参和实参对应相同的内存空间,改变形参的值实际就是改变实参的值。实例如下:

#include

using namespace std;

void Change(int &a)

{ a=5;}

int main()

{ int a =2;

cout<<"调用函数前a的值为:"<

Change(a);

cout<<"调用函数后a的值为:"<

return 0;

}

调用函数前a=2;调用函数后a=5,实参也发生了变化。

上述参数按地址传递和按引用传递很类似,但也有一些不同:

(1)使用引用类型不必在被调用函数中声明形参是指针变量,即不用另外开辟内存单元;

(2)在主函数中调用函数时,实参不必用变量的地址,而直接使用变量名。这种方式比使用指针变量简单,直观、方便。

(二)Java参数传递机制

Java程序中参数主要有按值传递和按引用传递两种方式。按值传递与C++中的相同。按引用传递主要是针对对象操作,它传递的是一个对象句柄的拷贝。也就形成了多个变量操作一个对象的局面。任何一个针对句柄操作的变量,都会影响到其他的变量。

public class Change {

int a;

public static void main(String[] args) {

Change c=new Change();

c.a=2;

System.out.println("调用函数之前a:"+c.a);

change(c);

System.out.println("调用函数之后a:"+c.a);

}

public static void change(Change c)

{ c.a=5;}

}

调用函数前a=2;调用函数后a=5。

三、结束语

本文系统分析了几种参数传递机制的作用和影响,使我们在程序设计中能更准确的使用参数传递,使一些对参数传递概念模糊的人能更全面的理解参数传递。

参考文献:

[1]谭浩强.C++程序设计[M].北京:清华大学出版社,2008

【黑马程序员】Java中方法的参数传递问题 第5篇

上一篇:秀美的风景700字作文下一篇:为幸福下一个定义