标签:
4.1 面向对象设计概述
面向对象设计俗称oop
OOP把数据放在第一位,然后再考虑操作数据的算法。
4.1.1类
4.1.2 对象
要想使用oop 一定要清楚对象的三个特性:
对象的行为---可以对对象施加哪些操作?
对象的状态--施加那些方法后,对象如何响应?
对象标识--如何辨别具有相同行为和状态的不同对象?
对象的状态并不能完全描述一个对象,每个对象都有一个唯一的身份。
4.1.3 识别类
识别类的简单规则是在分析问题的过程中寻找名词,而方法对应着动词。
(这种原则只是一种经验)
4.1.4类之间的关系
依赖 use-a 一个类的方法操作另一个类的对象
聚合 has-a 类A的对象包含类B的对象
继承 is-a
应该尽可能减少类与类之间的依赖性,让类之间的耦合度最小
4.2使用预定义类
4.2.1对象与对象变量
在java程序设计语言中,使用构造器构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。
New 类名()的返回值也是一个对象的引用
如果将一个方法应用于值为null的引用上,为发生运行错误
局部变量不会自动初始化为Null,而必须用过new 或者将他们设置为null进行初始化
4.2.2 java类库中的GregorianCalendar类
类库包含了两个类:
表示时间点的Date类
表示大家熟悉的日历表示法的GregorianCalendar类 扩展与Calendar类 具体用法参见API
4.2.3更改器方法和访问器方法
对实例域作出修改的方法称为更改器方法
仅访问实例域而不进行修改的方法称为访问器方法
通常在访问器方法名前面加上前缀get,在更改器方法前面加上set
4.3用户自定义类
在一个源文件中,只能有一个公有类和任意数目的非公有类。文件名必须与public的类的名字相同。
package c3;
import java.util.Date;
import java.util.GregorianCalendar;
public class EmployeeTest {
public static void main(String[] args) {
Employee []staff=new Employee[3];
staff[0]=new Employee("Carl Cracker",75000,1987,12,15);
staff[1]=new Employee("Harry Hacker",50000,1989,10,1);
staff[2]=new Employee("Tony Tester",40000,1990,3,15);
for(Employee e:staff)
{
e.raiseSalary(5);
}
for(Employee e:staff)
{
System.out.println("name="+e.getName()+",salary="+e.getSalary()+",hireDay="+e.getHireDay());
}
}
}
class Employee
{
private String name;
private double salary;
private Date hireDay;
public Employee(String n,double s,int year,int month,int day)
{
name=n;
salary=s;
GregorianCalendar calendar=new GregorianCalendar();
hireDay=calendar.getTime();
}
public String getName()
{
return name;
}
public double getSalary()
{
return salary;
}
public Date getHireDay()
{
return hireDay;
}
public void raiseSalary(double byPercent)
{
double raise=salary*byPercent/100;
salary+=raise;
}
}
4.3.2多个源文件的使用
在上面的代码中,一个源文件中包含了两个类,许多程序员习惯将每一的类存在单独的源文件中,如果喜欢这样组织文件
Javac Employee*.java(*是通配符)
或者直接javac Employee.java
这样并没有显式的编译Employee.java 然而编译器发现使用了Employee类后就会查找后缀名为Employee.class的文件 如果没找到则寻找Employee.java的文件 并进行编译
4.3.3剖析Employee类
方法的关键字public意味着任何类的任何方法都可以调用这个方法
Private:确保只有Employee类自身的方法能够访问这些实例域,而其他的方法不能够读写这些域
4.3.4从构造器开始
构造器总是伴随着new操作而执行,不能进行调用
记住
构造器与类同名
每一个类可以有一个以上的构造器
构造器有0个 1个或者多个参数
构造器没有返回值
构造器总是伴着new操作而执行
4.3.5隐式参数和显式参数
显式参数用对象变量 如a.salary
隐式参数直接使用实例域:如salary(隐含着当前调用对象)
实际为this.salary
4.3.6封装的优点
如何访问 或者进行修改操作由某个类的方法决定。
注意:不要编写返回引用可变对象的访问器方法 这样如果返回这个引用给其它地方,其它地方就可以在外面直接修改数据
如在一个类中返回Date对象 如果这样 这个对象就可以通过Date类的方法修改这个类中Date类型的值
如果需要返回一个可变对象的引用,应该首先对它进行克隆,对象克隆指的是存放在另外一个位置上的对象副本。
4.3.7基于类的访问权限
类的对象的方法可以访问本对象的私有域,也可以访问本类其它对象的私有域。
4.3.8私有方法
仅在本类中使用的方法 功能与当前实现的机制非常紧密
4.3.9final实例域
Final int a 代表a是一个常量
但是final Employee e 仅代表对象变量是一个对象常量,而不代表对象不可变
4.4 静态域与静态方法
4.4.1静态域
如果将域定义为static 则每一个对象对于这样的域都会有一个相同的拷贝 它属于类 而不属于任何一个对象
4.4.2静态常量
静态变量用得比较少,但是静态常量却使用得比较多
4.4.3静态方法
没有this指针的方法
建议使用类名调用静态方法
在下面两种情况下使用静态方法
一个方法不需要访问对象状态,其所需参数都是通过显式参数提供
一个方法只需要访问静态域
4.4.4工厂方法
4.4.5main()方法
4.5方法参数
java的参数传递采用值传递
4.6对象构造
4.6. 1重载
方法有相同名字,不同参数,称为重载。编译器必须通过参数匹配方法。如果找不到匹配的参数,就会产生编译错误,这个过程也被称为重载解析。
java允许重载任何方法。
4.6.2默认域初始化
如果在构造器中没有显式的给域赋予初值,数值将默认为0,布尔值为false,对象引用为null,最好要进行初始化
4.6.3 无参数的构造器
如果在编写一个类时没有编写构造器,那么系统将会提供一个无参数构造器。(如果编写了构造器,这个构造器将不再提供)
4.6.4显式域初始化
在定义域时赋予初值,在执行构造器前就会执行赋值操作。
4.6.5参数名
注意this指针的使用和不要把局部变量和实例域混淆
4.6.6调用另一个构造器
关键字this还有另外一种含义。
如果构造器的第一个语句类似于this(“参数”)
这样就好像使用一个构造器 构造器又调用另一个构造器
4.6.7 初始化块
类的声明中,包含多个代码块。
构造过程是这样的
1 所有数据被初始化为默认值
2 按照在类声明中出现的次序,执行域初始化语句和初始化块。
3如果构造器第一行调用了第二个构造器,则执行第二个构造器主体
4 执行这个构造器主体
4.6.8对象析构与finalize方法
java有自动垃圾回收器,不需要人工回收内存,所以Java不支持析构器。
可以为任何一个类添加finalize方法,finalize方法将在垃圾回收器清楚对象前调用。在实际应用中,不要依赖于使用finalize方法回收任何短缺的资源.
4.7包
java允许使用包将类组织起来。借助于包可以方便的组织自己的代码,并将自己的代码与别人提供的代码库分开管理。
标准的java包有一个层次结构,如果硬盘的目录嵌套一样。使用包的原因是确保类名的唯一性 如果两个程序员建立了一个相同名称的类 放在不同包中就不会产生冲突
4.7.1类的导入
一个类可以使用所属包中的所有类,以及其它包中的共有类
我们可以采用两种方式访问另一个包的公有类
第一种方式是在每个类名之前添加完整的包名。例如
Java.util.Date today=new java.util.Date()
第二种方式使用import java.util.*
但是注意的是,只能使用一个*号导入一个包,而不能使用两个*号
如果使用*号发生了冲突,就要再后面继续明确哪个类
类文件的字节码肯定使用完整包名来引用其它类
4.7.2静态导入
import语句不仅可以导入类,还增加了导入静态方法和静态域的功能
例如
Import static java.lang.System.*;
就可以使用System类的静态方法和静态域了 而不必加类名前缀
4.7.3将类放入包中
使用package关键字
如果没有这个关键字,将放在默认包中,包中的文件对应硬盘上的文件存储
注意:编译器在编译源文件的时候不检查目录结构,如果一个源文件没有在某个子目录下(使用了package关键字),如果它不依赖其它包,就不会出现编译错误。但是最终程序无法运行,这是虚拟机找不到类文件。
4.7.4包作用域
通过包密封机制,使得无法再向某个包添加类
4.8类路径
类存储在文件系统的子目录中,类的路径必须与包名匹配。
在一个JAR文件中,可以包含多个压缩形式的类文件和子目录,这样既可以节省又可以改善性能。在程序中用到第三方的库文件时,通常会给出一个或多个需要包含的jar文件.JDL也提供了许多的jar文件。
4.9文档注释
jdk包含一个很有用的工具 叫做javadoc,它可以由源文件生成一个HTML文档,事实上,联机API就是这样生成的
使用/** */ 很容易地生成一个看上去具有专业水准的文档。
如果将文档存入一个独立的文件中,就有可能随着时间的推移,出现代码和注释不一致的问题。有了javadoc 注释与源代码在同一个文件中,在修改源代码的同时,重新运行javadoc可以保持一致性
4.9.1注释的插入
javadoc实用程序从下面几个特性中抽取信息
包
公有类和接口
公有的和受保护的构造器及方法
公有的和受保护的域
应该为上面几部分写注释
每个/** */文档注释在标记之后紧跟着自由格式文本,标记由@开始 如@author或@param
自由格式文本的第一句应该是一个概要性的句子,java实用程序自动地将这些句子抽取出来形成概要页。
在自由格式文本中,可以使用HTML修饰符,但有些字符会发生冲突。
4.9.2类注释
类注释必须放在import语句之后,类定义之前
4.9.3 方法注释
@param变量描述
这个标记将对当前的param(参数)部分添加一个条目。这个描述可以占据多行 并可以使用HTML标记。一个方法的所有@param标记必须放在一起
@return描述
这个标记将对当前方法添加return部分。这个描述可以跨越多行,并可以使用HTML标记
@throw类描述
这个标记将添加一个注释,用于表示这个方法有可能抛出异常
示例:
/**
* Raise the salary of an employee
* @param byPercent the percentage by which to raise the salary
* @return the amount of the raise
*/
public void raiseSalary(double byPercent)
{
double raise=salary*byPercent/100;
salary+=raise;
}
4.9.4域注释
只需要对公有域(通常指的是静态常量)建立文档。
例如
/*
* The "Hearts" card suit
*/
public static final int HEARTS =1;
4.9.5通用注释
下面的标记可以用在类文档的注释中
@author 姓名
这个标记将产生一个author条目。可以使用多个@author标记,每个@author标记对应一名作者
@version 文本
这个标记将产生一个version条目,这里的文本可以是对当前版本的任何描述。下面的标记可以用于所有的文档注释中。
@since文本
这个标记将产生一个”since”条目,这里的text可以是对引入特性的版本描述
@deprecated 文本
这个标记将对类 方法或变量添加一个不再使用的注释
通过@see和@link标记 可以使用超级链接,链接到javadoc文档的相关部分或外部文档
@see引用
这个标记将在”see also”部分增加一个超级链接。它可以用于类中,也可以用于方法中。
4.9.6 包与概述注释
4.9.7注释的抽取
4.10类设计技巧
简单地介绍几点技巧,应用这些技巧可以使得设计出来的类更具有oop的专业水准。
1 一定要保证数据私有 绝对不要破坏封装性
2 一定要对数据初始化
3 不要在类中使用过多的基本类型
4 不是所有的域都需要独立的域访问器和更改器
5 将职责过多的类分解
6 类名和方法名要体现他们的职责
标签:
原文地址:http://www.cnblogs.com/HJL085/p/5736359.html