深入理解Java中方法的参数传递机制

深入理解Java中方法的参数传递机制
深入理解Java中方法的参数传递机制

形参和实参

我们知道,在Java中定义方法时,是可以定义参数的,比如:

public static void main(String[] args){

}

这里的args就是一个字符串数组类型的参数。

在程序设计语言中,参数有形式参数和实际参数之分,先来看下它们的定义:

形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数,简称“形参”。

实际参数:在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”,简称“实参”。

举个栗子:

public class ParamTest {

public static void main(String[] args) {

ParamTest pt = new ParamTest();

// 实际参数为“张三”

pt.sout("张三");

}

public void sout(String name) {

// 形式参数为name

System.out.print(name);

}

}

上面例子中,ParamTest类中定义了一个sout方法,该方法有个String类型的参数name,该参数即为形参。在main方法中,调用了sout方法,传入了一个参数“张三”,该参数即为实参。

那么,实参值是如何传入方法的呢?这是由方法的参数传递机制来控制的。

值传递和引用传递

参数传递机制有两种:值传递和引用传递。我们先来看下程序语言中是如何定义和区分值传递和引用传递的:

值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

那么,在我们大Java中,到底是值传递还是引用传递呢?

Java中是值传递还是引用传递?

有了上面的概念,我们就可以一起来探究一下,Java中方法参数到底是值传递还是引用传递了。

先看如下代码:

public class ParamPass1 {

public static void main(String[] args) {

ParamPass1 p = new ParamPass1();

int i = 10;

System.out.println("pass方法调用前,i的值为=" + i);

p.pass(i);

System.out.println("pass方法调用后,i的值为=" + i);

}

public void pass(int i) {

i *= 3;

System.out.println("pass方法中,i的值为=" + i);

}

}

上面代码中,我们在类中定义了一个pass方法,方法内部将传入的参数i的值增加至3倍,然后分别在pass方法和main方法中打印参数的值,输出结果如下:

pass方法执行前,i的值为=10

pass方法中,i的值为=30

pass方法执行后,i的值为=10

从上面运行结果来看,pass方法中,i的值是30,pass方法执行结束后,变量i的值依然是10。

可以看出,main方法里的变量i,并不是pass方法里的i,pass方法内部对i的值的修改并没有改变实际参数i的值,改变的只是pass方法中i的值(pass方法中,i=30),因为pass 方法中的i只是main方法中变量i的复制品。

因此同学们很容易得出结论:Java中,一个方法不可能修改一个基本数据类型的参数,所以是值传递。

然而,结论下的还太早,因为方法参数共有两种类型:

基本数据类型

引用数据类型

前面看到的只是基本数据类型的参数,那对于引用类型的参数,又是怎么样的呢?看如下代码:

public class ParamPass2 {

public static void main(String[] args) {

ParamPass2 p = new ParamPass2();

User user = new User();

user.setName("张三");

user.setAge(18);

System.out.println("pass方法调用前,user=" + user.toString());

p.pass(user);

System.out.println("pass方法调用后,user=" + user.toString());

}

public void pass(User user) {

user.setName("李四");

System.out.println("pass方法中,user = " + user.toString());

}

}

class User {

/**

* 姓名

*/

private String name;

/**

* 年龄

*/

private int age;

public String getName() {

return name;

}

public void setName(String name) {

https://www.360docs.net/doc/f09522869.html, = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "User{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

上面代码中,定义了一个User类,在main方法中,new了一个新的User对象user,然后给user对象的成员变量赋值,pass方法中,修改了传入的user对象的属性。

运行main方法,结果如下:

pass方法调用前,user= User{name=‘张三’, age=18}

pass方法中,user = User{name=‘李四’, age=18}

pass方法调用后,user= User{name=‘李四’, age=18}

经过pass方法执行后,实参的值竟然被改变了!!!那按照上面的引用传递的定义,实际参数的值被改变了,这不就是引用传递了么?

有同学可能会说:难道在Java的方法中,在传递基本数据类型的时候是值传递,在传递引用数据类型的时候是引用传递?

其实不然,Java中传递引用数据类型的时候也是值传递。

为什么呢?

先给大家说一下概念中的重点:

值传递,是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递,是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

总结下两者的区别:`

值传递引用传递

根本区别会创建副本不会创建副本

所以函数中无法改变原始对象函数中可以改变原始对象

敲黑板:复制的是参数的引用(地址值),并不是引用指向的存在于堆内存中的实际对象。main方法中的user是一个引用(也就是一个指针),它保存了User对象的地址值,当把user 的值赋给pass方法的user形参后,即让pass方法的user形参也保存了这个地址值,即也会引用到堆内存中的User对象。

上面代码中,之所以产生引用传递的错觉,是因为参数保存的是实际对象的地址值,你改变的只是地址值指向的堆内存中的实际对象,并没有真正改变参数,参数的地址值没有变。下面结合生活中的场景,再来深入理解一下值传递和引用传递。

你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。

你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。但是,不管上面哪种情况,你的朋友拿着你给他的钥匙,进到你的家里,把你家的电视砸了。那你说你会不会受到影响?

我们在pass方法中,改变user对象的name属性的值的时候,不就是在“砸电视”么。你改变的不是那把钥匙(地址值),而是钥匙打开的房子(地址值对应的实际对象)。

那我们如何真正的改变参数呢,看如下代码:

public class ParamPass3 {

public static void main(String[] args) {

ParamPass3 p = new ParamPass3();

User user = new User();

user.setName("张三");

user.setAge(18);

System.out.println("pass方法调用前,user= " + user.toString());

p.pass(user);

System.out.println("pass方法调用后,user= " + user.toString()); }

public void pass(User user) {

user = new User();

user.setName("李四");

user.setAge(20);

System.out.println("pass方法中,user = " + user.toString());

}

}

class User {

/**

* 姓名

*/

private String name;

/**

* 年龄

*/

private int age;

public String getName() {

return name;

}

public void setName(String name) {

https://www.360docs.net/doc/f09522869.html, = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "User{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

在这段代码中,pass方法中,我们真正的改变了user参数,因为它指向了一个新的地址(user = new User()),即参数的地址值改变了。运行结果如下:

pass方法调用前,user= User{name=‘张三’, age=18}

pass方法中,user = User{name=‘李四’, age=20}

pass方法调用后,user= User{name=‘张三’, age=18}

从结果看出,对参数进行了修改,没有影响到实际参数。

所以说,Java中其实还是值传递的,只不过对于引用类型参数,值的内容是对象的引用。

参数传递方式

引用在函数参数传递中的作用 传递参数有三种方法:1,传递对象本身。2,传递指向对象的指针。3,传递对象的引用。 (1)传值方式 ①传给被调用函数的是整型、长整型、浮点型或双精度型变量。被调用的函数得定义相应的变量为形参。 ②传给被调用函数的是结构变量。被调用函数得定义结构变量为形参。 ③传给被调用函数的是结构变量的成员。被调用函数得定义与该成员同类的变量为形参。 #include "stdio.h" ?#include ?main( ) ?{ ?void swap(int pt1,int pt2); ?int a,b; ?scanf("%d, %d", &a,&b); ?swap(a,b); ?printf("\n%d,%d\n",a,b); ?} ?void swap(int pt1,int pt2) ?{int p; p=pt1; pt1=pt2; pt2=p; } ?

#include "stdio.h" void swapint(); int a,b; void main() { a = 5, b = 10; swapint(); printf("%d\n%d\n",a,b); } void swapint() { int temp; temp=a; a=b; b=temp; } (2)传址方式 ①传给被调用函数的是变量的地址。被调用函数得定义指针变量为形参。 ②传给被调用函数的是数组的地址即数组名。被调用的函数得定义数组或指针变量为形参。 ③传给被调用函数的是函数的地址即函数名称。被调用函数得定义指向函

数的指针变量为形参。④传给被调用函数的是结构的地址。被调用函数得定义结构指针为形参。 #include "stdio.h" ?#include ?main( ) ?{ ?void swap(int *pt1,int *pt2); ?int a,b,*p1,*p2; ?scanf("%d, %d", &a,&b); ?p1=&a;p2=&b; ?swap(p1,p2); ?printf("\n%d,%d\n",a,b); ?} ?void swap(int *pt1,int *pt2) ?{int p; p=*pt1; *pt1=*pt2; *pt2=p; } #include "stdio.h" void swapint(int *a,int *b); void main() { int a = 5, b = 10;

Java中传值与传引用的三种情况

java传值与传引用的三种情况大家先看一个例子: public class Example{ String str=new String("good"); char[]ch={'a','b','c'}; public static void main(String args[]){ Example ex=new Example(); ex.change(ex.str,ex.ch); System.out.print(ex.str+" and "); System.out.print(ex.ch); } public void change(String str,char ch[]){ str="test ok"; ch[0]='g'; } } 看看输出结果? good and gbc java中没有了c++中这样的引用符号,也没像c#中那样提供了out与ref 那么它是怎么做的呢 做什么事情都要去除例外的东西,String类就是此类问题的一个特殊情况 为什么特殊呢?

因为它是一个引用类型,确执行的是值传递。这样说有些抽象,还是举个例子吧 值传递: class Str { public static void main(String[] args) { int i = 900; System.out.println(i); changeInt(i); System.Out.println(i); } public static void changeInt(int s) { s = 34234; } } 结果: 900 900 这就是所谓的值传递。i把自己的副本给了函数changeInt的形参,而在changeInt中虽然将s赋值34234。但是对原来的i值并没有影响,因为它所修改的只是i的copy品而已。

C#中方法的参数有四种类型

C#中方法的参数有四种类型 1. 值参数(不加任何修饰符,是默认的类型) 2. 引用型参数(以ref 修饰符声明) 3. 输出参数(以out 修饰符声明) 4. 数组型参数(以params 修饰符声明) 1. 值传递: 值类型是方法默认的参数类型,采用的是值拷贝的方式。也就是说,如果使用的是值类型,则可以在方法中更改该值,但当控制传递回调用过程时,不会保留更改的值。 使用值类型的例子如:(下面的Swap()未能实现交换的功能,因为控制传递回调用方时不保留更改的值) using System; class Test { static void Swap(int x, int y) { int temp = x; x = y; y = temp; } static void Main() { int i = 1, j = 2; Swap(i, j); Console.WriteLine("i = {0}, j = {1}", i, j); } } /* * 输出结果为: i=1, j=2 * 未能实现Swap()计划的功能 */ 2. 引用传递(ref类型) ref关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。 2.1. 若要使用ref 参数,则方法定义和调用方法都必须显式使用ref关键字。 2.2. 传递到ref 参数的参数必须最先初始化。这与out 不同,out 的参数在传递之前不需要显式初始化。 2.3. 如果一个方法采用ref 或out 参数,而另一个方法不采用这两类参数,则可以进行重载。

相关实例如下: using System; class Test { static void Swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } static void Main() { int i = 1, j = 2; Swap(ref i, ref j); Console.WriteLine("i = {0}, j = {1}", i, j); } } /* * 引用类型实现了Swap()计划的功能: * 输出为: * i = 2, j =1 */ 3. 输出类型(out类型) out 关键字会导致参数通过引用来传递。这与ref 关键字类似。 与ref 的不同之处: 3.1. ref 要求变量必须在传递之前进行初始化,out 参数传递的变量不需要在传递之前进行初始化。 3.2. 尽管作为out 参数传递的变量不需要在传递之前进行初始化,但需要在调用方法初始化以便在方法返回之前赋值。 示例如下: using System; class Test { static void Swap(out int x, out int y) { //在这里进行了i和j的初始化

java中的值传递和引用传递

转载 原文地址:https://www.360docs.net/doc/f09522869.html,/clara/archive/2011/09/17/2179493.html Java中的值传递和引用传递 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。 Java参数,不管是原始类型还是引用类型,传递的都是副本(有另外一种说法是传值,但是说传副本更好理解吧,传值通常是相对传址而言)。 如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的值不会改变原始的值. 如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的值,那么在函数内的改变会影响到传入的参数。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以不会改变参数的值。 例: 1public class ParamTest { 2public static void main(String[] args){ 3/** 4 * Test 1: Methods can't modify numeric parameters 5 */ 6 System.out.println("Testing tripleValue:"); 7double percent = 10; 8 System.out.println("Before: percent=" + percent); 9 tripleValue(percent); 10 System.out.println("After: percent=" + percent); 11 12/** 13 * Test 2: Methods can change the state of object parameters 14 */ 15 System.out.println("\nTesting tripleSalary:"); 16 Employee harry = new Employee("Harry", 50000);

函数调用参数传递类型(java)的用法介绍.

函数调用参数传递类型(java)的用法介绍. java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清。 (一)基本数据类型:传值,方法不会改变实参的值。 public class TestFun { public static void testInt(int i){ i=5; } public static void main(String[] args) { int a=0 ; TestFun.testInt(a); System.out.println("a="+a); } } 程序执行结果:a=0 。 (二)对象类型参数:传引用,方法体内改变形参引用,不会改变实参的引用,但有可能改变实参对象的属性值。 举两个例子: (1)方法体内改变形参引用,但不会改变实参引用,实参值不变。 public class TestFun2 { public static void testStr(String str){ str="hello";//型参指向字符串“hello” } public static void main(String[] args) { String s="1" ;

TestFun2.testStr(s); System.out.println("s="+s); //实参s引用没变,值也不变 } } 执行结果打印:s=1 (2)方法体内,通过引用改变了实际参数对象的内容,注意是“内容”,引用还是不变的。 import java.util.HashMap; import java.util.Map; public class TestFun3 { public static void testMap(Map map){ map.put("key2","value2");//通过引用,改变了实参的内容 } public static void main(String[] args) { Map map = new HashMap(); map.put("key1", "value1"); new TestFun3().testMap(map); System.out.println("map size:"+map.size()); //map内容变化了 } } 执行结果,打印:map size:2 。可见在方法testMap()内改变了实参的内容。 (3)第二个例子是拿map举例的,还有经常涉及的是 StringBuffer : public class TestFun4 {

函数参数传递的原理

函数参数传递的原理 参数传递,是在程序运行过程中,实际参数就会将参数值传递给相应的形式参数,然后在函数中实现对数据处理和返回的过程,方法有按值传递参数,按地址传递参数和按数组传递参数。 形参:指出现在Sub 和Function过程形参表中的变量名、数组名,该过程在被调用前,没有为它们分配内存,其作用是说明自变量的类型和形态以及在过程中的作用。形参可以是除定长字符串变量之外的合法变量名,也可以带括号的数组名。 实参:实参就是在调用Sub 和Function过程时,从主调过程传递给被调用过程的参数值。实参可以是变量名、数组名、常数或表达式。在过程调用传递参数时,形参与实参是按位置结合的,形参表和实参表中对应的变量名可以不必相同,但它们的数据类型、参数个数及位置必须一一对应。 等号、函数名称、括弧和参数,是函数的四个组成部分。 函数“=SUM(1,2,3)”,1、2和3就是SUM函数的参数,没有参数1、2、3,函数SUM 则无从求值。 函数“=VLOOKUP(2,A:C,3,)”,没有参数2、A:C和3,函数VLOOKUP如何在A:C 区域查找A列中是2那一行第3列的数值? 当然,也有不需要参数的函数,如“=PI()”、“=NOW()”、“TODAY()”等。 函数参数传递的原理C语言中参数的传递方式一般存在两种方式:一种是通过栈的形式传递,另一种是通过寄存器的方式传递的。这次,我们只是详细描述一下第一种参数传递方式,另外一种方式在这里不做详细介绍。 首先,我们看一下,下面一个简单的调用例程: int Add (int a,int b,int c) { return a+b+c; }

C++中函数调用时的三种参数传递方式

在C++中,参数传递的方式是“实虚结合”。 ?按值传递(pass by value) ?地址传递(pass by pointer) ?引用传递(pass by reference) 按值传递的过程为:首先计算出实参表达式的值,接着给对应的形参变量分配一个存储空间,该空间的大小等于该形参类型的,然后把以求出的实参表达式的值一一存入到形参变量分配的存储空间中,成为形参变量的初值,供被调用函数执行时使用。这种传递是把实参表达式的值传送给对应的形参变量,故称这种传递方式为“按值传递”。 使用这种方式,调用函数本省不对实参进行操作,也就是说,即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。 [cpp]view plaincopy 1./* 2. pass By value 3.*/ 4.#include https://www.360docs.net/doc/f09522869.html,ing namespace std; 6.void swap(int,int); 7.int main() 8.{ 9.int a = 3, b = 4; 10. cout << "a = " << a << ", b = " 11. << b << endl; 12. swap(a,b); 13. cout << "a = " << a << ", b = " 14. << b << endl; 15.return 0; 16.} 17.void swap(int x, int y) 18.{ 19.int t = x; 20. x = y; 21. y = t; 22.}

如果在函数定义时将形参说明成指针,对这样的函数进行调用时就需要指定地址值形式的实参。这时的参数传递方式就是地址传递方式。 地址传递与按值传递的不同在于,它把实参的存储地址传送给对应的形参,从而使得形参指针和实参指针指向同一个地址。因此,被调用函数中对形参指针所指向的地址中内容的任何改变都会影响到实参。 [cpp]view plaincopy 1.#include https://www.360docs.net/doc/f09522869.html,ing namespace std; 3.void swap(int*,int*); 4.int main() 5.{ 6.int a = 3, b = 4; 7. cout << "a = " << a << ", b = " 8. << b << endl; 9. swap(&a,&b); 10. cout << "a = " << a << ", b = " 11. << b << endl; 12. system("pause"); 13.return 0; 14.} 15.void swap(int *x,int *y) 16.{ 17.int t = *x; 18. *x = *y; 19. *y = t; 20.} 按值传递方式容易理解,但形参值的改变不能对实参产生影响。 地址传递方式虽然可以使得形参的改变对相应的实参有效,但如果在函数中反复利用指针进行间接访问,会使程序容易产生错误且难以阅读。

java参数传递(经典)

java参数传递(超经典) (2009-02-20 14:47:22)转载 分类:Java 标签:杂 谈 Java中的参数传递机制一直以来大家都争论不休,究竟是“传值”还是“传址(传引用)”,争论的双方各执一词,互不相让。不但“菜鸟”们一头雾水,一些“老鸟”也只知道结果却说不出所以然来。我相信看过下面的内容后,你就会明白一些。 先看基本类型作为参数传递的例子: public class Test1 { public static void main(String[] args) { int n = 3; System.out.println("Before change, n = " + n); changeData(n); System.out.println("After changeData(n), n = " + n); } public static void changeData(int nn) { n = 10; } } 我想这个例子大家都明白,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点: Before change, n = 3 After changeData(n), n = 3 那么,我们现在来看看对象作为参数传递的例子,这也是大家争论的地方。public class Test2 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); } public static void changeData(StringBuffer strBuf) {

参数传递方式与解题应用(精)

VB过程中使用的参数分为实参和形参,简单的讲,在过程定义中给定的参数是形参,而在过程调用语句中给定的参数是实参。当调用一个有参数的过程时,形参和实参逐一匹配传递,根据传递方式不同,可分为按值和按地址两种。对参数传递方式的正确判别是过程学习中的一个难点,也是等级考试中的一个考点。 一、按值与按地址方式的内涵 按值传递参数,实质上是将实参的值复制一份给形参,因此形参获得的是实参的副本,当过程执行中对形参进行改变,并不会影响实参本身;按地址传递参数,实质上是将实参变量的地址传递给形参,因此形参与实参将指向同一内存单元,当过程执行中形参发生改变时,对应实参也将跟着改变。 二、参数传递方式判别方法 判断参数传递方式,不能单纯的看过程定义中形参前的修饰限定词有无By Val。参数传递到底采用何种方式,不仅取决于过程定义,还取决于过程调用,即与对应实参的具体形式也有很大关系。因此,应该从以下三个方面综合考虑: 1.形参是否为数组或者控件 2.形参前是否有ByVal修饰 3.对应实参是否为表达式或者值 具体判别方法,请见如下判别流程图。

三、不同传递方式对参数类型的要求 若参数按地址传递,则VB要求实参的数据类型与形参的数据类型完全一致;若参数按值传递,则实参数据类型不要求与形参完全一致,但是必须能够由VB 默认转化。 四、解题应用 (一)以江苏省计算机等级考试2001年春季的一道考题为例: 在应用程序中用“Private Function Fun(X As Integer, Y As Single)”定义了函数Fun. 调用函数Fun的过程中的变量I,J均定义为Integer型,能正确引用函数Fun的是____ ①Fun(I,J) ②Call Fun(I,3.65) ③Fun(3.14,234) ④Fun(“245”, “231.5”) A.①③ B.②③④ C.①②③ D.①②③④ 分析:

总结Java方法(函数)传值和传引用的问题

总结Java方法(函数)传值和传引用的问题 java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清。 (一)基本数据类型:传值,方法不会改变实参的值。 public class TestFun { public static void testInt(int i){ i=5; } public static void main(String[] args) { int a=0 ; TestFun.testInt(a); System.out.println("a="+a); } } 程序执行结果:a=0 。 (二)对象类型参数:传引用,方法体内改变形参引用,不会改变实参的引用,但有可能改变实参对象的属性值。 举两个例子: (1)方法体内改变形参引用,但不会改变实参引用,实参值不变。 public class TestFun2 { public static void testStr(String str){ str="hello";//型参指向字符串“hello” } public static void main(String[] args) { String s="1" ;

TestFun2.testStr(s); System.out.println("s="+s); //实参s引用没变,值也不变 } } 执行结果打印:s=1 (2)方法体内,通过引用改变了实际参数对象的内容,注意是“内容”,引用还是不变的。 import java.util.HashMap; import java.util.Map; public class TestFun3 { public static void testMap(Map map){ map.put("key2","value2");//通过引用,改变了实参的内容 } public static void main(String[] args) { Map map = new HashMap(); map.put("key1", "value1"); new TestFun3().testMap(map); System.out.println("map size:"+map.size()); //map内容变化了 } } 执行结果,打印:map size:2 。可见在方法testMap()内改变了实参的内容。 (3)第二个例子是拿map举例的,还有经常涉及的是 StringBuffer : public class TestFun4 {

PB窗口之间传递多参数的方法:

PB窗口之间传递多参数的方法: 在PowerBuilder中函数OpenWithParm,CloseWithReturn,OpenSheetWithParm,windowname.OpenUserObjectWithParm等都有一个在进行窗口操作(打开或者关闭)时存入Message消息对象的参数parameter或returnvalue。 消息对象Message有三个属性用于存储这些函数传递给窗口的数据(依赖于窗口操作时参数赋予的类型)。根据parameter / returnvalue参数数据类型的不同,该参数的值保存在Message对象的不同属性中。parameter / returnvalue参数的类型与使用的Message对象属性的对应关系如下表: 参数类型Message对象属性 Numeric(数值) Message.DoubleParm PowerObject(PB对象,包括用户自定义的结构数据类型) Message.PowerObjectParm String(字符串) Message.StringParm 应用程序根据OpenWithParm()等函数的parameter / returnvalue参数类型,从Message 消息对象的不同属性中提取该函数并传送给被打开窗口的值。 在PB中如果是传递一个参数,是很容易实现的。在调用脚本中,可以使用如下代码:openwithparm(w_wantparm,parmtotrans) 接着在打开窗口w_wantparm的open事件中键入: string ls_getparm ls_getparm=message.stringparm … 如果需要传递多个参数,可以使用如下两种方法: 方法一 定义结构变量:lstr_declaredstr,其中包含你想传递的各种参数: 变量名变量类型 ID Unsignedlong Name Character Email Character Homepage Character …… 在调用脚本中,使用如下代码: lstr_declaredstr lstr_parmtotrans lstr_parmtotrans.id=1 lstr_https://www.360docs.net/doc/f09522869.html,="panya" lstr_paramtotrans.email="panya@https://www.360docs.net/doc/f09522869.html," lstr_paramtotrans.homepage=" https://www.360docs.net/doc/f09522869.html,"; … openwithparm(w_wantparm,parmtotrans) 接下来在打开窗口w_wantparm的open事件中,获取结构信息: lstr_declaredstr lstr_getparm integer li_getid string ls_getname string ls_getemail string ls_gethomepage lstr_getparm = message.powerobjectparm li_getid = lstr_getparm.id ls_getname = lstr_https://www.360docs.net/doc/f09522869.html, ls_geemail = lstr_getparm.email ls_gethomepage = lstr_getparm.homepage … 其中,lstr_declaredstr为用户自定义结构数据类型,是值传送

过程和参数传递

1. 过程是子程序的一种形式,过程文件的形式为: PROCEDURE| function <过程名> [PARAMETERS<参数列表>] <语句系列> [RETURN[<表达式>]] [ENDPROC|endfunc] 2调用过程的方法 格式一: DO <过程名>|<文件名> WITH <实参表> 格式二: <过程名>|<文件名>(<实参表> ) 过程举例: SET TALK OFF CLEAR ?”主程序” DO tt1 DO tt2 RETURN PROCEDURE tt1 ?”过程…tt1” PROCEDURE tt2 ?”过程…tt2”

结果: 主程序 过程…tt1 过程…tt2 3.过程文件的打开 格式:SET PROCEDURE TO <过程文件名> 4.过程文件的关闭 关闭所有已打开的过程文件 SET PROCEDURE TO 关闭指定已打开的过程文件 RELEASE PROCEDURE <过程文件名1> [,<过程文件名2> …] 5.参数传递 (1)接收参数的命令 格式一:PARAMETERS <形参1>[,<形参2>,…] 格式二:LPARAMETERS <形参1>[,<形参2>,…] (2)调用带参数过程的命令 格式一: DO <过程名>|文件名WITH <实参1>[,<实参2>,…] 格式二: <过程名>|<文件名>(<实参1> [,<实参2>,…]) (3)说明 ①实参可以是常量、变量,也可以是一般般形式的表达式; ②调用时,实参传递给形参;

③形参数目不能少于实参数目; ④形参多于实参时,多余的形参初值为逻辑假。 (4)参数传递方式 格式:SET UDFPARMS TO VALUE|REFERENCE ①按值传递(传值):计算实参的值,将值放入内存变量,再将值传给形参变量。形参变量值的改变不会影响实参变量的取值。 ②按引用传递(传地址):把实参变量的地址传递给对应的形参变量,形参变量变化时,实参变量值也随之变化。 6应用举例 例1 X=1 Y=2 Do p3 with (x),(y) &&按值传递 ?x,y Procedure p3 Parameters a,b a=3 b=4 Return 结果: 1 2 分析:(x),(y) 表示按值传递给形参x,y,在p3中,虽然x=3,y=4发生了变化,但形参变量值的改变不会影响实参变量的取值。 所以输出的还是原来实参的值。

深入了解C语言(函数的参数传递和函数使用参数的方法)

深入了解C语言(函数的参数传递和函数使用参数的方法) C语言生成的代码在执行效率上比其它高级语言都高.现在让我们来看看C语言生成的代码具体是什么样子的.当你看完本文对于C语言的了解一定会更深一步了. 本文通过一个个实际案例程序来讲解C语言. 研究案例一 工具: Turboc C v2.0,Debug,MASM v5.0,NASM 实例C程序: /* example1.c */ char ch; int e_main() { e_putchar(ch); } 目标内容:C语言调用函数的方法与细节 我们使用的C编译器是16位的Turboc C v2.0,它生成的是16位的代码,比较简单,方便我们来研究.同时我们也需要用到DOS下的DEBUG来进行反汇编.由于我们很多案例中的程序并不是完整的C程序,所以Turboc下的Tlink并不能为我们生成目标程序,所以我将使用MASM 中的link.exe,同时里面的https://www.360docs.net/doc/f09522869.html,也可以为我们把exe文件转换成bin文件. 这个程序没有main函数,我们用e_main来代替main函数.这样我们能避开C语言对main函数进行一系列处理的代码.同样,我们也用e_putchar()来代替我们平常使用的putchar().这里"e"的意思就是"example". 没有了main函数,我们的C程序就没有了入口,所以在开始编译这段C代码之前,我还得写几行简单的汇编代码,通过它来作为我们程序的入口. ; C程序的入口start.asm [BITS 16] [global start] [extern _e_main] start: call _e_main 按照C语言的习惯,所以C总的名词都要自动在前面加一个"_"下划线.所以,我们在C中的e_main函数,如果要在汇编中调用,就变成了_e_main函数.这段汇编代码只有一句:call _e_main,就是调用我们在C中的e_main函数

java参数是如何传递的

java参数是如何传递的 总的来说,计算机语言给子程序传递参数的方法有两种。第一种方法是按值传递(call-by-value )。这种方法将一个参数值(value )复制成为子程序的正式参数。这样,对子程序的参数的改变不影响调用它的参数。第二种传递参数的方法是引用调用(call-by-reference )。在这种方法中,参数的引用(而不是参数值)被传递给子程序参数。在子程序中,该引用用来访问调用中指定的实际参数。这样,对子程序参数的改变将会影响调用子程序的参数。你将看到,根据传递的对象不同,Java 将使用这两种不同的方法。 在Java 中,当你给方法传递一个简单类型时,它是按值传递的。因此,接收参数的子程序参数的改变不会影响到该方法之外。例如,看下面的程序: // Simple types are passed by value. class Test { void meth(int i,int j) { i *= 2;j /= 2; } } class CallByValue { public static void main(String args[]) { Test ob = new Test(); int a = 15,b = 20; System.out.println("a and b before call: " +a + " " + b); ob.meth(a,b); System.out.println("a and b after call: " +a + " " + b); } } 该程序的输出如下所示: a and b before call: 15 20 a and b after call: 15 20 可以看出,在meth( ) 内部发生的操作不影响调用中a和b的值。它们的值没在本例中没有变为30和10。 当你给方法传递一个对象时,这种情形就会发生戏剧性的变化,因为对象是通过引用传递的。记住,当你创建一个类类型的变量时,你仅仅创建了一个类的引用。因此,当你将这个引用传递给一个方法时,接收它的参数将会指向该参数指向的同一个对象。这有力地证明了对象是通过引用调用传递给方法的。该方法中对象的改变确实影响了作为参数的对象。例如,考虑下面的程序: // Objects are passed by reference. class Test { int a,b; Test(int i,int j) {a = i;b = j; } // pass an object void meth(Test o) {

GUI界面之间的参数传递方法

GUI界面之间的参数传递方法(1-3) 今天,研究了一下不同GUI之间的参数传递方法,Matlab中GUI之间参数传递不如VC一样简单,易于理解,但是如果理解了,也是有章可循的,传说的具有六种方法,介绍其中的一种,如下所示: **运用gui本身的varain{}、varaout{}传递参数。 上面介绍的方法只是适用于主从GUI之间传递参数,即从主GUI调用子GUI,然后关掉子GUI,子GUI的参数就传递到了主GUI,比如子GUI的名称为subGUI, 设想的参数输入输出为:[out1, out2] = subGUI(in1, in2) 在subGUI的m文件中(由GUIDE自动产生),varargin 和varargout 分别是一个可变长度的cell数组(MATLAB帮助文件中有说明)。输入参数in1和in2保存在varargin中,输出参数out1,out2包含在varargout中;在subGUI的OpeningFcn中,读入参数,并用guidata 保存,即:handles.in1 = varargin{1};handles.in2 = varargin{2}; guidata(hObject, handles); 返回参数的设置: 1. 在GUI子程序的OpeningFcn函数的结尾加上uiwait(handles.figure1); figure1是subGUI 的Tag; 2. subGUI中控制程序结束(如"OK”和"Cancel"按钮)的callback末尾加上uiresume(handles.figure1),不要将delete命令放在这些callback中; 3. 在子GUI的OutputFcn中设置要传递出去的参数,如varargout{1} = handles.out1;varargout{2} = handles.out2;末尾添加delete(handles.figure1); 结束程序。 在GUI的OpenFcn中,如果不加uiwait,程序会直接运行到下面,执行OutputFcn。也就是说程序一运行,返回值就确定了,再在其它部分对handles.output作更改也没有效果了。加上uiwait后,只有执行了uiresume后,才会继续执行到OutputFcn,在此之前用户有充分的时间设置返回值。 通过以上设置以后,就可以通过[out1, out2] = subGUI(in1, in2) 的形式调用该子程序。 在一个GUI中调用另一个GUI时,主GUI不需要特别的设置,同调用普通的函数一样。在打开子GUI界面的同时, 主程序还可以响应其它的控件。不需要担心子GUI的返回值被传错了地方。 综上所述:一是,两点需要注意,uiwait和uiresume的使用位置和使用时机,二是,delete 句柄的位置…… 通过以上设置以后,就可以通过[out1, out2] = subGUI(in1, in2) 的形式调用该子程序。 在一个GUI中调用另一个GUI时,主GUI不需要特别的设置,同调用普通的函数一样。在打开子GUI界面的同时,主程序还可以响应其它的控件。不需要担心子GUI的返回值被传错了地方。 success……哈哈…… 方法二 延续以前的博文,今天介绍一下方法二,利用setappdata和getappdata函数进行不同GUI之

SpringMVC向页面传递参数的4种方式

SpringMVC向页面传递参数的4种方式 1、使用HttpServletRequest和Session 然后setAttribute(),就和Servlet 中一样 request.setAttribute(“user”,user_data); 2、使用ModelAndView对象 @RequestMapping("/login.do") publicModelAndView login(String name,String pass) { User user = userService.login(name,pwd); Map data = new HashMap(); data.put("user",user); return newModelAndView("success",data); } 3、使用ModelMap对象 ModelMap数据会利用HttpServletRequest的Attribute传值到success.jsp中 @RequestMapping("/login.do") public String login(String name,String pass ,ModelMapmodelMap) { User user =userService.login(name,pwd); modelMap.addAttribute("user",user); modelMap.put("name",name); return "success"; } Session存储,可以利用HttpServletReequest的getSession()方法 @RequestMapping("/login.do") Public String login (String name,Stringpwd,ModelMapmodel,HttpServletRequest request) { User user = serService.login(name,pwd); HttpSession session = request.getSession(); session.setAttribute("user",user); model.addAttribute("user",user); return "success"; } 4、使用@ModelAttribute注解

java参数传递时到底是值传递还是引用传递

java参数传递时到底是值传递还是引用传递(baidu搜集) 最近比较长一段时间以来,网上的IT同行里面比较流行“JAVA面试32问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解。 原题是:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 用google查询结果,得到答案基本上是:值传递。当时觉得挺纳闷儿,为什么连参数的内容都被修改了,怎么还能说是“值传递”呢?因为在传统的印象里(尤其是从C++过来以后),值传递都应该是不改变原参数的。 问问周围的同事,也大都这么讲,但是也都讲不清这种理论的根源是什么。我这个人有个毛病,有事情想不通时就会憋得难受,后来在《Thinking in Java》的一段内容(注解[1])里找到了自己的结论,我认为(《Thinking in Java》的作者也这么认为):可以说是值传递,也可以说是引用传递。 一,认为是值传递。得出这种结论的前提必须是“参数的值就是对该对象的引用,而不是对象的内容”,这句话可能有些费解,举个例子加以说明。 public class Paier { public static void main(String[] args) { Paier paier = new Paier(); paier.test();

} public void test() { TestClass para1 = new TestClass(); para1.setTest(new Integer(10)); TestClass result1 = test1(para1); System.out.println("para1 = " + para1.getTest()); System.out.println("result1 = " + result1.getTest()); TestClass para2 = new TestClass(); para2.setTest(new Integer(10)); TestClass result2 = test2(para2); System.out.println("para2 = " + para2.getTest()); System.out.println("result2 = " + result2.getTest()); } public TestClass test1(TestClass t) {

Action参数传递(精)

Action2的脚本如下: ' Input Parameters Message = Parameter("Msg") Msgbox Message ' Output Parameters If NOT Message = "" Then Parameter("ReturnMsg") = "The Message is " & Message Else Parameter("ReturnMsg") = "The Message is Empty!" End If ' RetuenValue ExitAction "HAHAHAHHAHA!!!!!" 'ExitAction Parameter("ReturnMsg") 3种调用Action的方法,Action1的脚本如下: ' 调用Action2,输入参数为“ Hello!”,把输出参数值写到ReturnMessage1变量 RunAction "Action2", oneIteration,"Hello!" ,ReturnMessage1 Msgbox ReturnMessage1 ' 调用Action2,输入参数为“ Hello!”,通过Parameter方法读取输出参数值RunAction "Action2", oneIteration,"Hello!" ReturnMessage2= Parameter("Action2","ReturnMsg") Msgbox ReturnMessage2 ' 如果被调用的Action使用了ExitAction来退出Action并返回ReturnValue,则可以使用下面的方式来获取Return Value的值 ' 注意OutPut Parameters与Return Value的区别 ReturnMessage3 = RunAction( "Action2", oneIteration ,"Hello!") Msgbox ReturnMessage3 通过全局数据表(Global Data Table)来共享数据

相关文档
最新文档