在Java与C++中对象作为参数传递的不同

  问题源于在Java中使用对象作为参数,按照C++的思路进行调试,发现结果与C++中并不相同。

  导致该问题的原因是Java与C++对于对象的解释是不相同的。

  在C++中对象作为参数采用的是“传值调用”,当实参通过形参传递时,会调用对象(实参)的拷贝构造函数(如果没有显式的定义拷贝构造函数,将自动调用默认拷贝构造函数,它的功能是将实参中的对象原样的拷贝到形参中,这里牵扯到深拷贝和浅拷贝的问题,但不影响对本问题的分析。),函数实际操作的是该对象的拷贝,并不影响原对象。

  而在Java中,对象作为参数时,形参是被初始化为实参对象的引用。如果对形参进行操作会影响到实参(原对象)。这有点类似于C++中的”引用调用“,但并非如此,Java中采用的仍然是”传值调用“。而导致结果不同的原因是,Java与C++中对对象名的解释是不同的。在C++中“类”和“对象”的关系可以类比为“类型”和“变量”之间的关系,对象在定义的时候即分配了内存空间,它是实实在在存在的。而在Java中,对象定义时只是定义了“对象变量”,它只是指向一个对象,当使用new操作符时才会构造指向的这个对象。Java中的对象名有点像C++中指向对象的指针,当作为参数传递时,传递的是该对象在内存中的地址。

  在C++和Java中String类的对象str的存储方式分别如下:

  以Java中对象作为参数传递的例子分析一下:

 1 public class Test1 {
 2        public static void main(String[] args) {
 3         StringBuffer str = new StringBuffer("Hello ");
 4         System.out.println("Before change, str = " + str);
 5         changeData(str);
 6         System.out.println("After changeData, str = " + str);
 7     }
 8
 9        public static void changeData(StringBuffer strBuf) {
10         strBuf.append("World!");
11     }
12 }

   按照上面的分析,将str传递给strBuf 时,是将Hello存储的地址传递过去,那么输出结果是:

Before change, str = Hello
After changeData, str = Hello World!

  将上面的代码修改一下,如下:

 1 public class Test2 {
 2        public static void main(String[] args) {
 3         StringBuffer str = new StringBuffer("Hello ");
 4         System.out.println("Before change, str = " + str);
 5         changeData(str);
 6         System.out.println("After changeData, str = " + str);
 7     }
 8                                                                                                                                                                                             9        public static void changeData(StringBuffer strBuf) {
10            strBuf = new StringBuffer("Hi ");
11            strBuf.append("World!");
12     }
13 }

  按照上面的分析,将str传递给strBuf 时,strBuf 与str都将存放Hello的存储地址,如下图:

  然后当执行完 strBuf = new StringBuffer("Hi "); 后,以上关系将变成:

  此时strBuf 中存放的不再是Hello的地址,而是Hi的地址,new操作符操作成功后总会在内存中新开辟一个存储区域。

  当执行 strBuf.append("World!"); 这句时,此时操作的将是Hi,而不是Hello,那么结果将变成:

  最后输出结果如下:

Before change, str = Hello
After changeData(n), str = Hello

  

时间: 2024-11-06 03:32:04

在Java与C++中对象作为参数传递的不同的相关文章

java 对list中对象按属性排序

实体对象类 --略 排序类----实现Comparator接口,重写compare方法 package com.tang.list; import java.util.Comparator; public class Mycompera implements Comparator<Student> { @Override    public int compare(Student o1, Student o2) {        if (o1.getSid() > o2.getSid()

JAVA基础知识_对象

对象可以作为参数传递给方法 传递对象不是将对象本身的值传递给形参,而是将对象的引用值传递给形参 void method1(Num num){ num.i+=10; } method1方法体内形参内容的任何改动,也是对对象本身的改动 void method2(Num num){ num=new Num(); num.i=100; } 这里的对象内容并没有改变 因为Java中对象作为参数传递时,相当于是把对象在内存中的地址拷贝了一份传给参数 method1中,因为形参和对象有相同的内存地址,所以对形

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

形参和实参 我们知道,在Java中定义方法时,是可以定义参数的,比如: public static void main(String[] args){ } 这里的args就是一个字符串数组类型的参数. 在程序设计语言中,参数有形式参数和实际参数之分,先来看下它们的定义: 形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数,简称"形参". 实际参数:在主调函数中调用一个函数时,函数名后面括号中的参数称为"实际参数",简称"

XML在java或.NET中转为Json的数组或对象数据时的处理

XML在java和.NET中转为Json数据时会出现这样一个问题,当节点中只有一个节点数据时是转换为对象,有多个节点则是转为数组,为了应对这个问题我们需要在解析的时候进行如下的处理,不然就会报异常: 数据1:数组格式 "Field": [                    {                        "@name": "APPROVE",                        "@title"

Java中对象、对象引用、堆、栈、值传递以及引用传递的详细解释

Java中对象.对象引用.堆.栈.值传递以及引用传递的详细解释 1.对象和对象引用的区别: (1).对象: 万物皆对象.对象是类的实例.在Java中new是用来在堆上创建对象用的.一个对象可以被多个引用所指向. (2).对象引用: 类似于C++中的地址.通过对象引用可以找到对象.一个引用可以指向多个对象.操纵的标识符实际上是指向对象的引用. 就像:对象存放在屋子里,对象的引用就相当于屋子的钥匙. 2.值传递和引用传递的区别: (1).值传递:传递的是值的拷贝.也就是说传递后就不互相关了. (2)

java中对象的初始化问题

最近又把java编程思想看了看.又有些收获.此书确实不错 java中的初始化相信很多人都知道.但是具体的初始化步骤,初始化几次确不一定.上代码 public class A{ public static A a = new A(); public static int i; public static int j= 2; public A(){ i++; j++; } public static void main(String[] args){ A a1= new A(); System.ou

java中对象多态时成员变量,普通成员函数及静态成员函数的调用情况

/* 样例1: class Parent{ int num = 3; } class Child extends Parent{ int num = 4; } */ /* 样例2: class Parent{ } class Child extends Parent{ int num = 4; } */ /* 样例3: class Parent{ void show(){ System.out.println("Parent Show!"); } } class Child exten

java中对象的初始化过程

class Parent{ int num = 8;// ->3 Parent(){ //super(); // ->2 //显示初始化 // ->3 //构造代码段 // ->4 show(); // ->5 } {// ->4 System.out.println("Parent constructor code run->"); } public void show(){//被覆盖 System.out.println("num

深入理解Java类型信息(Class对象)与反射机制(干货)

[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/70768369 出自[zejian的博客] 本篇主要是深入对Java中的Class对象进行分析,这对后续深入理解反射技术非常重要,这篇有点偏向内功类文章,主要内容如下: 深入理解Class对象 RRTI的概念以及Class对象作用 Class对象的加载及其获取方式 Class对象的加载 ClassforName方法 Class字面常