类和对象
一. 类之间的三种基本关系
1 使用 一个类操作另一个类的对象时,这个类就使用另一个类 。 尽量减少相互使用的类,这样修改类B时,不会向类A中引入程序错误。
2 包含 包含关系是指类A的对象包含类B的对象.。
3 继承 继承关系代表特殊化,专门化。
二. 用已经存在的类
关于clone 函数:
许多类都有一个名为clone的方法。它创建真正的拷贝。当复制已存在的对象时,就获得了反映该对象目前状态的拷贝。然而,与使用等号的赋值不同。从现在开始,这两个对象独立存在,随着时间的推移,他们能发生各不相同的变化。
关于null 对象:
如果对空变量调用某个方法,将引起运行时错误。局部对象变量不能自动的初始化为空,必须显示初始化他们,或者调用 new 或者将他们设置为空。
C++注释:
可将 java 对象视为C++中的指针
AudioClip meow; // Java
完全等同与
AudioClip * meow; // C++
如果将一个变量拷贝给另一个变量,那么这两个变量指向同一个声音片断,他们是指向同一个对象的两个指针。Java 中的空对象对应于C++的空指针。
所有 Java 对象都建立在堆上。
日期类:
Date today = new Date();
Date perMillenium = new Date(99,11,31); // 1999.11.31
Date perMillenium = new Date(99,11,31,23,59,59); //1999.11.31
API注释:日期类(java.util.Date)
void parse(String s) 从字符串s得到日期
Boolean before (Date when) 如果调用该方法的日期(对象)在日期when之前,则该方法返回真。
Boolean after (Date when) 如果调用该方法的日期(对象)在日期when之后,则该方法返回真。
String toString () 将日期对象的日期值转化为表示该日期的字符串
String toLocaleString() 该方法按本地日,月,年顺序约定,将日期对象的日期值转化为该日期的字符串描述
Date today = new Date();
System.out.println(today.toLocaleString());
System.out.println(today.toString());
的结果为:
2005-8-10
Wed Aug 10 2005
int getDate() 获得一月中的某一天,1 – 31
int getMonth() 获得月份 0 – 11
int getYear() 获得当前年份 – 1900
int getDay() 获得星期值 0 – 6 0表示星期天
int getHours() 获得时
int getMinutes() 获得分
int getSeconds() 获得秒
C++注释:
在C++中,从形式上区分修改对象的转换操作和只访问对象的访问操作是非常重要的。后者需被说明为const操作。这在Java中是不需要的。
*日类:
Day todaysDate = new Day();
Day preMillenium = new Day(1999,12,31);
与Java的日期类不同的是,该类不处理时间,并且禁止创建非法日期。
关于函数的传参问题:
Java 从不以传地址方式传递方法参数
三.创建自己的类
C++注释:
在Java 中,类的所有函数都定义在类自身中,但是函数并不自动成为嵌入函数。
构造函数:
1 总是用new关键字调用构造函数。不能用构造函数来重置已存在对象的实例域。如d.Date(1950 ,1 ,1)是错误的。C++程序员经常忘记new 操作符。
Employee number007(“James Bond” , 100000 , hireDate); //C++ , not Java
2 不带参数的构造函数是缺省构造函数。若类没定义构造函数,Java则为该类提供缺省构造函数,并将所有实例变量设为其缺省值。因此,包含在实例域中的所有数值都被设为零,所有的对象变量都指向空。
3 顾客类没有定义无参数构造函数,因此下列的用户定义是非法的:
c = new Customer(); //错误――没有缺省构造函数
难点:
注意不要使局部变量名与实例变量名相同。例如,下面的构造函数将不设置salary实例变量:
public Employee(String n , double s , Day d){
name = n;
hireDate = d;
float salary = s;
}
私有方法:
当公有数据非常危险时,私有方法就应运而生。对使用者不关心的方法设置为私有方法。
静态方法:
静态方法只能访问静态域,如果一个方法需要访问某对象的非静态实例域,则该方法就不能为静态方法。
main方法是静态的。
重载:
Java 允许重载任何方法――不仅仅是构造函数方法。
实例域初始化:
如果不显式设置,Java将为每个实例域设置缺省值(数字域设为零,对象域设为空)。但是依赖于此种缺省值的做法不是好的编程风格。在这方面,实例变量与方法中的局部变量不同。局部变量必须被显式初始化。如果,类的所有构造函数都要将某个实例变量设置为同一值,那么可使用一个方便的初始化语句完成该初始化,即在定义类时,给该域赋值即可。例如:
class Customer{
……
private String name;
private int nextOrder = 1;
}
this指针:
如果构造函数的第一行是以this(…)形式开始,那么,该构造函数调用了该类的另一个构造函数。
在Java 中的this对象与C++的this指针相同。然而在C++里,一个构造函数不能调用另一个构造函数。
对象的析构和finalize()方法:
由于Java 有自动的垃圾回收程序,不需要手工内存回收,所以Java 不支持析构函数。
当然,除内存外,一些对象还使用其他资源,如文件或指向对象的句柄,而这个对象又使用了系统资源。此时,当不再使用这些资源时,应回收,重新利用这些资源,这是非常重要的。
dispose()方法 和 finalize()方法
四.包
关于package语句:
package语句必须是文件中注释语句后的第一个语句。
使用包:
1 如: java.util.Date today = new java.util.Date();
或者import java.util.*;
Date today = new Date();
2 不能用import java.* 装入带java 前缀的所有包。
包作用域:
方法通常应该显式声明为公共的或私有的,而实例和静态变量应是私有的。
没有说明public 或者 private 的类可以被同一包中的其他类访问。
注意:
每个源文件至多可包含一个公共类,该公共类名必须与文件名相同。
五.关于类设计的提示:
1 始终私有化数据
2 始终初始化数据
3 在类中不要使用太多的基本类型
4 不是所有的域都需要域访问方法和转变方法, 即get 和set 函数。
5 用标准格式定义类。
始终按下列顺序列出类的内容:
公共特性
包范围特性
私有特性
对上述个段中列出:
常量
构造函数
方法
静态方法
实例变量
静态变量
6 分解责任太多的类
7 让类名和方法反映他们的责任
好的作法是类名应该是名词,或前面有形容词的名词