类
由类构造对象的过程称为创建类的实例。
封装:是与对象有关的重要概念。
从形式上看,封装不过是将数据和行为组合在一个包下,并对对象的使用者隐藏了数据的实现方式。数据的对象称为实例域,操纵数据的过程称为方法。
实现类封装的关键在于绝对不能让类中的方法直接地访问其他类的实例域。程序仅通过对象的方法与对象数据进行交互。
这意味着一个类可以全面地改变存储数据方式,只要仍旧使用同样的方法操作数据,其他对象的就不会知道或介意所发生的变化。
OOP的另一个原则会让用户自定义Java变得轻而易举,这就是:类可以拓展另一个类来建立。所有的类都源自一个超类,读者将可以看到有关Object类的详细介绍。
对象:
要想使用OOP,一定要清楚对象的三个主要特性:
对象的行为:可以对对象施加哪些操作,
对象的状态:当施加那些方法时,对象如何响应。
对象标识:如何辨别具有相同行为与状态的不同对象。
对象的这些关键特性在彼此之间相互影响着。
识别类
类之间的关系
常见的关系有
- 依赖
- 聚合 (关联)
- 继承
如果一个类的方法操作另一个类的对象,我们就说一个类依赖于另一个类。
聚合关系意味着类A包含类B的对象。
在java中并不是所有类都具有面向对象特征。例如,Math类,在程序中,可以使用Math类的方法,如Math.random并只需要知道方法名和参数,而不必了解它的具体实现过程。这也正是封装的关键所在,当然所有类都是这样。但遗憾的是,Math类只封装了功能,它不需要也不必隐藏数据。由于没有数据,因此也不必担心生成对象以及初始化实例域。
一定要认识到:一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。在Java中任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new操作符的返回值也是一个引用。
可以显示地将对象变量deadline设置为null,表明这个对象变量目前没有引用任何对象。
如果将一个方法应用于一个值为null的对象上,那么就会产生运行错误。
变量不会自动地初始化为null,而必须通过调用new或将他们设置为null进行初始化。
很多人错误地认为java对象变量与C++的引用很类似。然而,在C++中没有空引用,并且引用不能被赋值。可以将Java的对象变量看作C++的对象指针。
所有的java对象都存储在堆中。当一个对象包含另一个对象变量时,这个变量依然包含着指向另一个堆对象的指针。
C++确实做了很大的努力,他通过拷贝型构造器和复制操作符来实现对象的自动拷贝。一个链表的拷贝结果将会得到一个新链表。这使得将同样的拷贝行为内置在类中成为可能。在java中必须使用clone方法获得对象的完整拷贝。
Final 实例域
可以将实例域定义为final。构建对象时必须初始化这样的体验。也就是说,必须确保在每个构造器执行之后,这个域的值被设置。并且在后面的操作中,不能够再对它进行修改。
static静态域
每个类中只有一个这样的域。而每个对象对于所有的实例域却都有自己的一份拷贝。他属于类,而不属于任何独立的对象。
静态常量
静态变量使用的较少,但静态常量却使用的比较多。
static final double PI = 3.1415
静态方法
静态方法是一种不能向对象实施操作的方法。例如,Math类的pow方法就是一个静态方法。换句话说,静态方法没有隐式的参数。
在下面两种情况下使用静态方法:
- 一个方法不需要访问对象状态,其所需参数都是通过显示参数提供。
- 一个方法只需要访问类的静态域。
Factory方法
静态方法还有一个常见的用途。NumberFormat类使用factory方法产生不同风格的格式对象。
Main方法
默认初始化域
如果在构造器中没有显示地给域赋予初值,那么就会被自动地赋为默认值:数值为0、布尔值为false、对象引用为null。然而,只有缺少程序设计经验的人才会这样做。确实,如果不明确地对进行初始化,就会影响程序代码可读性。
默认构造器
所谓默认构造器是指没有参数的构造器。
调用另一个构造器
关键字this引用方法的隐式参数。然而这个关键字还有另外一层含义。
如果构造器的第一个语句形如this(),这个构造器将调用同一类的另一构造器。
对象析构与finalize方法
有些面向对象的程序设计语言,特别是C++,有显示的析构方法,其中放置一些当对象不再使用时需要执行的清理代码。在析构器中,最常见的操作是回收分配给对象的存储空间。由于Java有自动的垃圾回收器,不需要人工回收内存,所以java不支持析构器。
当然,某些对象使用了内存之外的其他资源,例如,文件或使用了系统资源的另一个对象的句柄。在这种情况下,当资源不再需要时,将其回收和再利用将显得十分重要。
可以为任何一类添加finalize方法。finalize方法将在垃圾回收器清除对象之前调用在实际应用中不要依赖于使用finalize方法回收任何短缺资源,这是因为很难知道这个方法什么时候才能够调用。
有个名为System.runFinalizersOnExit(true)的方法能够确保finalizer方法在Java关闭前被调用。不过,这个方法并不安全,也不鼓励大家使用。有一种替代的方法是使用方法Runtime.addShutdownHook添加“关闭钩”。如果某个资源需要在使用完毕后立刻被关闭,那么就需要人工来管理。可以应用一个类似dispose或close的方法完成相应的清理工作。特别需要说明,如果一个类使用了这样的方法,当对象不再被使用时一定要调用它。
包作用域
如果没有指定public或private,这个部分(类、方法或变量)可以被同一个包中的所有方法访问。