面向对象总结
1. 什么是面向对象
1.1 面向对象(Object Oriented)是一种思想,90年代以后软件开发的主流思想.由于现实社会是由各种各样的事物所组成的,
而我们编程又是在模拟现实社会,那么在程序也要用一些东西来表示现实社会中的事物,这些东西就是程序中的对象。
我们在程序中使用这些对象,对其特征和行为进行操作进行编程,这就是面向对象编程。在使用面向对象编程思想之前,
我们通常用面向过程的思想编程,先分析出解决问题的步骤,然后按照步骤一步一步实现。
1.2 面向对象编程的优点
1.2.1 提高代码复用性。
1.2.2 使用者无需关心具体细节。
1.2.3 转变程序员角色,更加符合人的思维习惯。
2. 类与对象
2.1 什么是类: 类是用来描述对象的。由于对象是虚拟出来的东西,是看不见摸不着的,我们需要在程序中使用对象,
就需要用一种方式来描述对象,然后根据这个描述来创建对象。
2.2 类和对象的关系: 对象是类的实例,类是对象的描述。
2.3 怎么定义类: 将一系列特征相似的对象的共同特征及行为抽取出来进行描述,写在一个class中,
用成员变量描述对象的特征,用成员方法来描述对象的行为。
class Person { String name; int age; void speak(){System.out.println("My name is " + name);System.out.println("I am " + age + " years of age"); }}
2.4 怎么使用类创建对象:使用new关键字和指定类名来创建一个对象。
//对象的产生
Person p = new Person();
这句话先在堆内存中创建了一个对象,然后栈内存中创建一个变量引用了对象的地址。
2.5 成员变量初始化
当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。
基本数据类型初始化值为0,引用数据类型初始化值为null。
2.6 对象的使用:当我们创建对象之后可以使用点语法来访问对象的属性和方法。例如:
Person p = new Person();
p.name = "张三"; // 访问属性(成员变量)
p.age = 20;
p.speak(); // 访问方法
2.7 对象的生命周期:对象的生命周期从new关键字创建时开始,到没有任何引用到达对象时结束(成为垃圾)。
2.8 匿名对象
2.8.1 我们可以不定义变量引用对象,使用new关键字创建对象后直接使用,这样的对象没有名字,所以叫匿名对象。
2.8.2 通常我们需要使用一个对象且只使用一次的时候,就可以使用匿名对象。比如将对象作为一个参数传递给另外一个函数。
2.8.3 匿名对象因为没有任何引用到达,在使用一次之后即成为垃圾。
3. 封装(Encapsulation)
3.1 什么是封装?
将一类事物的特征和行为定义在一起,可以通过这个定义创建对象,使用对象进行编程
封装时需要将对象的属性和一些实现细节隐藏,仅对外提供必须的访问方式。
3.2 怎么封装?
将所有属性隐藏,提供公有方法对其访问。
将不需要对外提供的方法隐藏。
3.3 封装的优点
3.3.1 提高安全性:在访问对象的属性时候通过方法实现,在方法中可以进行校验。隐藏不必要提供的方法避免错误的调用。
3.3.2 简化编程:使用者无需关心对象内部具体实现细节,只要根据对象功能调用指定方法。
4. 构造函数(Constructor)
4.1什么是构造函数?
4.1.1 构造函数是一个特殊的函数。
4.1.2 函数名和类名相同。
4.1.3 没有返回值类型。注意:没有返回值类型不等同于void。
4.1.4 在使用new关键字创建对象之后自动调用。
4.2 构造函数的重载
构造函数的重载和普通函数相同,函数名相同,参数列表不同即可。
4.3 构造函数的调用
4.3.1 构造函数在new关键字创建对象时调用。
4.3.2 构造函数可以在该类其他构造函数的第一个语句使用this关键字调用。
4.4 所有类都有构造函数
每一个类都有构造函数,即使我们没有显式定义构造函数,也会生成一个默认无参的构造函数,其中没有任何内容。
生成的构造函数只在未定义任何构造函数时生成,如果我们定义了一个有参的构造函数,那么就不会生成无参的了。
4.5 构造函数的访问权限
4.5.1 在定义构造函数时,如无特殊需要,应使用public关键字修饰构造函数。
4.5.2 在一些特定情况下,我们不想让别人创建该类对象,那么可以使用private修饰构造函数,例如单态设计模式。
4.6 this关键字
4.6.1 this关键字除了在构造函数中调用其他构造函数以外,还可以当做一个引用使用。其用于方法中,
哪个对象调用该方法,this就引用哪个对象。
4.6.2 方法中局部变量和成员变量重名,我们想调用成员变量时就可以使用this.变量名形式访问成员变量。
4.6.3 在方法中要将调用该方法的对象作为参数传递给另一个方法时,可以将this作为实参传给该方法。
4.6.4 在内部类中访问外部类的成员时,需要使用外部类名.this.成员名形式访问。
4.7 函数的参数传递
4.7.1 基本数据类型的变量作为实参传入函数之后,在函数中将形参改变,调用处的实参不变。
因为基本数据类型的值是直接存在变量中,传入函数之后函数中的形参也同样存了一个值,
这两个值是没有联系的,所以函数中将形参改变时修改的只是函数中的变量的值,和调用处的实参无关。
4.7.2 引用数据类型的变量作为实参传入函数之后,在函数中将形参改变,调用处的实参改变。
因为引用数据类型变量中存储的是地址,传入函数之后函数中的形参存储的也是同样一个地址,
函数中将这个形参改变时改变的都是同一个地址上的对象,所以一边改变两边都变。
5. static关键字
5.1 static关键字用来修饰类的成员,被这个关键字修饰的成员都和类加载有关。
5.2 JVM运行时不会将所有类加载到内存,因为无法确定程序中要使用哪些。类在第一次使用时加载,只加载一次。
5.3 静态变量
5.3.1 用static修饰的变量就是静态变量。
5.3.2 静态变量在类加载后就初始化。
5.3.3 静态变量被类的所有实例所共享。
5.3.4 静态变量可以使用 类名.变量名 形式访问。
5.3.5 如果在定义一个类的时候,发现一个成员变量需要被所有实例所共享,那么这个成员变量就需要定义为static的。
5.4 静态方法
5.4.1 用static修饰的方法就是静态方法。
5.4.2 静态方法在类加载后就可以使用。
5.4.3 静态方法可以使用 类名.方法名 形式访问。
5.4.4 静态方法不能直接访问外部非静态成员。
因为外部非静态成员必须在类创建对象之后才能使用,而静态方法可以在没创建对象时就使用。
如果要在静态方法内部访问外部非静态成员,需要先创建该类对象,通过对象访问。
5.4.5 静态方法中不能使用this关键字。
因为this是个引用,哪个对象调用方法就引用哪个对象。而静态方法有可能不是被对象调用的,this无从引用。
5.4.6 如果一个方法不用访问非静态成员,那么就可以定义为静态的,这样使用者就不需要创建对象,直接用类名调用。
静态方法通常是作为工具方法或者一个可以产生对象的方法被声明,目的是为了让调用者更方便的使用,
不必创建对象。
5.5 静态代码块:用static修饰的代码块就是静态代码块。
5.5.1 静态代码块在类加载后执行。
5.5.2 静态代码块和静态方法相同,不能使用外部非静态成员。
5.5.3 静态代码块执行和静态变量的初始化顺序由代码从上到下顺序决定。
5.5.4 如果我们有一段代码想在别人使用某个类的时候就运行, 而且只运行一次, 那么就可以写在静态代码块中.
5.6 静态内部类
5.6.1 用static修饰的内部类就是静态内部类。
5.6.2 静态内部类在类加载后就可以创建对象,无需创建外部类对象。
6. 垃圾回收
6.1 对象在没有任何引用可以到达时,生命周期结束,成为垃圾。
6.2 所有对象在被回收之前都会自动调用finalize()方法。
6.3 一个对象在成为垃圾之后不会被马上回收,JVM会检测内存中的垃圾堆积到一定程度时才会回收,
如果我们不想等到这个时候才回收,可以使用System.gc()方法来通知虚拟机回收垃圾。
调用该方法之后JVM会开启新线程做处理垃圾的工作,这需要一定时间。
7. 单态设计模式(SingletonPattern)
7.1 什么是设计模式
在编程过程中我们经常会遇到一些典型的问题或需要完成某种特定需求,而这些问题和需求前人也曾经遇到过,
他们经过大量理论总结和实践验证之后优选出的代码结构、编程风格、以及解决问题的思考方式,这就是设计模式(Design pattern)。
设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免得我们自己再去思考和摸索。
7.2 单态(单例)设计模式
单态设计模式(Singleton pattern)就是要保证在整个程序中某个类只能存在一个对象,这个类不能再创建第二个对象。
7.3 单态设计模式的写法
7.3.1 私有化构造函数,阻止创建新对象。
7.3.2 由于需要返回一个对象,那么我们就需要在类内部自己创建一个对象,并使用成员变量记住它。
由于该类不能创建对象,所以这个成员变量不能是普通的成员变量,需要静态,这样在类加载之后就可以创建一个唯一的对象了。
我们不希望其他类修改这个成员变量,所以将其私有。
7.3.3 提供一个公有的方法用来获取唯一的一个对象。这个方法由于需要在不创建对象的情况下使用,所以需要静态。
/*
* 饿汉式:
* 1,将构造函数私有
* 2,创建本类的对象,用private static final修饰
* 3,提供公共的方法用来返回这个对象,用static修饰
* ----------------------------------------------
* 懒汉式:
* 1,将构造函数私有
* 2,声明本类的对象,用private static修饰
* 3,在方法内部做判断对象的引用是否为空,为空则创建对象
*/
class Persion {
private Persion() {
} // 将构造函数私有,禁止其它类创建对象
/*
// 饿汉式
private static final Persion p = new Persion();
public static Persion getPersion() {
return p;
}
*/
// 懒汉式
private static Persion p = null;
public static synchronized Persion getPersion() {
if (p == null)
synchronized (Persion.class) {
if (p == null) {
p = new Persion();
}
}
return p;
}
}
/*
* 饿汉式:
* 1,将构造函数私有
* 2,创建本类的对象,用private static final修饰
* 3,提供公共的方法用来返回这个对象,用static修饰
* ----------------------------------------------
* 懒汉式:
* 1,将构造函数私有
* 2,声明本类的对象,用private static修饰
* 3,在方法内部做判断对象的引用是否为空,为空则创建对象
*/
class Persion {
private Persion() {
} // 将构造函数私有,禁止其它类创建对象
/*
// 饿汉式
private static final Persion p = new Persion();
public static Persion getPersion() {
return p;
}
*/
// 懒汉式
private static Persion p = null;
public static synchronized Persion getPersion() {
if (p == null)
synchronized (Persion.class) {
if (p == null) {
p = new Persion();
}
}
return p;
}
}