面向对象
面向对象 - OOP
1、类和对象
概述: 类是构造对象的模板或蓝图;- 模具
1、封装
封装 - 将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现方式;
对象中的数据 称为实例字段,操作数据的过程 称为方法;
实现封装的关键,绝对不能让类中的方法直接访问其他类的实例字段; - private (属性私有化)
封装后,需要使用访问器get方法访获得实例字段值;使用更改器set方法设置实例字段;
2、超类 - Object
所有的类都源于超类 Object
3、类的关系
-
依赖
- 如果一个类的方法使用或操作另外一个类的对象,我们就说一个类依赖于另外一个类
-
聚合
- 例如一个类对象包含一些其他类对象,这就意味着类A的对象包含类B的对象;
- 例如类A 对象里面有一个属性是类B的对象;
-
继承
- A类继承了B类,A类 就扩展了B类,A类不但有了从B类中继承的方法,还会有一些额外的功能;
4、对象是类的实现(类是对象的模板)
- 创建对象的几种方法:
- new 一个对象 - 调用构造函数
- 通过反射得到一个对象 - 调用构造函数
- 反序列化一个对象 - 没调用构造函数
- clone 一个对象 - 没调用构造函数
5、对象的内存分析
(基础内存分析)
2、构造器 - (构造函数)
构造器是一种特殊的方法,用来构造并初始化对象;
构造器快捷键:alt+insert --> 生成构造器
/*
* 构造器的作用:
* 1、new 的本质就是调用构造方法
* 2、初始化对象的值
* 构造器:(实际上就是一个没有返回值的方法)
* 1、和类名相同
* 2、没有返回值
* */
public class Constructor01 {
String name;
int age;
// 无参构造器
public Constructor01() {
}
// 有参构造器
public Constructor01(String name, int age) {
this.name = name;
this.age = age;
}
}
1、构造器必须要和类同名
-
类中一般默认有一个空参构造器;
-
如果在类中设置有参构造器,最好也设置一个无参构造器;
-
每个类可以有一个以上的构造器;
2、构造器需要结合 new 运算符来调用
- 不能对已经存在的对象调用构造器来达到重新设置实例字段的目的;
3、构造器没有返回值
4、对象需要通过 new +构造器 实例出来;
- jvm栈 中存放对象的引用,堆中存放具体的对象
5、this 和 super
- this 关键词 指代当前对象
- super 关键词 指代父类对象
3、修饰符
-
public - 公共
- 标记public 的部分可以由任意类使用;
-
protected - 受保护(子类可以调用,对其他类隐藏)
-
default - 默认的
-
private - 私有
- 标记private 的部分只能由定义他们的类使用;
-
static - 静态
- 静态字段(属性)- 类字段 每个类的对象都可以访问这个属性,静态字段属于类,不属于任何单个对象
- 静态常量 - 每个类的对象都可以修改公共字段,所有最好不要有公共字段;但是静态常量不同,因为被fina 修饰,不允许在将他重新赋值;
- 静态方法 - 静态方法不是在实例对象上执行的,所以静态方法不能访问实例字段,但是静态方法可以访问静态字段,静态方法可以直接通过类名调用;
- 静态方法常见的用法:工厂方法;
-
fina - 常量
- fina 修饰的类,不能被继承(就不允许被扩展),该类下所有的方法都会变成fina 方法
- fina 修饰的方法,不能被子类继承,子类只能继承其他没被fina 修饰的方法
-
abstract - 抽象
4、包
-
使用包的主要原因是为了确保类名的唯一性
例如:com.ze.corejava.Employee
-
类的导入
一个类可以使用所属包中的所有类,以及其他包中的公共类
两种方式访问其他包的公共类:
-
使用完全限定名 - (一般不实用,太繁琐)
java.time.LocalDate today = java.time.LocalDate.now(); -
在当前类,使用import 语句导入一个特定的类或者整个包:
import java.time.*; LocalDate today = LocalDate.now();
-
-
静态导入
在类上import static 可以导入静态方法和静态字段,而不只是类
这样就可以直接使用这些导入静态类的方法,而不必加上类的前缀
另外还可以直接导入特定的字段或方法(不建议 - 这样代码可读性会非常差)
-
包中增加类 - 直接在类的源文件开头写上 package+包的全限定名
package com.ze.corejava; -
没有指定public 和private 部分(类、方法或变量)可以被同一包中的所有方法访问;
5、jar 包
jar文件 - java归档(jar)文件:
-
一个jar 文件既可以包含类文件(应用程序、代码库),也可以包含诸如图像、声音等其他类型的文件;
-
jar文件是压缩的,它使用的是我们非常熟悉的zip压缩格式;
-
除了类文件、资源文件 外,每个jar文件都还包含一个清单文件,用来描述归档文件的特殊特性;
6、封装
- 属性私有,实例字段前加上 private关键子 ---> 提高代码的安全性,保护数据
- 利用方法获取对应的实例属性 数据 ;
7、继承
- 使用关键字 extends 表明 继承某个父类; -- 子类相当于父类的扩展
- 子类可以重写父类的方法,因此完成对父类的扩展;
- 被继承类称为父类,继承类称为子类,子类拥有父类所有字段属性和方法;
- 子类在new 的过程中会先调用父类的构造方法,然后在进行子类的实例化;
- 只能在继承层次内进行强制转换 - 父类转换成子类,需要进行强制转换;
- 父类的私有属性子类不能继承,但是可通过继承父类的公共方法,通过父类方法获取父类的私有属性;
- 父类的私有方法子类也不能继承,也只能通过父类的其他公共方法进行调用;
-
继承是类和类之间的关系;
-
一个子类只能继承一个父类,一个父类可以有多个子类(一个儿子只能有一个爸爸,一个爸爸可以有多个儿子);
-
类和类之间的其他关系;
- 依赖
- 聚合
- 组合
-
方法的重写
-
子类中方法名与父类方法名必须相同
-
子类方法中的参数列表与父类的相同
-
子类方法的修饰符范围 可以扩大,不能缩小;(例如 private --> public )
-
子类方法抛出异常的范围 可以缩小,不能扩大;(类似子类不能 “欠债” 比父类多)(ClassNotFoundException(小) --> Exception(大))
-
方法的重写是发生在子类继承父类中;方法的重载时发生在同一类中;
-
8、多态
-
instanceof 关键字 - 判断一个对象是什么类型
public class Demo01 { public static void main(String[] args) { Person person = new Person(); Student student = new Student(); //判断 person 是否是Student 的实例? System.out.println(person instanceof Student);//false //判断 student 是否是Person 的实例? System.out.println(student instanceof Person);//true } } -
多态是提升程序的扩展性;
-
理解:同一个人在不同环境下表现出不同的状态
-
本质:父类或者接口的引用,指向自己的子类对象
-
多态的前提:
- 必须有继承关系
- 方法必须重写
- 父类指向自己的子类
-
注意:
- 多态中,子类重写了父类的方法,所以父类这个方法运行的是子类的重写方法;(父类可以调用子类重写的方法,但是子类独有的方法,父类是不能进行调用的)
- 静态的方法与对象无关,所以运行的是对应的类型的静态方法;(静态没有多态)
- 多态是方法的多态,属性不是多态;(变量、常量没有多态)
-
内存分析图:
9、抽象类
抽象关键字 abstract
-
包含一个或多个抽象方法的类,必须被声明为抽象;
- 抽象方法 - 相当于定义了一个方法,但是没有具体的实现,交给子类进行实现 和 接口中的方法类似;
- 抽象方法充当占位方法的角色
-
抽象类中还可以包含字段和具体的方法;
-
即使不含有抽象方法也可以把类声明为抽象类
- 抽象类不能被实例化(不能被new ,但是存在构造器 - 类都有构造器)
理解:
-
抽象类 相当于可以继承的接口,可以有实例字段(属性)和普通方法
-
抽象类相当是利用多态特性的一种实现,而接口就是更进一步的约束;
-
抽象类只能单继承(类只能单继承),接口可以多实现(多继承);
普通类 - > 抽象类 - > 接口
10、接口 - interface
1、接口概述
-
接口可以看成是抽象的规范;
-
一个类可以实现一个或多个接口;
-
接口可以被接口继承;
-
接口必须要被实现,不然接口没有意义;实现接口的类,必须重写(实现)接口的全部方法;
-
接口中的所有方法都是自动public 的,所以可以省略关键字public;
2、接口中的属性
-
接口中一般不会有属性,如果有属性,必须是一个公开静态常量;
接口的属性是可以被继承的,但是不能被改变;(一般不推荐接口定义属性)
理解:接口就像是个标准结合,里面定义的方法标准
public interface Test01 { String AOU_TT = "abc"; // public static final 可以省略,会自动添加 public static final int a = 6; }
3、接口和抽象类的区别
- 每个类只能由继承一个父类(类单继承),每个类可以实现多个接口(接口多实现);
4、接口与静态方法和私有方法
- 理论上是接口中是可以使用静态方法的,但是违反了将接口作为抽象类的规范初衷,所以一般把接口的静态方法放在伴随的类中
- 很多标准库中可以看到接口和实用工具类成对出现;
- 接口中是可以定义私有方法的,但是它们的作用很有限,只能作为接口中其他方法的辅助方法;
5、接口中方法默认实现 - 关键字default
-
接口中方法可以默认实现 - 必须要用 default 关键字修饰
- 但是这个一般并没有什么用,因为你的实现类会重写这个方法;
-
一些特殊情况下,这个默认方法可能有用
- 默认方法的一个重要用法:“接口演化”
-
默认方法冲突:
- 1、父类优先
- 如果一个类继承了一个父类,也实现了一个接口,如果父类中的方法,参数都和接口中默认方法一模一样,那么子类只会考虑父类的方法,接口中一样的默认方法都会被忽略 - 类优先原则
- 2、接口冲突
- 如果一个类实现两个接口,两个接口中有一模一样的默认方法,java编译器会报错,然后要程序员自己解决这个二义性问题;- 在子类中写一个方法,这个方法功能就是选择一个冲突方法;
- 1、父类优先
6、回调
11、lambda 表达式
lambda 表达式是一个可传递的代码块,可以在以后执行一次或多次;
(参数)->{具体实现内容(方法内容/逻辑内容}
(String a,String b)->{
if(a.length() < b.length()) return -1;
else if(a.length() > b.length()) return 1;
else return 0;
}
1、lambda 表达式的简化
-
如果可以推倒出一个lambda 表达式的参数类型,则可以忽略不写
-
如果方法只有一个参数,而且这个参数类型可以推导,还可以省略小括号
-
无需指定lambda表达式的返回类型,lambda表达式的返回类型总是会由上下文推导得到
(String a,String b)->a.length()-b.length()
2、lambda 表达式 - 函数式接口的对象
函数式接口 :就是只有一个抽象方法的接口;
函数式接口对象:可以使用lambda 表达式表示;
12、内部类
内部类:定义在另外一个类中的类;
使用内部类的两个原因:
- 内部类可以对同一个包中的其他类隐藏;
- 内部类方法可以访问定义这个类的作用域中的数据,包括原本的私有数据;
1、普通内部类
-
内部类可以访问自身字段,也可以访问创建它的外围对象的数据字段;
-
内部类两种:一个java文件中只能由一个同级 public class类,但是可以有多个class类
- 第一种:
public class A { private int id = 1; public class B{ // 内部类,不同级的public可以有多个 public void in(){ System.out.println("这是内部类的方法"); } } }- 第二种:
public class A{ } class B{// 第一级的public class 只能有一个 } class C{ } -
如果只需要类的对象,并不需要这个对象名字
public class A{ }
2、局部内部类(方法内部类)
- 方法内部类的作用域被限定在声明这个局部类的快中;
- 优势:
- 对外部世界完全隐藏,这个方法外的其他代码方法都无法访问;
- 可以访问外部类的所有字段,还可以访问局部变量;
3、匿名内部类
-
只需要类的对象,并不需要类的名字可以使用匿名内部类
public class Demo01 { public static void main(String[] args) { new A().test();// 匿名内部类,不需要把实例对象保存到变量,直接使用这个对象的方法 // 后期可以简写成 lamb 表达式 new B() { // 匿名接口实现高阶使用,直接使用接口的实现,并现场重写方法,然后使用方法 @Override public void hello() { System.out.println("方法实现"); } }.hello(); } } class A{ public void test(){ System.out.println("test"); } } interface B{ public void hello(); }
4、静态内部类
- 普通内部类,加上static 关键字,就是静态内部类;
- 静态内部类不能直接访问外围的非静态属性;

浙公网安备 33010602011771号