Java应用程序即是对象的集合,它旨在完全用对象去建模,按照事物存在的形态去思考问题的本身,程序逻辑都是对象之间相互发送消息完成的。甚至Java的main函数都是作为类的静态方法而存在,因此相对于C++,Java是纯的面向对象的语言。
?
Java对象除原始类型(primitive)会用栈空间外,其他类型都是通过new分配在堆上,然后通过对象的引用来操作对象,赋值对象传递对象都是传递引用。
?
让C++程序员最困扰的事之一便是内存管理,内存何时创建何时释放。Java的初衷便是让程序员从计算机语言,系统中解放出来,程序员更多考虑的是系统的构架,业务逻辑。Java语言本身会去帮你完成很多计算机方面的工作,当然包括管理内存,你永远不用去delete,它提供了垃圾回收的功能,然而这也会造成性能上的代价:一是在堆上分配空间的时间代价,二是垃圾回收器的代价,并且你永远不知道这片空间会何时释放,我就见到很多Java程序因为虚拟机内存耗光而强行退出,也听到会有Java内存泄露的问题。
?
很多在C++中可以通过编译,但不推荐的用法,在Java中是明令禁止的,即不能通过编译。
在C++中,非零即为真的原则在Java中废止,boolean只能是true和false,不能将其他类型隐式或强行转换为boolean,你只能通过关系caozuofu.html" target="_blank">操作符将他们转换为boolean类型。这避免了if (a = true)这样的错误。
在C++中的窄类型转换(narrowing conversion),一般编译器会给警告,而在Java中,如果没有明确的强制类型转换,则不能通过编译。
同样C++中没有初始化的局部变量,编译器会给警告信息,而在Java中,则是编译错误。Java的变量可以初始化为null,即空引用,很特别。
C++中的全局变量和静态变量会被初始化为合适的值,Java中没有全局变量,类的成员变量都会被初始化为合适的值。
在C++中,一个变量的作用域内的子作用域,如果有同名的变量则,子作用域的变量会隐藏掉上层的变量。
在Java中,这是一个编译错误。
这一点跟它的精神有些不符,不知为何
?
Java的对象都是由引用操作的,赋值,传递,都是引用,如果用等于(==)操作符去比较两个对象,则比较的是引用,虽然内容相同,但比较的结果却不相同,Java为每个类都提供一个equals方法用于比较内容。
对于String类型有一点特别。
以下内容转载自:http://www.cnblogs.com/tonyqus/archive/2004/12/07/73710.aspx
-------------------------------------------------------------------------------------------------------------------------
熟悉C++的人对于两个字符串比较的代码一定很了解:
(string1==string2)
但在java中,这个代码即使在两个字符串完全相同的情况下也会返回false
Java中必须使用string1.equals(string2)来进行判断
补充
如果:
string s1=new String("Hello");
string s2=new String("Hello");
则(s1==s2)=false
如果:
string s1="Hello";
string s2="Hello";
则(s1==s2)=true;
因为他们指向的同一个对象。
如果把其他变量的值赋给s1和s2,即使内容相同,由于不是指向同一个对象,也会返回false。所以建议使用equals(),因为equals比较的才是真正的内容。
Java中的构造函数能够相互调用完成初始化,但一个构造函数只能调用一个其他构造函数,并且必须是最先调用。调用用this,例子如下:
?
Java中没有析构函数,为了对特殊的资源进行回收,它提供了finalize方法,但它不同于C++的析构函数,在垃圾回收的时候它才会被调用,因此你不能确定它会在什么时候执行,那么在什么情况下会用到finalize呢?一种情况是例如你有文件打开,需要在对象被清理前关闭,即非内存的资源的释放(内存释放是垃圾回收处理的),第二种情况是你用本地方法(Native method)获得了内存资源,即通过JNI调用C或C++的方法。
由于垃圾回收和finalize方法都不确定在什么时候被调用,因此你的一些清理操作要显示的调用,例如,一个应用程序在屏幕上绘图,用户最小化应用程序时,你需要显示的调用方法清理屏幕。
对象的成员会被合理的初始化,即使你没有显示的初始化它们,原始类型会被初始化为物理意义上的 0 ,而对象类型则被初始化为 null ,和 C++ 一样, Java 中对象成员的初始化顺序是成员在类中出现的顺序,接下来调用构造函数。
静态成员会在必要时(即用到时)初始化,先会初始化类的静态成员,并且只初始化一次,以后创建类的实例,都不再初始化静态成员。
你有 3 种初始化的方法
1. 在定义的时候初始化( Java 中不分声明和定义,都是声明和定义在一起)
2. 在构造函数中初始化
3. 可以有特别的代码块来初始化成员,例如:
1. 原始类型数组的初始化和 C++ 基本一样,但你必须初始化它。如:
int[] a1 = { 1, 2, 3, 4, 5 };
并且你不能在运行时改变它的大小,访问超过初始化时设置的大小的下标是会接受到超出范围的异常。
2. 若需要创建动态数组,则需要 new 一个动态数组,如:
int[] a = new int[rand.nextInt(20)];
3. 数组的传递,也是传引用。
4. 非原始类型的数组,初始化时其元素必须 new 出一个非空的引用。
?