面向对象的三个主要特征:
行为——可以对对象施加哪些操作,或可以对对象施加哪些方法
状态——当施加那些方式时,对象如何响应
标识——如何辨别具有相同行为与状态的不同对象
作为一个类,每个对象的标识永远是不同的,状态常常也存在着差异
类之间的关系:
依赖("is-a"):一个类的方法操纵另一个类的对象 (尽量减少依赖)
聚合("has-a"):类A的对象包含类B的对象
继承("is-a"):特殊与一般;一般而言,类A扩展类B,类A不但包含从类B继承的方法,还会拥有一些额外的功能
new Date();这个对象被初始化为当前的时间和日期
一个对象变量并没有实际包含一个对象,而仅仅引用一个对象
在Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用.
new 操作符的返回值也是一个引用
语句 Date deadline = new Date(); 有两个部分,表达式new Date()构造了Date类型的对象,并且它的值是对新创建对象的引用,这个引用存储在变量deadline中
局部变量不会自动初始化为null,而必须调用new或将它们设置为null进行初始化
在所有的方法中不要命名与实例域同名的变量。
不要编写返回引用可变对象的访问器的方法,如果需要返回一个可变对象的引用,应该首先对它进行克隆,对象clone是指对存放在另一个位置上的对象的副本
两种情况使用静态方法:
- 一个方法不需要访问对象状态,其所需参数都是通过显示参数提供
- 一个方法值需要访问类的静态域
工厂方法:
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(); NumberFormat percentFormatter = NumberFormat.getPercentInstance(); double x = 0.1; System.out.println(currencyFormatter.format(x)); // prints $0.10 System.out.println(percentFormatter.format(x)); // prints 10%
调用构造函数的步骤:
- 所有数据域被初始化为默认值(0、false 或 null)
- 按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块
- 如果构造器第一行调用了第二个构造器,则执行第二个构造器
执行这个构造器的主体
嵌套的包中没有任何关系,如java.util包与java.util.jar包毫无关系,每一个都拥有独立的类集合
继承
在子类中可以增加域、增加方法或覆盖超类的方法,但不能删除继承的任何域和方法
class Manager extends Employee
由于Manager类的构造器不能访问Employee类的私有域,所以必须利用Employee类的构造器对这部分私有域进行初始化,我们可以通过super实现对超类构造器的调用。使用super调用构造器的语句必须是子类构造器的第一条语句。
如果子类的构造器没有显示地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。如果超类没有不带参数的构造器,并且子类的构造器中又没有显示地调用超类的其他构造器,则java编译器将报告错误
this用途:引用隐式参数;调用该类其他的构造器
super用途:调用超类的方法;调用超类的构造器
多态
是否应该设计为继承的"is-a"规则,它表明子类的每个对象也是超类的对象
置换规则:程序中出现超类对象的任何地方都可以用子类对象置换
可以将一个子类的对象付给超类变量
Manager boss = new Manager(...);
Employee[] staff = new Employee[3];
staff[0] = boss;
staff[0]与boss引用同一个对象,但编译器将staff[0]看成Employee对象
不能将超类的引用赋给子类变量
在java中,子类数组的引用可以转换成超类数组的引用,而不需要采用强制类型转换
Manager[] managers = new Manager[10];
将它转换成Employee[]数组完全合法的
Employee[] staff = new managers;
在覆盖一个方法的时候,子类方法不能进行低于超类方法的可见性
如果一个类声明为final,只有其中的方法自动地成为final,而不包括域
将方法或类声明为final主要目的是
将一个子类的引用赋给一个超类变量,编译器是允许的,将一个超类的引用赋给一个子类变量,必须进行类型转换。