Java笔记——面向对象编程(中级)
面向对象编程(中级)
IntelliJ IDEA
快捷键(Mac版)
- 删除当前行
command+backspace - 复制当前行
command+D - 补全代码
option+/ - 添加注释和取消注释
command+space+/ - 导入该行需要的类
option+enter - 快速格式化代码
option+command+L - 快速运行程序
control+shift+R - 生成构造器等
command+N - 查看一个类的层级关系
control+H - 自动的分配变量名
.var - 定位方法的类 将光标放在方法上
command+click - 模板/自定义模板 Live Templates
psvmsout
快捷键(Win版)
File -> Setting -> Keymap
- 显示所有快捷键
ctrl + J - 删除当前行
Ctrl + Y - 复制当前行
Ctrl + D - 补全代码
Alt + / - 添加、取消注释
Ctrl + / - 导入该行需要的类 先配置auto
import,然后使用
Alt + Enter - 快速格式化代码
Ctrl + Alt + L - 快速运行程序
Shift + F10 - 生成构造器等
Alt + Insert - 查看一个类的层级(继承)关系
Ctrl + H - 自动的分配变量名
.varAlt+Enter - 定位方法的类 将光标放在方法上
Ctrl + 鼠标左键 - 模板/自定义模板 Live
Templates
psvmsout - 移动当前行 Alt+Shift+↓
- 多行编辑 Alt+ 鼠标拖动
- 向后删除 Del
包
包的三大作用
- 区分相同名字的类
- 当类很多时,可以很好的管理类
- 控制访问范围
包的基本语法
package 包名; 包的本质
实际上就是创建不同的文件夹/目录来保存类文件
### 常用的包 * java.lang.*
// lang包是基本包,默认引入,不需要再引入 * java.util.* //
util包,系统提供的工具包,工具类,例如使用Scanner时需引入 *
java.net.* // 网络包,网络开发 * java.awt.* //
是做java的界面开发,GUI
访问修饰符
| 访问级别 | 访问控制修饰符 | 同一类 | 同一包 | 子类 | 不同包 |
|---|---|---|---|---|---|
| 公开 | public | √ | √ | √ | √ |
| 受保护 | protected | √ | √ | √ | × |
| 默认 | √ | √ | × | × | |
| 私有 | private | √ | × | × | × |
注意事项
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和public才能修饰类!并遵循上述访问权限的特点
- 成员方法的访问规则和属性完全一致
封装
封装介绍
封装(encapsulation)就是把抽象出的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作【方法】,才能对数据进行操作。
封装的理解和好处
- 隐藏实现细节:方法(连接数据库) <--- 调用(传入参数)
- 可以对数据进行验证,保证安全合理
封装的实现步骤(三步)
- 将属性进行私有化private 【不能直接修改属性】
- 提供一个公共的set方法,用于对属性判断并赋值
1
2
3
4public void setXxx(类型 参数名) { // Xxx表示某个属性
//加入数据验证的业务逻辑
属性 = 参数名;
} - 提供一个公共的get方法,用于获取属性的值
1
2
3public 数据类型 getXxx() { // 权限判断,Xxx的某个属性
return xx;
}
封装与构造器
构造器中调用set方法,实现数据验证逻辑
继承
当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。
### 继承的基本语法 1
2
3class 子类 extends 父类 {
}
继承的使用细节
- 子类继承了所有的属性和方法,但是私有属性不能在子类直接访问,要通过公共的方法去访问
- 子类必须调用父类的构造器,完成父类初始化
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用
super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过。 - 如果希望指定去调用父类的某个构造器,则显式的调用一下:
super(参数列表); super在使用时,必须放在构造器第一行super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器中- Java所有类都是Object类的子类
- 父类构造器的调用不限于直接父类!将一直往上追溯直到Object类
- 子类最多只能继承一个父类(指直接继承),Java中是单继承机制
- 不能滥用继承,子类和父类之间必须满足
is-a的逻辑关系
继承的内存布局

多态 Polymorphic
多态基本介绍
方法或者对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承的基础之上的。
多态的具体体现
- 方法的多态: 重写和重载体现多态
- 对象的多态:
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时就确定了,不能改变
- 运行类型时可以变化的
- 编译类型看定义时
=的左边,运行类型看=的右边1
2Animal animal = new Dog(); // animal编译类型是Animal,运行类型是Dog
animal = new Cat(); // animal的运行类型变成了Cat,编译类型仍然是Animal
- 使用多态机制,统一管理主人喂食问题
1
2
3public void feed(Animal animal, Food food) {
System.out.println(animal.getName() + " " + food.getName());
}
注意细节
- 多态的前提是:两个对象(类)存在继承关系
- 多态的向上转型
- 本质:父类引用指向子类对象
Object obj = new Cat(); - 特点:可以调用父类中的所有成员(需遵守访问权限),不能调用子类的特有成员,最终运行效果看子类的具体实现。
- 本质:父类引用指向子类对象
- 多态的向下转型
- 语法:
子类类型 引用名 = (子类类型) 父类引用;Cat cat = (Cat) animal; - 特点:只能强转父类的引用,不能强转父类的对象;要求父类的引用必须指向的是当前目标类型;可以调用子类类型中的所有成员
- 语法:
- 属性/成员变量没有重写之说!属性的值看编译类型
1
2
3
4
5
6
7
8
9
10
11
12Base base = new Sub();
System.out.println(base.count); // 10
Sub sub = new Sub();
System.out.println(sub.count); // 20
class Base {
int count = 10;
}
class Sub extends Base {
int count = 20;
} instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或xx类型的子类型- Java的动态绑定机制(重要)
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,那里使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31class A {
public int i = 10;
public int sum() {
return getI() + 10;
}
public int sum1() {
return i + 10;
}
public int getI() {
return i;
}
}
class B extends A {
public int i = 20;
// public int sum() {
// return i + 20;
// }
public int getI() {
return i;
}
// public int sum1() {
// return i + 10;
// }
}
// main方法中
// A是a的编译类型,B是a的运行类型
A a = new B(); // 向上转型
System.out.println(a.sum()); // 40 注释掉B的sum方法后---> 30
Systtem.out.println(a.sum1()); // 30 ---> 20
多态的应用
- 多态数组 数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
Person[] persons = new Person[5];persons[0] = new Student("jack", 18, 100);if(person[i] instanceOf Student) ((Student) person[i]).study(); - 多态参数 方法定义的形参类型为父类类型,实参类型允许为子类类型
Super
super代表父类的引用,用于访问父类的属性、方法、构造器 ### 基本语法 1.
访问父类的属性,但不能访问父类的private属性 super.属性名;
2. 访问父类的方法,不能访问父类的private方法
super.方法名(参数列表); 3.
访问父类的构造器,只能用在构造器的第一句,只能出现一句!
super(参数列表);
使用细节
- 调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类属性由子类初始化)
- 当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果!
- 如果多个基类(上级类)中都用同名的成员,使用super访问遵循就近原则。
super和this的比较
方法重写/覆盖 Override
方法重写就是子类有一个方法,和父类的某个方法的名字、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法
### 使用细节 1.
子类的方法的形参列表,方法名,要和父类方法的形参列表,方法名完全一致。
2. 子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类;比如
父类返回类型是Object,子类方法返回类型是String。 3.
子类方法不能缩小父类方法的访问权限。 void A() {}
public void A() {}
方法重写和重载的比较

Object类详解
equals()
==和equals的对比
==是一个比较运算符,既可以判断基本类型(值),又可以判断引用类型(地址)equals只能判断引用类型,默认判断的是地址是否相等,子类往往重写该方法,用于判断内容是否相等。
hashCode()
- 提高具有哈希结构的容器的效率!
- 两个引用,如果指向的是同一对象,则哈希值肯定一样
- 两个引用,如果指向的是不同的对象,则哈希值是不一样的
- 哈希值主要是根据地址号来的,不能完全将哈希值等价于地址
toString()
- 基本介绍 默认返回:全类名 + @ +
哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息。
1
2
3public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
} - 重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式。
- 当直接输出一个对象时,toString方法会被默认的调用。
finalize()
- 当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些
释放资源的操作; - 当某个对象没有任何引用时,则JVM就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象之前,会先调用finalize方法;
- 垃圾回收机制的调用,是由系统来决定的,也可以通过
System.gc()主动触发垃圾回收机制;
断点调试
Step over逐行运行Step into进入方法Step out运行完当前方法Resume运行到下一个断点