第二章、面向对象
一、类和对象
1、基本概念
1)什么是对象
万物皆对象、客观存在的事物。
对象:用来描述客观事物的一个实体,由一组属性和方法构成。
2)什么是面向对象
人关注对象
人关注事物信息
3)什么是类
类是模子,确定对象将会拥有的特征(属性)和行为(方法)。
类的特点:
类是对象的类型。
具有相同属性和方法的一组对象的集合。
4)什么是对象的属性和方法
属性:对象具有的各种静态特征。
“有什么”
方法:对象具有的各种动态行为
“能做什么”
5)类和对象的关系
类是抽象的概念,仅仅是模板。
对象是一个你能够看得到、摸得着的具体实体。
类是对象的类型。
对象是特定类型的数据。
具体开发过程中,先定义类再实例化对象。
2、单一职责原则
单一职责原则(SRP:Single responsibility principle)又称单一功能原则,面向对象五个基本原则(SOLID: SRP 单一责任原则、OCP 开放封闭原则、LSP 里氏替换原则、DIP 依赖倒置原则、ISP 接口分离原则)之一。
它规定一个类应该只有一个发生变化的原因。
所谓职责是指类变化的原因。
如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。
而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。
单一职责原则告诉我们:
一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。
出现单一职责原则原因:
之所以会出现单一职责原则就是因为在软件设计时会出现以下类似场景:T负责两个不同的职责:职责 P1,职责 P2。当由于职责 P1 需求发生改变而需要修改类 T 时,有可能会导致原本运行正常的职责P2 功能发生故障。也就是说职责 P1 和 P2被耦合在了一起。
解决办法:遵守单一职责原则,将不同的职责封装到不同的类或模块中。分别建立两个类 T1、T2,使 T1 完成职责 P1 功能,T2 完成职责 P2 功能。这样,当修改类 T1 时,不会使职责 P2 发生故障风险;同理,当修改 T2 时,也不会使职责 P1发生故障风险。
3、对象实例化
实例化对象的过程可以分为两部分:
- 声明对象 Cat one;
- 实例化对象 new Cat();
每次new对象会产生新的实例化对象。
多个对象可以指向同一块实例化空间。
对象必须被实例化之后才能使用。
对象间的引用传递,实际上传递的是堆内存空间的使用权。
1)Java内存管理之堆和栈
栈:存储局部信息的值,如:方法体中的基本数据类型定义的变量、对象的引用等。当局部作用范围结束时,栈内信息立即自动释放。
当存储内容是由基本数据类型(byte、short、int、long、float、double、char、boolean)声明的局部变量时,在栈中存储的是它们对应的具体数值。
当存储的是局部对象的引用(定义在方法体中的引用类型的变量),存储的是具体对象在堆中的地址。没有时为null。
堆:用来存放动态产生的数据,如:new出来的对象。当对象使用结束,并确定已无实例引用指向堆空间时,JVM才会依据相关垃圾回收机制进行资源回收,完成堆内资源释放。
需要注意:创建出来的对象只包含属于各自的成员变量,并不包括成员方法。(同一个类的方法被不同实例共享)
4、构造方法
1、构造方法与类同名且没有返回值 。
2、构造方法的语句格式 。
public 类名(参数列表){
//初始化代码
}
3、只能在对象实例化的时候调用。
4、当没有指定构造方法时,系统会自动添加无参的构造方法 。
5、当有指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参的构造方法 。
6、一个类中可以有多个构造方法。
5、this关键字
this是Java中常用的关键字,代表当前对象本身。
this的使用:
类方法中调用成员变量,可以用this 关键字,解决成员属性和局部变量同名冲突。
类方法中调用其他成员方法,可以用this关键字,也可以省略this关键字。
调用重载的构造方法:
1、可以在构造方法中,通过this调用本类的另一个构造方法,且必须置于第一行。
2、可以通过this调用本类中带参或无参构造方法,调用带参构造方法时,需要按顺序传入设定的参数。
3、在一个构造方法内只能调用一个构造方法。
4、不能在类中普通成员方法内通过this调用构造方法。
6、包
作用:
1、管理Java文件。
2、解决同名文件冲突。
1)定义包
语法:
package 包名;
例:package com.ql.animal;
注意:
1、必须放在Java源文件中的第一行。
2、一个Java源文件中只能有一个package语句,若缺省则指定为无名包。
3、包名全部英文小写。
4、命名方式:域名倒序.模块.功能,其中用"."来指明包的层次。
基于合理分类,便于管理的思想,约定:
1、推荐将一组互相具有联系并组合起来完成某一功能的类聚集到同一个包中。
2、同一包中,类名不允许重复。
3、不同包中,可以存在同名类。
2)导入包
语法:
import 包名.类名;
例:
导入包中全部类:
import com.ql.*;
导入包中指定类:
import com.ql.animal.Cat;
注意:
1、一个Java文件中可以有多条import语句。
2、java.lang包是默认导入的。
3、import需要写在class语句上面,即一个Java文件中存在顺序是:package - import - class
3)常用系统包
java.lang - - 包含java语言基础的类
java.util - - 包含java语言中各种工具类
java.io - - 包含输入、输出相关功能的类
7、static
static是Java中常用关键字,代表"全局"或者"静态"的意思。
1、static+属性 - - 静态属性
2、static+方法 - - 静态方法
3、static+类 - - 不存在
4、static+方法内局部变量 - - 不存在
1)静态属性
概念:
静态成员:用static修饰的成员变量,通常也称为静态成员、静态属性、类成员、全局属性等。
非静态成员:没有被static修饰的成员变量,也称为叫非静态成员、实例变量、实例成员、对象成员、对象属性等。
特征:
静态成员:
1、静态成员是属于整个类的,由类所进行维护,仅在类初次加载时会被初始化,在类销毁时回收。
2、通过该类实例化的所有对象都共享类中静态资源,任一对象中信息的修订都将影响所有对象。
3、由于静态成员在类加载期间就已经完成初始化,存储在Java Heap 堆(Jdk7.0之前存储在方法区)中静态存储区,因此优先于对象而存在,可以通过类名和对象名两种方式访问。
4、可以将频繁调用的公共信息、期望加快运行效率的成员设置为静态,但是注意,由于其生命周期长,资源占用周期长,要慎用。
非静态成员:
1、非静态成员属于对象独有,每个对象进行实例化时产生各自的成员,随着对象的回收而释放。
2、对象对各自成员信息的修订不影响其他对象。
3、只能通过对象名访问。
2)静态方法
概念:
静态方法:用static修饰的成员方法,通常也称为静态方法、类方法、全局方法。
非静态方法:没被static修饰的成员方法,通常也称为非静态方法、实例方法、对象方法。
特征:
与静态成员相似,静态方法属于整个类的,由类进行维护,优先于对象而存在,因此可以通过类名和对象名两种方式访问,也因此在静态方法中无法直接访问同类中的非静态成员。
3)静态代码块
概念:
普通代码块:定义在方法内部,用{}括起的代码段。
构造代码块:定义在类内部,用{}括起的代码段。
静态代码块:被static修饰的,定义在类内部,用{}括起的代码段。
特征:
普通代码块:
1、可以在方法内出现多次,按顺利在方法调用时执行。
2、可以定义局部变量,作用范围为:自定义位置起,至该代码块结束。
3、方法内定义的局部变量,作用范围为:自定义位置起,至该方法结束,在此期间,不允许在普通代码快中声明同名的局部变量。
构造代码块:
1、可以在类内出现多次,按顺序在每个对象实例化时执行。
2、执行优先级:晚于静态代码块,高于构造方法。
3、每次执行对象实例化时,均会执行一次。
4、可以在构造代码块中直接操作静态和非静态成员。
静态代码块:
1、只能出现在类内,不允许出现在方法内。
2、可以出现多次,按顺序在类加载时执行。
3、无论该类实例化多少对象,只执行一次。
4、不能在静态代码块中直接对非静态成员赋值。
5、不能在静态代码块中声明静态成员,可以声明局部成员。
8、访问修饰符
访问修饰符 | 本类 | 同包 | 子类 | 其他 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
二、面向对象特性
面向对象有三大特性:封装、继承、多态。
1、封装
将类的某些信息隐藏在类内部,不允许外部程序直接访问。
通过该类提供的方法来实现对隐藏信息的操作和访问。
特点:
1、只能通过规定的方法访问数据。
2、隐藏类的实例细节,方便修改和实现。
2、继承
一种类与类之间的关系。
使用已存在的类的定义作为基础建立新类。
新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。
特点:
1、利于代码复
2、缩短开发周期
1)继承的关系
满足“A is a B ”的关系就可以形成继承关系
如:
猫、狗是动物 =》 猫,狗继承自动物
学生、老师是人 =》 学生,老师继承自人
小轿车、大卡车是汽车 =》 小轿车,大卡车继承自汽车
2)实现继承
使用extends实现封装
//编写父类
class Animal{
//公共的属性和方法
}
//编写子类,继承父类
class Cat extends Animal{
//子类特有的属性和方法
}
class Dog extends Animal{
//子类特有的属性和方法
}
/**
* 注:
* 1、子类只能继承一个父类。
* 2、父类不可以访问子类特有成员。
*/
3)方法重写
语法规则:
在子类中定义,方法名、参数类型、顺序、个数都要与父类继承的方法相同,参数名可以不同。
当子类重写父类方法后,子类对象调用的是重写后的方法。
4)方法重写与方法重载
方法重写:
1、在满足继承关系的子类中。
2、方法名、参数个数、顺序、类型与父类相同。
3、当返回值是void或基本数据类型时,必须相同;当返回值是引用类型时,可以是父类或其子类。
4、访问修饰符的限定范围大于等于父类方法。
5、与方法的参数名无关。
方法重载:
1、在同一个类中。
2、方法名相同。
3、参数个数、顺序、类型不同。
4、返回值类型、访问修饰符任意。
5、与方法的参数名无关。
注:
1、方法重写存在,属性重写不存在的,但是在子类中,可以定义与父类重名的属性。
2、父类构造方法不允许被继承和重写。
5)super
子类访问父类成员
1、访问父类成员方法
super.print(