java中的实参与形参的区别_Java 与 C 方法中实参形参与指针联系的分享

版权声明:本文章原创于 RamboPan ,未经允许,请勿转载。

Java 与 C 方法中实参形参与指针联系的分享

Java 形参为基本类型

Java 形参为类对象

C/C++ 形参为基本类型

C/C++ 形参为结构体

C/C++ 形参为基本类型指针

C/C++ 形参为结构体指针

讨论结果

图示

因为不是计算机专业,在大学时也只是简单地学习了下 C ,然而在工作中 (Android) 因为项目原因反而接触了很多 C/C++ 的部分,决定补一下这些基础,在最近看 C / C++ 课程,当然有一个很重要的概念就是指针,之前大学因为没有一定工作经验,所以对于指针理解不够透彻,现在重新看一遍感觉又明白了一些,也做个笔记分享下。

因为主要想分享形参与实参的理解,用交换两个变量的值来举例吧。

先说说 Java ,写个片段来测试看看。

Java 形参为基本类型

public static void main(){

int a = 20;

int b = 30;

System.out.println("main a :" + a + " ; b :" + b);

switchPara(a,b);

System.out.println("main a :" + a + " ; b :" + b);

}

//交换这两个变量的值

private static void switchPara(int a,int b){

System.out.println("switchPara a :" + a + " ; b :" + b);

int temp = b;

b = a;

a = temp;

System.out.println("switchPara a :" + a + " ; b :" + b);

}

main a :20 ; b :30

switchPara a :20 ; b :30

switchPara a :30 ; b :20

main a :20 ; b :30

从结果可以看到在 switchPara() 方法中,参数确实是发生了变化,但是在 main()中打印的日志,的确没有发生变化。常见的解释是在方法中,形参是实参的拷贝,所以在这个方法里,你只是改变了形参值,并没有改变实参的值。所以在 main() 中没有生效,那么我们先暂时记下这个结论。

Java 形参为类对象

接下来测试下如果交换对象中的基本变量,会不会不一样。

static class Param{

public int i;

}

public static void main(){

Param p1 = new Param();

p1.i = 20;

Param p2 = new Param();

p2.i = 30;

System.out.println("switchPara p1 :" + p1.i + " ; p2 :" + p2.i);

switchPara(p1,p2);

System.out.println("switchPara p1 :" + p1.i + " ; p2 :" + p2.i);

}

//交换这两个变量的值

private static void switchPara(Param a,Param b){

System.out.println("switchPara a :" + a.i + " ; b :" + b.i);

int temp = b.i;

b.i = a.i;

a.i = temp;

System.out.println("switchPara a :" + a.i + " ; b :" + b.i);

}

main p1 :20 ; p2 :30

switchPara a :20 ; b :30

switchPara a :30 ; b :20

main p1 :30 ; p2 :20

是不是发现有点奇怪,为什么之前单独交换基本类型时,没有生效,而放在一个对象当中就可以生效了,仿佛这个形参不是实参的拷贝。这里暂时有点迷惑,我们就先放着,接下来看看 C/C++ 中,测试下这两个例子会怎么样。

C/C++ 形参为基本类型

//交换这两个变量的值

void switchPara(int a,int b)

{

cout << "switchPara a : " << a << " ; b :" << b << endl;

int temp = b;

b = a;

a = temp;

cout << "switchPara a : " << a << " ; b :" << b << endl;

}

void main()

{

int a = 20;

int b = 30;

cout << "main a : " << a << " ; b :" << b << endl;

switchPara(a,b);

cout << "main a : " << a << " ; b :" << b << endl;

}

main a : 20 ; b :30

switchPara a : 20 ; b :30

switchPara a : 30 ; b :20

main a : 20 ; b :30

看结果,这里和 Java 中使用基本类型一样。接下来我们用结构体作为形参,类似 Java 中的对象。

C/C++ 形参为结构体

struct Param{

int i;

};

//交换这两个变量的值

void switchPara(Param a,Param b){

cout << "switchPara a : " << a.i << " ; b :" << b.i << endl;

int temp = b.i;

b.i = a.i;

a.i = temp;

cout << "switchPara a : " << a.i << " ; b :" << b.i << endl;

}

void main()

{

Param p1;

p1.i = 20;

Param p2;

p2.i = 30;

cout << "main a : " << p1.i << " ; b :" << p2.i << endl;

switchPara(p1,p2);

cout << "main a : " << p1.i << " ; b :" << p2.i << endl;

}

main a : 20 ; b :30

switchPara a : 20 ; b :30

switchPara a : 30 ; b :20

main a : 20 ; b :30

这里发现测试结构体的时候和基本类型一样,在 switchPara()中形参的值确实修改了,而实参的值没有改这里是为什么呢 ? 因为这里的形参确实是拷贝,而 Java 中传入对象的时候就不是拷贝了。

当然我们先继续测试下如果需要在形参改变时也改变实参,那么需要怎么做 ?当然需要用到指针,当然这部分用 C/C++ 测试。

C/C++ 形参为基本类型指针

//交换这两个变量的值

void switchPara(int * a,int * b)

{

cout << "switchPara a : " << *a << " ; b :" << *b << endl;

int temp = *b;

*b = *a;

*a = temp;

cout << "switchPara a : " << *a << " ; b :" << *b << endl;

}

void main()

{

int a = 20;

int b = 30;

cout << "main a : " << a << " ; b :" << b << endl;

switchPara(&a,&b);

cout << "main a : " << a << " ; b :" << b << endl;

}

main a : 20 ; b :30

switchPara a : 20 ; b :30

switchPara a : 30 ; b :20

main a : 30 ; b :20

这里可以看到使用指针,在 switchPara() 中形参是基本类型,如果通过形参的修改了值,也是可以改变实参的值。

接下来还是测试结构体指针。

C/C++ 形参为结构体指针

struct Param{

int i;

};

//交换这两个变量的值

void switchPara(Param * a,Param * b){

cout << "switchPara a : " << a->i << " ; b :" << b->i << endl;

int temp = b->i;

b->i = a->i;

a->i = temp;

cout << "switchPara a : " << a->i << " ; b :" << b->i << endl;

}

void main()

{

Param p1;

p1.i = 20;

Param p2;

p2.i = 30;

cout << "main a : " << p1.i << " ; b :" << p2.i << endl;

switchPara(&p1,&p2);

cout << "main a : " << p1.i << " ; b :" << p2.i << endl;

}

main a : 20 ; b :30

switchPara a : 20 ; b :30

switchPara a : 30 ; b :20

main a : 30 ; b :20

当然使用结构体指针时也是可以在 switchPara() 修改对应实参的值。

讨论结果

从上面的测试来看,可以得出结论。

在 C/C++ 中形参只要不是指针类型,那么改变形参,不会改变实参的值。

在 C/C++ 中形参只要是指针类型,那么可以通过形参去改变实参的值。

在 Java 中形参为基本类型,改变形参不改变实参的值。

在 Java 中形参为类对象,改变形参可以改变实参的值。

注意:在测试例子中,不是算改变形参的值,而是通过形参去访问了实参。

那么是不是得出结论:

在 Java 中使用方法时,如果形参使用基本类型,就是实参的拷贝,而使用类对象时,传递的就是指针。

我们来回忆下 Java 中关于对象的生成与使用。

class Param{

int i;

}

public static void main(){

Param p1 = new Param();

p1.i = 20;

}

如果使用 Java 熟悉点的朋友都知道,我们在

Param p1 = new Param();

这句话中,Param p1 代表声明了一个 Param 类型的引用,而 new Param() 才代表生成了一个 Param 对象;而 p1 这个引用是放在栈中的,而 Param 对象是放在堆中的,实际上我们用 p1.i = 20 时,是使用栈中 p1 去访问了堆中的 Param 对象,并且进行了写操作。

如果我们 main() 中是这样的话,那么肯定会报错。

class Param{

int i;

}

public static void main(){

Param p1 = null;

p1.i = 20;

}

当然大家都知道是什么错误,空指针!是不是也确实说明这个 p1 引用就是一个 Param 类型的指针,如果你不让指针去指向某个对象,那么肯定没法对那个对象进行读写操作。

至于为什么 Java 要考虑在形参使用类对象时,不使用拷贝而使用指针,可能有很多因素,但有一个原因可以确定:

如果使用拷贝的话,会因为执行大量方法而生成很多新的对象,频繁触发 GC ,那么这肯定不合理。

或许也是 C/C++ 中常说方法中尽量使用指针变量而不是使用变量的原因吧。

图示

画了一个小的示意图,说明下为啥形参是指针时可以通过拷贝的指针可以改变实参的值;

不是指针时却不行。

7cbc85b8ae7f4ab69bcf0a86bf7961fb.png

6a92f2cf9307ff21be32f52d60c85c5d.png

分享下平时思考的笔记,如有不对之处,欢迎指出讨论。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值