三大特性
封装
- 利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户无需知道对象内部的细节,但可以通过对象对外提供的接口来访问该对象。
优点:
- 减少耦合: 可以独立地开发、测试、优化、使用、理解和修改
- 减轻维护的负担: 可以更容易被程序员理解,并且在调试的时候可以不影响其他模块
- 有效地调节性能: 可以通过剖析确定哪些模块影响了系统的性能
- 提高软件的可重用性
- 降低了构建大型系统的风险: 即使整个系统不可用,但是这些独立的模块却有可能是可用的
- 以下 Person 类封装 name、gender、age 等属性,外界只能通过 get() 方法获取一个 Person 对象的 name 属性和 gender 属性,而无法获取 age 属性,但是 age 属性可以供 work() 方法使用。
注意到 gender 属性使用 int 数据类型进行存储,封装使得用户注意不到这种实现细节。并且在需要修改 gender 属性使用的数据类型时,也可以在不影响客户端代码的情况下进行。
public class Person {
private String name;
private int gender;
private int age;
public String getName() {
return name;
}
public String getGender() {
return gender == 0 ? "man" : "woman";
}
public void work() {
if (18 <= age && age <= 50) {
System.out.println(name + " is working very hard!");
} else {
System.out.println(name + " can't work any more!");
}
}
}
继承
- 继承实现了 类的父子继承关系,例如 Cat 和 Animal 就是一种 类的父子继承关系,因此 Cat 可以继承自 Animal,从而获得 Animal 非 private 的属性和方法。
- 继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。
Cat 可以当做 Animal 来使用,也就是说可以使用 Animal 引用 Cat 对象。父类引用指向子类对象称为 向上造型 。
pbulic class Cat extends Animal(){...} Animal animal = new Cat();
多态
多态分为编译时多态和运行时多态:
- 编译时多态主要指方法的重载
- 运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定
- 运行时多态有三个条件:
- 继承
- 重写
- 向上转型
- 下面的代码中,乐器类(Instrument)有两个子类: Wind 和 Percussion,它们都重写了父类的 play() 方法,并且在 main() 方法中使用父类 Instrument 来引用 Wind 和 Percussion 对象。在 Instrument 引用调用 play() 方法时,会执行实际引用对象所在类的 play() 方法,而不是 Instrument 类的方法。
```java
public class Instrument {
public void play() {
} }System.out.println("Instrument is playing...");
public class Wind extends Instrument { public void play() { System.out.println(“Wind is playing…”); } }
public class Percussion extends Instrument { public void play() { System.out.println(“Percussion is playing…”); } }
public class Music {
public static void main(String[] args) {
List
<a name="kbvTf"></a>
# 类图
<a name="pN0au"></a>
## 泛化关系 (Generalization)
- 用来描述继承关系,在 Java 中使用 extends 关键字。
- 他们之间通过实线加三角形连接,箭头指向被继承的父类
![1655625314(1).png](https://cdn.nlark.com/yuque/0/2022/png/26235396/1655625317839-8edb9aa3-0e59-47cc-b2ad-525b91ad0420.png#clientId=u7bbe261b-617a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=210&id=uc03bf1cd&margin=%5Bobject%20Object%5D&name=1655625314%281%29.png&originHeight=263&originWidth=240&originalType=binary&ratio=1&rotation=0&showTitle=false&size=18365&status=done&style=none&taskId=u4e6eccc6-55ed-4fa1-939b-e970b1f1955&title=&width=192)
<a name="w3vln"></a>
## 实现关系 (Realization)
- 用来实现一个接口,在 Java 中使用 implement 关键字。
- 他们之间通过虚线加三角形连接,箭头指向被实现的接口
![1655625533(1).png](https://cdn.nlark.com/yuque/0/2022/png/26235396/1655625536020-4975ca2b-8154-4376-9cc5-b67c60587220.png#clientId=u7bbe261b-617a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=209&id=ue787afe0&margin=%5Bobject%20Object%5D&name=1655625533%281%29.png&originHeight=261&originWidth=201&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21616&status=done&style=none&taskId=u08581461-2abc-4048-895a-8b53a954eb4&title=&width=160.8)
<a name="fhKcY"></a>
## 依赖关系 (Dependency)
和关联关系不同的是,依赖关系是在运行过程中起作用的。A 类和 B 类是依赖关系主要有三种形式:
- A 类是 B 类中的(某中方法的)局部变量;
- A 类是 B 类方法当中的一个参数;
- A 类向 B 类发送消息,从而影响 B 类发生变化;
![1655626070(1).png](https://cdn.nlark.com/yuque/0/2022/png/26235396/1655626073436-238c2a8d-2a8c-454f-bb3a-afc8e495c521.png#clientId=u7bbe261b-617a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=246&id=uad79308e&margin=%5Bobject%20Object%5D&name=1655626070%281%29.png&originHeight=307&originWidth=449&originalType=binary&ratio=1&rotation=0&showTitle=false&size=34256&status=done&style=none&taskId=uef06cc82-706b-4f3f-b6b4-4dc719366dd&title=&width=359.2)
<a name="ZMdhY"></a>
## 关联关系 (Association)
1. 表示不同类对象之间有关联,这是一种静态关系,与运行过程的状态无关,在最开始就可以确定。因此也可以用 1 对 1、多对 1、多对多这种关联关系来表示。比如学生和学校就是一种关联关系,一个学校可以有很多学生,但是一个学生只属于一个学校,因此这是一种多对一的关系,在运行开始之前就可以确定。
1. 关联关系还能细分为聚合关系和组合关系
![1655625988(1).png](https://cdn.nlark.com/yuque/0/2022/png/26235396/1655625991696-a19a7a2c-dd77-4839-948e-fd4e7da7afc7.png#clientId=u7bbe261b-617a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=109&id=u8e650dfe&margin=%5Bobject%20Object%5D&name=1655625988%281%29.png&originHeight=136&originWidth=292&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13721&status=done&style=none&taskId=ucb1d53e9-819f-4fd4-8a1e-b69981f2a5d&title=&width=233.6)
<a name="hASDe"></a>
### 聚合关系 (Aggregation)
- 表示整体由部分组成,但是整体和部分**不是强依赖的**,**整体不存在了部分还是会存在**。
- 他们之间通过实线加菱形连接,箭头指向整体.
![1655625637(1).png](https://cdn.nlark.com/yuque/0/2022/png/26235396/1655625640064-eae75a40-e174-443c-b15a-afd90e170a93.png#clientId=u7bbe261b-617a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=216&id=mst9n&margin=%5Bobject%20Object%5D&name=1655625637%281%29.png&originHeight=270&originWidth=458&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31529&status=done&style=none&taskId=u768e823b-55a7-4321-994e-0062339f694&title=&width=366.4)
<a name="dxIrV"></a>
### 组合关系 (Composition)
- 和聚合不同,组合中整体和部分是强依赖的,**整体不存在了部分也不存在了**。
- 他们之间通过实线加实心菱形连接,箭头指向整体.
![1655625814(1).png](https://cdn.nlark.com/yuque/0/2022/png/26235396/1655625822834-42c5305a-48b4-47cb-b637-546afc2db1c0.png#clientId=u7bbe261b-617a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=221&id=qSH21&margin=%5Bobject%20Object%5D&name=1655625814%281%29.png&originHeight=276&originWidth=411&originalType=binary&ratio=1&rotation=0&showTitle=false&size=25503&status=done&style=none&taskId=ubb6f9eca-ab5e-4773-a26a-544dc157dbc&title=&width=328.8)
<a name="TwIcC"></a>
#### 注意区分
- 比如公司和部门是组合关系,公司没了部门就不存在了。
- 但是公司和员工就属于聚合关系了,因为公司没了员工还在。
<a name="JSYB1"></a>
# 内部类
<a name="mM8pX"></a>
## 1.成员内部类:
1.定义:类中套类,外面的称为外部类,里面的称为内部类<br />2.内部类通常只服务于外部类,对外不具备可见性<br />3.内部类对象通常在外部类中创建<br />2.内部类中可以直接访问外部类的成员(包括私有的)<br /> 内部类中有个隐式的引用指向了创建它的外部类对象:**外部类名.this**
```java
public class InnerClassDemo {
public static void main(String[] args) {
Mama m = new Mama();
//Baby b = new Baby(); //编译错误,内部类对外不具备可见性
}
}
class Mama{ //外部类
private String name;
void create(){
Baby b = new Baby(); //正确,内部类对象通常在外部类中创建
}
class Baby{ //内部类
void showName(){
System.out.println(name); //省略写法
System.out.println(Mama.this.name); //完整写法
//System.out.println(this.name); //编译错误,this指代当前Baby对象
}
}
}
2.匿名内部类:
———————————-大大简化代码
1.匿名内部类适用场景:若想创建一个类(派生类)的对象,并且对象只被创建一次,可以做成匿名内部类
2.在匿名内部类中默认外面的变量为final的——这是规定,记住就行了
3.内部类有独立的.class外部类名字$内部类名字(没有名字就是123的数字)
public class NstInnerClassDemo {
public static void main(String[] args) {
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o1
//3)大括号中的为派生类的类体
Aoo o1 = new Aoo(){类体};
//1)创建了Aoo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o2
//3)大括号中的为派生类的类体
Aoo o2 = new Aoo(){类体};
int num = 5;
num = 55;
//1)创建了Boo的一个派生类,但是没有名字
//2)为该派生类创建了一个对象,名为o3
//3)大括号中的为派生类的类体
Boo o3 = new Boo(){
void show(){
System.out.println("showshow");
//在匿名内部类中会默认外面的变量为final的所以无法更改
//num = 55; //编译错误,并且外部类更改过内部类甚至不能再用
}
};
o3.show();
}
}
abstract class Boo{
abstract void show();
}
abstract class Aoo{
}
隐式的引用:
1.this:指代当前对象
2.super:指代当前对象的超类对象
3.外部类名.this:指代当前对象的外部类对象