题目:
- 将每个版本的C++代码改写成Java代码。
- 写一篇技术博客,讲述其中C++与Java的不同,从第一个版本到最后一个版本使用面向对象特性进行代码重构的体会。
每个版本进行代码重构的详细体会:
版本1:4_9
这个版本是最基本的类,改写起来比较容易。
需要注意的是accumulate函数在原C++文件里是double accumulate(int date) const
,所以这里要给它加上final
修饰。
下面放上类的框架,内部函数实现就是非常简单的改几个语法就行了:
输出结果:
版本2:5_11
这个版本是增添静态属性与方法。
单纯的改代码难度并不大,关键在于对静态属性与方法的理解。
下面放上类的框架,内部函数实现就是非常简单的改几个语法就行了:
输出结果:
版本3:6_25
这个版本是增添字符串、对象数组。
相比于前面两个版本,因为多了一个调用类Date,代码相对长了很多,所以稍微有一些难度。
本来很自信,只要遇到const就换成final,现在看到一个新的函数,有些推翻之前的想法了:
本来我的方法:
- C++:
double getBalance() const {...}
就变成java:
public/private final double getBalance() {...}
- C++:
int distance(const Date& date) const {...}
就变成java:
public/private final int distance(final Date date) {...}
直到我遇到了它:
C++:
const std::string &getId() const {...}
它在函数的前面出现了一个const,函数后面也有一个const,这让我无从下手了,像原来一样的改法只加一个final是否可以?上课再问老师吧。
下面放上类的框架,内部函数实现就是改几个语法就行了:
Date类:
SavingsAccount类:
输出结果:
版本4:7_10
这个版本是继承与派生,抽象出父类,增添子类。
下面放上类的框架,内部函数实现就是改几个语法就行了:
Date类:
Accumulator类:
Account父类:
SavingsAccount子类:
CreditAccount子类:
主函数Run类:
运行结果:
版本5:8_8
这个版本是多态特性。
有个新知识点就是如何用java从键盘中接收一个字符。而java原本并不支持接收单个字符。所以可以先接收一个字符串,然后再取字符串的第一个字符即可。
还有就是java不能进行运算符重载!
还有就是注意抽象类的运用!
下面放上类的框架,内部函数实现就是改几个语法就行了:
Date类:
Accumulator类:
Account抽象父类:
SavingsAccount子类:
CreditAccount子类:
主函数Run类:
运行结果还要交互式输入,太麻烦了,就不贴上来了。
版本6:9_16
这个版本是使用容器代替数组。
其Date类、Accumulator类、Account类、SavingsAccount类、CreditAccount类都与第5版本无异。
难点在于主函数Run类编写。
多了(a)add account这个选项。又因为Account[] accounts = new Account[0];//创建账户数组,元素个数为0
,所以需要一个可以变化大小的容器数组便十分迫切。
因为Java与C++不一样,C++数组是直接创建的,而Java数组是先引用后对象,所以这方便了Java不用像C++一样再写一个Array.h的类来专门实现容器这个功能。
那么如何让Java的数组改变大小了,经过资料查询,发现别无他法,只能新创建一个数组引用,每次多一个单元,然后再一一拷贝过去即可。
于是我想写一个函数或类函数来专门实现这个功能,但遗憾的是因为程序是在public static void main(String[] args)
里面写的,所以如果专门写一个函数或者类函数,那么一定是static
类型的,这明显和我们要实现的功能不相符,所以在这里我的处理是如果确定用户要创建账户了,那么立马resize一下,然后resize出来的新单元就用于放这个新创的账户。
下面仅放难点代码:
此外,还有一个垃圾回收的机制,原C++代码是用的delete进行释放空间的,而java要用到如下代码:
C++与Java的不同:
综合自己写题和网上资料,总结出以下几点:
- 垃圾回收机制的区别。c++用析构函数回收垃圾,java自动回收(GC算法),写C和C++程序时一定要注意内存的申请和释放。
- Java语言中没有指针的概念,引入了真正的数组,有利于防止在c++程序中常见的指针越界的不安全问题。
- Java有丰富的插件和函数库,可以直接调用,而不需要自己实现,这非常方便。
- Java完全面向对象,独特的运行机制是其具有天然的可移植性。
- Java的应用在高层,C++在中间件和底层。
- C++里可以用头文件,而Java里没有头文件,但是有比较类似的用法:import。
- Java里有package关键字的用法,可以避免在程序开发中不同的程序开发人员使用相同的类名这个问题。包就是一个文件夹,它将源代码文件(.java)、编译后的文件(.class)和其他的一些用到的文件有组织的放在一起,这样一个大型程序就算是有相同类名,这些相同名字的类在不同包内就不用担心会出问题。
- 在c++里有一个经典的命名:using namespace std;这行代码使得我们在使用cin、cout、endl……时不用加std::的前缀。而在Java里有import关键字的用法,它同样能让我们在编写程序时省下写前缀的力气。import与#include有点相似但却不一样,编译器会在import导入的包里选择与类名对应的包,而#include则是编译器将其他文件的内容载入进来。Java里有一个java.lang包,里面的类经常用到,几乎没有类不用它的, 所以不管有没有写 import java.lang,编译器都会自动补上。
- C/C++基本上是由n个函数组成,主函数调用其他函数实现所需功能。Java是由n个类组成,方法都在类内,某个类内的主方法调用当前类的方法,或是调用其他类的公有(public)方法实现所需功能。
- C/C++里主函数内要使用的函数必须在主函数之前有过声明或定义,否则编译会不通过。即C/C++主方法要么写在所有调用函数的后面,要么在主函数之前就必须有所调用函数的声明。Java则比较随意,只要语法没问题,主方法可以写在类内任意位置(当然肯定不能写在别的方法里面)。
- c/c++编译的最终结果是一个程序生成一个exe文件。Java编译结果是一个程序中有多少类就生成多少个与类名相同的class文件。
- Scanner类中没有nextChar方法,不能直接通过Scanner类从控制台读取char类型的变量。
- Java的输出语句用法很简单:System.out.println();或System.out.print();System.out.println语句结束后自动换行,System.out.print语句结束后不换行。
- 在Java中,String字符串不是基本数据类型,它被当作类来处理,是引用数据类型。String类在java.lang包内,导包语句可忽略。创建字符串对象时用的是String。
- c++有引用,有指针。Java有引用,但是没有指针。