从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出一个非空的引用。