技术开发 频道

Java和C++在细节上的差异(一)

二、对象与类:

  1. Java对象实例的存储方式:

  所有的Java对象实例都是通过new的方式创建的,如Employee employee = new Employee()。而此时创建的employee对象实例,实际是指向Employee对象的一个实例的引用,主要体现为实例之间基于等号的赋值,如:employee = employee2; 赋值后两个变量将指向同一个Employee对象实例。Java处理对象变量的方式和C++中的引用比较类似,但是还是存在一定的差异,首先C++不存在空引用,既引用变量定义时也必须被同时声明其所引用的对象实例,再者就是引用一旦定义时初始化后就不能再被重新赋值了。因此这里可以将Java的对象变量看做C++中的对象指针,如:BirthdayDate d; /*Java*/ 等同于 BirthdayDate* d; /*C++*/。

  与Java对象实例声明的方式相同,C++中的对象指针也是通过new的方式进行初始化的,如BirthdayDate* d = new BirthdayDate. 同样可以将C++中的对象指针赋值为NULL,也可以将其重新赋值指向另外一个对象实例。与Java相同,通过new操作符创建的对象实例是存储在堆中的,不同的是,Java的对象在创建后,无需开发人员在去关注该对象实例需要合适被释放,所有的操作均有Java虚拟机中提供的垃圾回收机制自动完成。而C++中的该类对象,则需要开发人员通过调用delete操作符来自行完成释放,如果忘记释放将会产生内存泄露。在C++中,不仅可以将对象存储在堆上,同样也可以定义并存储的栈上,如BrithdayDate d; 该对象实例不需要手工释放,在栈退出时将自动释放该对象的存储空间,同时也会调用该对象的析构函数。

  2. Java对象方法的显式参数和隐式参数:

1     public class Employee {
2         public void raiseSalary(double byPercent) {
3             double raise = salary + byPercent / 100;
4             salary += raise;
5         }
6         private double salary;
7     }

  raiseSalary是Employee类的一个成员方法,该方法是由两个参数构成,一个是显式参数byPercent,另一个则是隐式参数this,既raiseSalary方法是实现体可以改为:

1     public void raiseSalary(double byPercent) {
2         double raise = this.salary + byPercent / 100;
3         this.salary += raise;
4     }

  这里的隐式参数this表示当前调用raiseSalary方法的对象实例的自身,该机制和C++基本相同。

  注:静态方法中不存在该特征。

  3. Java对象中定义的final实例域,如:public class Employee { ... private final String name; }, 该类型的field必须在对象构造函数中进行初始化,之后该变量将不能再被重新赋值。和final字段相似,C++对象中的const成员变量也必须在对象构造函数的初始化列表中完成赋值任务,在之后的使用中该字段将不会再被修改,否则会产生编译错误。对于Java的final域而言,以便应用于基本数据类型,如int,double等,或者不可变类型,如String。对于可变类型而言,final修饰符可能会造成某些预料之外的混乱,如 private final Date hiredate; 当该field作为某个get方法的返回值返回给调用者之后,final的修饰作用只能保证返回后的date对象不能再被重新赋值并指向新的对象实例引用,但是可以通过直接修改返回值对象的自身数据来破坏对象的封装性,从而可能造成数据的非法性,或者状态的不一致性。

  4. 函数参数传递的方式:传值和传引用。

  在Java中调用函数是,参数都是通过传值的方式传递到函数内部,然而根据参数类型的不同,其表现仍然存在一定的差异。主要总结为以下3点:

  被调用方法不能修改一个基本数据类型的参数,如:int,double,boolean等,见如下代码:

1     private static void tripleValue(double x) {
2         x *= 3;
3         System.out.println("End of method: x = " + x);
4     }
5      
6     public static void testTripleValue() {
7         System.out.println("Test tripleValue");
8         double percent = 10;
9         System.out.println("Before: percent = " + percent);
10         tripleValue(percent);
11         System.out.println("After: percent = " + percent);
12     }
13     /*    结果如下:
14         Test tripleValue
15         Before: percent = 10.0
16         End of method: x = 30.0
17         After: percent = 10.0  */

  被调用方法可以改变一个对象参数的状态,见如下代码:

1     private static void tripleSalary(Employee x) {
2         x.raiseSalary(200);
3         System.out.println("End of method: salary = " + x.getSalary());
4     }
5      
6     public static void testTripleSalary() {
7         System.out.println("Test tripleSalary");
8         Employee harry = new Employee("Harry",50000);
9         System.out.println("Before: salary = " + harry.getSalary());
10         tripleSalary(harry);
11         System.out.println("After: salary = " + harry.getSalary());
12     }
13     /*    结果如下:
14         Test tripleSalary
15         Before: salary = 50000.0
16         End of method: x = 150000.0
17         After: salary = 150000.0  */

  被调用方法不能实现让对象参数引用一个新的对象,见如下代码:

1     private static void swap(Employee a,Employee b) {
2         Employee temp = x;
3         x = y;
4         y = temp;
5         System.out.println("End of method: x = " + x.getName());
6         System.out.println("End of method: y = " + y.getName());
7     }  
8     public static void testSwap() {
9         System.out.println("Test Swap");
10         Employee a = new Employee("Alice",70000);
11         Employee b = new Employee("Bob",60000);
12         System.out.println("Before: a = " + a.getName());
13         System.out.println("Before: b = " + b.getName());
14         swap(a,b);
15         System.out.println("After: a = " + a.getName());
16         System.out.println("After: b = " + b.getName());
17     }
18     /*    结果如下:
19         Test swap
20         Before: a = Alice
21         Before: b = Bob
22         End of method: x = Bob
23         End of method: y = Alice
24         After: a = Alice
25         After: b = Bob     */

  C++有值调用和引用调用,引用参数标有&符号。如:void tripleValue(double& x)或void swap(Employee& x,Employee& y)方法实现修改他们引用参数的目的,既该方法执行完成后,调用函数的参数变量的值将发生改变。

0
相关文章