从C++到Java

1.一切皆为对象

Java应用程序即是对象的集合,它旨在完全用对象去建模,按照事物存在的形态去思考问题的本身,程序逻辑都是对象之间相互发送消息完成的。甚至Java的main函数都是作为类的静态方法而存在,因此相对于C++,Java是纯的面向对象的语言。

Java对象除原始类型(primitive)会用栈空间外,其他类型都是通过new分配在堆上,然后通过对象的引用来操作对象,赋值对象传递对象都是传递引用。

2.内存管理

让C++程序员最困扰的事之一便是内存管理,内存何时创建何时释放。Java的初衷便是让程序员从计算机语言,系统中解放出来,程序员更多考虑的是系统的构架,业务逻辑。Java语言本身会去帮你完成很多计算机方面的工作,当然包括管理内存,你永远不用去delete,它提供了垃圾回收的功能,然而这也会造成性能上的代价:一是在堆上分配空间的时间代价,二是垃圾回收器的代价,并且你永远不知道这片空间会何时释放,我就见到很多Java程序因为虚拟机内存耗光而强行退出,也听到会有Java内存泄露的问题。

3.更为强迫的语言

很多在C++中可以通过编译,但不推荐的用法,在Java中是明令禁止的,即不能通过编译。

3.1禁止的隐式转换

在C++中,非零即为真的原则在Java中废止,boolean只能是true和false,不能将其他类型隐式或强行转换为boolean,你只能通过关系操作符将他们转换为boolean类型。这避免了if(a=true)这样的错误。

在C++中的窄类型转换(narrowingconversion),一般编译器会给警告,而在Java中,如果没有明确的强制类型转换,则不能通过编译。

3.2局部变量必须初始化

同样C++中没有初始化的局部变量,编译器会给警告信息,而在Java中,则是编译错误。Java的变量可以初始化为null,即空引用,很特别。

C++中的全局变量和静态变量会被初始化为合适的值,Java中没有全局变量,类的成员变量都会被初始化为合适的值。

3.3更为明确的作用域

在C++中,一个变量的作用域内的子作用域,如果有同名的变量则,子作用域的变量会隐藏掉上层的变量。

在Java中,这是一个编译错误。

3.4Java的class的默认访问修饰是public

这一点跟它的精神有些不符,不知为何

3.5对象的引用

Java的对象都是由引用操作的,赋值,传递,都是引用,如果用等于(==)操作符去比较两个对象,则比较的是引用,虽然内容相同,但比较的结果却不相同,Java为每个类都提供一个equals方法用于比较内容。

对于String类型有一点特别。

以下内容转载自:http://www.cnblogs.com/tonyqus/archive/2004/12/07/73710.aspx

-------------------------------------------------------------------------------------------------------------------------

熟悉C++的人对于两个字符串比较的代码一定很了解:

(string1==string2)

但在java中,这个代码即使在两个字符串完全相同的情况下也会返回false

Java中必须使用string1.equals(string2)来进行判断

补充

如果:

strings1=newString("Hello");

strings2=newString("Hello");

则(s1==s2)=false

如果:

strings1="Hello";

strings2="Hello";

则(s1==s2)=true;

因为他们指向的同一个对象。

如果把其他变量的值赋给s1和s2,即使内容相同,由于不是指向同一个对象,也会返回false。所以建议使用equals(),因为equals比较的才是真正的内容。

4.对象的初始化和清理

4.1特别的构造函数调用

Java中的构造函数能够相互调用完成初始化,但一个构造函数只能调用一个其他构造函数,并且必须是最先调用。调用用this,例子如下:

Java代码

publicclassJavaBasics{

privateinti;

privateStrings;

publicJavaBasics(inti_){

i=i_;

}

publicJavaBasics(){

this(0);

}

publicJavaBasics(Strings_){

s=s_;

}

publicJavaBasics(inti_,Strings_){

//s=s_;构造函数必须是最先调用

this(i_);

//this(s_);在同一个构造函数中不能调用两个构造函数

s=s_;

}

}

4.2垃圾回收和终结函数(finalize)

Java中没有析构函数,为了对特殊的资源进行回收,它提供了finalize方法,但它不同于C++的析构函数,在垃圾回收的时候它才会被调用,因此你不能确定它会在什么时候执行,那么在什么情况下会用到finalize呢?一种情况是例如你有文件打开,需要在对象被清理前关闭,即非内存的资源的释放(内存释放是垃圾回收处理的),第二种情况是你用本地方法(Nativemethod)获得了内存资源,即通过JNI调用C或C++的方法。

由于垃圾回收和finalize方法都不确定在什么时候被调用,因此你的一些清理操作要显示的调用,例如,一个应用程序在屏幕上绘图,用户最小化应用程序时,你需要显示的调用方法清理屏幕。

4.3成员的初始化

对象的成员会被合理的初始化,即使你没有显示的初始化它们,原始类型会被初始化为物理意义上的0,而对象类型则被初始化为null,和C++一样,Java中对象成员的初始化顺序是成员在类中出现的顺序,接下来调用构造函数。

静态成员会在必要时(即用到时)初始化,先会初始化类的静态成员,并且只初始化一次,以后创建类的实例,都不再初始化静态成员。

你有3种初始化的方法

1.在定义的时候初始化(Java中不分声明和定义,都是声明和定义在一起)

2.在构造函数中初始化

3.可以有特别的代码块来初始化成员,例如:

Java代码

classDemo{

//initwhendefinition

publicstaticStringstr0=newString("abc");

publicintival=3;

publicstaticdoublepi;

publiclonglval;

publicstaticStringstr1;

//initexplicit

static{

pi=3.1415D;

}

{

lval=100L;

}

publicDemo(){

//initinconstructor

str1=newString("inconstructor");

}

}

4.4数组的初始化

1.原始类型数组的初始化和C++基本一样,但你必须初始化它。如:

int[]a1={1,2,3,4,5};

并且你不能在运行时改变它的大小,访问超过初始化时设置的大小的下标是会接受到超出范围的异常。

2.若需要创建动态数组,则需要new一个动态数组,如:

int[]a=newint[rand.nextInt(20)];

3.数组的传递,也是传引用。

4.非原始类型的数组,初始化时其元素必须new出一个非空的引用。

相关推荐