1,面向对象程序设计(OOP)
类class
由类构造对象的过程称为创建类的实例(instance)。
封装
形式上封装将数据的行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。对象中的数据称为实例域,操作数据的过程称为方法。实现封装的关键就啊是不能让类中的方法直接地访问其他类的实例域。
继承
通过扩展一个类来建立另外一个类。“神通广大的超类” Object。
对象
三个主要的特性:行为,状态,标识
行为改变状态,状态影响行为。
识别类
面向过程的程序设计,从顶部的main函数开始编写程序。面向对象的话,可以首先从设计类开始,再往每个类中添加方法。
一个简单的识别类的规则是在分析问题的过程中寻找名词,而方法对应着动词。
类之间的关系
依赖:如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。应该尽可能地减少类与类之间的依赖,即,让类之间的耦合度最小。
聚合:类A对象包含着类B的对象
继承
UML(统一建模语言)绘制类图,描述类之间的关系。
2,使用预定义类
对象和对象变量
任何对象变量的值都是对存储在另外一个地方的一个对象的引用。比如
Date deadline = new Date();
表达式new Date()构造了一个Date类型的对象,并且它的值是对新创建对象的引用,这个引用存储在变量deadline中。
所有java对象都存储在堆中。
如何构造对象 以及如何调用类的方法
3,用户自定义类
类最简单的定义形式
class ClassName
{
//实例域
field1
field2
···
//构造器
constrcutor1
constrcutor2
···
//方法
method1
method2
···
}
可以用public,private,protected关键字修饰;private表明只有类自身的方法能够访问,而其他类的方法不能够读写。
从构造器开始
- 构造器与类同名
- 每个类可以有一个以上的构造器
- 构造器可以有0,1,或者多个参数
- 构造器没有返回值
- 构造器总是伴随着new操作一起使用
方法的隐式参数和显式参数
隐式参数是指。出现在方法名前的类对象,在每一个方法中,关键字this表示隐式参数。
显式参数是指方法名后面括号中的参数,即我们通常说的参数。
封装的优点
通常需要获得或者设置实例域的值,应该提供下面三项内容:
一个私有的数据域
一个公有的域访问器方法(get)
一个公有的域更改器方法(set)
相比提供一个简单的公有数据域,这样的优点是:
一是可以改变访问器或者更改器的内部实现,不会影响其他代码。
二是更改器方法可以执行错误检查。
注意:不要编写返回引用可变对象的访问器方法;如果需要返回一个可变数据域的拷贝,应该使用clone,要不然引用同一个对象,会改变这个对象的私有状态。
基于类的访问权限:一个方法可以访问所属类的所有对象的私有数据(不仅仅可以所调用对象的私有数据哦)
final实例域
构建对象时必须初始化这样的域,即,必须确保每一个构造器执行之后,这个域的值被设置,并且在后面的操作中,不能再对它进行修改。
大都应用于基本类型域,或者不可变类的域(如String类)。
4,静态域与静态方法
静态域:static修饰,每个类中只有一个这样的域,它属于类,而不属于任何独立的对象。即,所有对象共享这样一个域。
静态常量用的比较多
静态方法:不能向对象实施操作的方法,所以访问不了类的属于对象属性的实例域,但是可以访问自身类中的静态域。建议使用类名而不是对象名访问静态方法,因为得到的结果的具体的对象毫无关系。
总结:在下面两种情况中使用静态方法
i. 一个方法不需要访问对象状态,其所有参数都是通过显式参数提供
ii.一个方法只需要访问类的静态域
另外,可以使用静态工厂方法(factory method)来构造对象,生成不同风格的格式化对象。为什么使用静态工厂方法而不用构造器,两个原因:构造器的名字必须和类名相同,构造器的返回类型无法改变。
main方法也是静态方法,不对任何对象进行操作,实际上,在启动程序时还没有任何一个对象。
5,方法参数
java总是按值调用,而不是引用。
例1 按值调用
public static void tripleValue(double x)
{
x = x*3;
}
double percent = 10;
tripleValue(percent);//percent = 10
例2 对象引用也是按值传递
public static void tripleSalary(Employee x)
{
x.raiseSalary(200);
}
harry = new Employee(···);
tripleSalary(harry);//harry = 600; 引用拷贝给x,harry和x指向同一个对象
public statc void swap(Employee x,Employee y)
{
Employee temp = x;
x = y;
y = temp;
}
Employee a = new Employee("Alice",···);
Employee b = new Employee("Bob",···);
swap(a,b);//并不会交换a和b的值,因为a和b的值拷贝到x和y中,交换的是x和y的值
总结:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
- 一个方法可以改变一个对象参数的状态。
- 一个方法不能让对象参数引用一个新的对象。
6,对象构造
重载 overload
如果多个方法,有相同的名字,不同的参数,便产生了重载。java允许重载任何方法。
要注意的一点是,方法名以及参数类型是一个方法的签名,返回类型不是方法签名的一部分,所以不能有两个名字相同、参数类型也相同但是返回不同类型值的方法。
编译器根据,各个方法给出的参数类型,以及特定方法调用所使用的值类型进行匹配来挑选出相应的方法 的这个过程叫重载解析。
默认域初始化
如果在构造器中没有显式地给域赋予初值,则hi自动地被赋为默认值:数值为0,布尔为false,对象引用为null。这样会影响代码的可读性。
三种初始化数据域的方法
在构造器中设置值
无参数构造器
如果在编写一个类时没有编写构造器,系统会提供一个无参数构造器。这个系统提供的无参数构造器只在类没有提供任何构造器的时候才会有。
调用另一个构造器
如果构造器的第一个语句形如this(···),这个构造器将调用同一个类的另一个构造器。
显式域初始化
:在类定义中,直接将一个值赋给任何域。初始值不一定非得是常量值,也可以调用方法对域进行初始化。例如
class Employee
{
private String name = "";
···
}
class Employee
{
private static int nextId;
private int id = assignId();//调用了方法对域进行初始化
···
private static int assignId()
{
int r = nextId;
nextId++;
return r;
}
···
}
初始化块
在一个类的声明中,可以包含多个代码块,只要构造类的对象,这些块就会被执行。
class Employee
{
private static int nextId;
private int id;
private String name;
private double salary;
//static initialization block
static
{
Random generator = new Random();
nextId = generator.nextInt(10000);
}
//object initialization block
{
id = nextId;
nextId++;
}
}
明确调用构造器的具体步骤
- 所有数据域被初始化为默认值(0,false,null);
- 按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块;
- 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体;
- 执行这个构造器的主体。
7,包
包的导入:import
将类放入包中:package语句(包中的文件需要放到与完整的包名匹配的子目录中)
包作用域:
public可以被任意的类使用
private只能被定义他们的类使用
如果没有指定public或者private,这部分(类,变量,方法)可以被同一个包中的所有方法访问。
在默认情况下,包不是一个封闭的实体,即,任何人都可以向包中添加更多的类。使用包密封机制来解决各种包混杂在一起的问题。如果将一个包密封起来,就不能再向这个包添加类了。(Jar文件)
8,类路径
类路径是包含所有类文件的路径的集合。
9,文档注释
10,类设计技巧