尽管Java是基于C++的,但是Java是一种更纯粹的面向对象语言。
2.1用引用操作对象
每种编程语言都有自己操作内存中元素的方式。有时候程序员需要注意将要操作的数据是什么类型。是直接操控元素,还是用某种基于特殊语法的间接表示(如C和C++中的指针)。
Java中是非常简单的,由于一切都是对象,我们可以采用单一的语法进行操作。采用遥控器操作电视方式,用引用操控对象。任何对象都可以用一个引用来操作。
2.2必须由你创建所有对象
在创建了一个引用之后,就希望它可以与一个对象相关联。通常用new来实现:
String s = new String("hello");
Java内置了很多现成的类型,但重要的是我们可以自己创造类型,然后建立新对象。
2.2.1存储到什么地方
程序运行时,对象是怎么放置安排的?特别是内存如何分配的?了解这个对我们有很大帮助。有五个地方可以存放数据:
1)寄存器:位于处理器内部,是最快的存储区,但数量有限,按需分配。不能控制也无法在程序里感觉到它存在,C和C++允许向编译器建议寄存器的分配方式。
2)堆栈:位于RAM中,可以通过堆栈指针从处理器那里获得直接支持。速度仅次于寄存器。Java程序在创建的时候就必须要知道堆栈里所有元素的确切的生命周期,以便上下移动指针,这限制了程序的灵活性。所以Java把引用存放在堆栈,而把对象存在了堆中。
3)堆:通用内存池,也在RAM中,存放所有Java对象。编译器不需要知道数据在堆里的生命周期。所以使用起来非常方便灵活,只要用new即可自动在堆里进行存储分配,但灵活的背面也是有代价的:堆里的存储和分配所花费的时间比栈里更多。
4)常量存储:常量直接存放在代码里,这是安全的,不会被改变。
5)非RAM存储:如果数据完全存活于程序之外,那就可以不受程序控制,程序不运行时候也可以存在。常见的有流和持久化对象。这种存储方式的技巧在于把对象转化成可以存储在其他媒介上的东西,在需要的时候可以转化到RAM里。
2.2.2特例:基本类型
基本类型由于它比较"小"比较简单,如果用new在堆里创建它往往并不高效,所以基本类型直接按照各自类型所占空间的大小存储在栈空间中,会更加高效。Java每种类型的大小在各个平台是不会变化的,这加强了可移植性。
boolean - -
byte 1字节(8bits) -27~27-1
short 2字节(16bits) -215~215-1
int 4字节(32bits) -231~231-1
long 8字节(64bits) -263~263-1
float 4字节(32bits)
double 8字节(64bits)
void - -
可以使用包装类使它们创建在堆中。
利用BigInteger和BigDecimal两个类可以进行高精度计算,他们没有对应的基本类型。
2.2.3Java中的数组
几乎所有的语言都支持数组,C和C++里使用数组就是直接操作内存块,这是很危险的,如果访问越界或者未初始化就访问,会造成难以预料的问题。Java为提高安全性,会确保数组被初始化,且不能在它范围之外被访问(以少量的内存开销和运行时下标检查为代价,这种代价是值得的)。在数组创建时,引用会被设置为特定值null,如果java发现试图使用一个还是null的引用时,会产生一个运行时错误,从而避免了这种情况。
2.3永远不要销毁对象 大多程序设计语言中,变量的生命周期设计是非常重要的,存活多久?何时销毁?生命周期的混乱往往导致大量bug。此处将介绍Java是如何替我们完成所有清理工作的,从而大大简化这个问题的。
2.3.1作用域
作用域决定了在其内变量的可见性和生命周期。
2.3.2对象的作用域
java中对象和基本类型的生命周期不一样,当引用不存在时,对象依旧在内存中,等待垃圾回收。
2.4创建新的数据类型:类 我们用关键字class来定义一个新类型
class ATypeName{}
即使我们并没有做任何事情,而且该类也没任何行为,但是我们已经可以用new ATypeName()来创建它的对象。
2.4.1字段和方法
Java程序只要做3件事:定义类、产生对象、发送消息。
类定义之后,可以在类中设置2种类型元素:字段(数据成员)、方法(成员函数)。