核心内容:属性私有、get/set
1、封装的概念(数据的隐藏)通常,应该禁止(用户)直接访问对象中的数据的实际表示,而应该通过接口操作来访问,这就称为信息隐藏/封装。
- 该漏的漏,该藏的藏
- 高内聚,低耦合
- 高内聚:类的内部数据的操作细节是自己完成的,不允许外部干涉
- 低耦合,仅暴露少量的方法给外部使用
- 属性私有:修饰符private,
- private作用:个人理解,将该属性私有化,无法被外部类调用
- get/set:对应获取数据和修改数据的方法
- 快捷键:alt+insert,可以快速生成get和set方法
- 作用:比如可以在方法内加入纠错机制(安全性验证)
3、封装的意义
- 提高程序的安全性,可以保护数据
- 隐藏代码的实现细节(高聚合)
- 统一接口,形成规范(低耦合)
- 增加系统的可维护性:便于修改内部代码
二、继承 1、概念 (1)继承
- 继承,顾名思义,就是在现有类的基础上,构建新类,以满足新的要求。(可以理解为一种“拓展”)
- 新的类继承原来的方法和实例变量,并能添加自己的方法和实例变量
- 继承是类和类之间的一种关系,除此之外还有依赖、组合、聚合等关系
继承的特质和现实生活中的父子很像
- 所以现有类称为【父类 或 超类 或基类】,而派生类被称为【子类】。
- 子类会继承父类的属性和方法,但是前提是父类公开权限
- 比如父类里private修饰的私有属性就就无法继承
- Java类中只有单继承:一个类只能有一个父类
- 语法:class A extends B{...}
- 其中B就是父类,A就是子类,读作A继承B
- 两个作用:
- 在子类中调用父类的构造函数
- 在子类中调用父类的方法
-
super要调用父类构造函数,必须是构造函数主体的第一句。且只能出现一次。
-
this也是同样的用法(写在第一句。且只能出现一次),所以super和this是无法同时调用构造方法的。
-
如果父类的属性或者方法 权限定义为private,则无法用super调用。
-
-
当我们创建子类对象时,子类对象会自动调用父类的构造函数。
-
那么应该如何调用父类的有参构造?
想要调用父类的有参构造函数,要使用super关键字。
-
-
注意:当父类没有无参构造时,子类也无法定义无参构造。
-
代表的对象不同
super代表父类对象的应用,this代表调用本身这个对象
-
前提不同
super必须要在继承条件下才可以用,this没有继承也能用
-
构造方法不同
this(); 本类的构造; super(); 父类的构造
- 可以查看继承树:查看不同类之间的继承关系
所有的类都直接或间接地 继承object类
默认继承,不需要特意写
- Object类涉及到Java的低层原理
- 里面有很多熟悉的方法 :equals、toString等等
重写都是方法的重写,属性不能重写
- 概念:需要有继承关系,子类重写父类的方法!
- 父类的引用指向了子类 (怎么理解?
- 可以这么声明父类 对象名 = new 子类
- IDEA快捷键:alt+insert 可以快速重写方法
- @override 这是重写方法的注解(有功能的注解),可选的
-
静态方法 :方法的调用只和 左边定义的变量类型 有关()
- 个人理解,在声明一个父类 对象时,可以指向自己,也可以指向他的子类,但是调用的方法只跟声明的类型有关。
- 最终的效果就是,静态方法无法重载
- 个人理解,在声明一个父类 对象时,可以指向自己,也可以指向他的子类,但是调用的方法只跟声明的类型有关。
-
非静态方法:方法的调用只和 右边指向的变量类型 有关
- **子类可以重写父类的非静态方法,所以方法重写只和非静态方法有关 **
- 修饰符:范围可以扩大。但不能缩小
- 重写是否成功可以看对应的图标判断
- **子类可以重写父类的非静态方法,所以方法重写只和非静态方法有关 **
-
使用场景不同
方法重写必须在继承时才能用,而重载是在一个类里实现的
-
使用方法不同
方法重写必须是同名同参的方法名才能重写
方法重载则是同名但是参数列表不同的方法才能重载
## 方法重写小结父类的功能,子类不一定需要,或不一定满足
- 方法名必须相同
- 参数列表也必须相同
- 修饰符:(不能比被重写方法)更强、范围可以扩大、但不能缩小 (public > protected > default > private)
- 抛出的异常,范围可以被缩小,但不能被扩大;
简单一句话:重写要求:子类和父类的方法必须要一致,方法体不同!
三、多态 1、概念和作用
- 概念:同一个方法,可以根据发送对象的不同,而采用不同的行为方式(方法)
一个对象的实际类型是确定的,但是可以指向对象的引用类型有很多
举例说明
// 比如,有一个Student类继承Person类 new Student(); new Person(); // new某一个类,这个类型就一定是某一个类 // 所以 一个对象的实际类型的确定的 // 但是 可以指向的引用类型是不确定的 Student s1 = new Student(); Person s2 = new Student(); Object s3 = new Student(); // 子类可以指向父类这就 是 父类的引用 指向 子类的类型
- 作用:可以实现动态编译
- 动态编译:程序的类型,只有在执行的最终状态才能确认,写代码时是没办法确定的
- 在大型系统里,可以实现 ——可拓展性
- 多态 可以使 可拓展性更强 (写的时候不用关心程序是什么状态
举例说明:还是接刚才的举例,现在Person类里有一个方法叫run();
// 尝试用s2来运行父类Person类的run 方法 s2.run(); // 测试可行
- 接下来 在子类Student里重写run()方法
// 调用s1 s2的run 方法 s1.run(); s2.run(); // 结果:两个都执行了子类的方法(也就是重写后的方法)
- 结论一:子类的对象指向父类时,可以调用父类的方法。
- 结论二:当子类重写了父类的方法后,无论子类的对象指向谁,都会调用子类的方法。
继续举例:尝试调用子类独有的方法eat();
s1.eat(); // 正常执行 //s2.eat(); // 报错
- 如果需要调用子类独有的方法,就需要进行类型转换,格式举例如下
((Student) s2).eat(); //类似基本类型的强制转换,格式上需要注意外面加个小括号。
- 结论三:子类的对象指向父类时,无法调用子类独有的方法
- 结论四:对象能执行哪些方法,主要看对象左边的引用类型,和右边的实际类型关系不大
- 结论五:子类能执行的方法,都是自己的(包括继承父类的方法);父类虽然可以指向子类,但不能调用子类独有的方法。
( 所以说,JAVA里面的方法调用,是在运行时刻动态对象绑定的 )
3、多态的使用条件注意事项:多态是方法的多态,属性没有多态
三个使用条件:(其实总结一句话就是父类的引用要指向子类的对象。)
- 必须是继承关系的父子类才有多态( 报错: 类型转换异常 ClassCastException )
- 方法必须要重写的方法。否则都是调用各自的方法
- 反之,要学会如何判断在继承关系时,是执行哪个类里的方法
- 回顾知识点:哪些方法不能被重写? ——1、static (静态方法 属于类,不属于实例);2、final (常量);3、private方法(私有的 方法也不能重写)
- 父类的引用要指向子类的对象。
-
语法类似基本类型的强制转换
-
回顾以前的基本类型转换知识点有提到一个优先级的高低关系,在引用类型里,父类子类也是一种高低关系
- 低 —— —— —— — —> 高
- char/byte/short - int - long -float - double
- 子类 (低)——父类(高)— — Object类
- 基本类型 :低转高=自动转换;高转低=强制转换
- 引用类型:子类可以指向父类的引用类型;父类要调用子类独有的方法,则必须类型转换
-
类似数据类型的强制转换,引用类型的强制转换也会丢失方法
5、instanceof 关键字
- 作用:很简单,判断一个对象是什么类型?
# instanceof 的结论
举例说明:编写一个Student类继承Person类,再编写一个Teacher类继承Person类
// 尝试判断输出的结果 Object object = new Student(); // 声明一个Student类的对象指向Object类 System.out.println(object instanceof Student); // True System.out.println(object instanceof Person); // True System.out.println(object instanceof Object); // True System.out.println(object instanceof String); // Flase System.out.println(object instanceof Teacher); // Flase
- 可以看出来, instanceof可以判断是否是相似的类型,以便于后续进行类型转换
继续举例,
Person person = new Student(); // 声明一个Student类的对象指向Person类 System.out.println(person instanceof Student); // True System.out.println(person instanceof Person); // True System.out.println(person instanceof Object); // True //System.out.println(person instanceof String); //编译报错 System.out.println(person instanceof Teacher); // Flase Student student = new Student(); System.out.println(student instanceof Student); // True System.out.println(student instanceof Person); // True System.out.println(student instanceof Object); // True //System.out.println(student instanceof String); //编译报错 //System.out.println(student instanceof Teacher); //编译报错
- person instanceof String 直接编译报错,说明不想关的类型,instanceof是直接报错无法执行的
用法 X instanceof Y,返回值为布尔值
- 能否编译通过 取决于是否X的引用类型和Y存在关系 ,有则通过,无则报错(X的左边和Y有没有关系
- 输出的结果,取决于X的实际类型和Y是否存在直接父子关系,有则为true,没有为false (X的右边和Y有没有关系
6、多态小结
- 编译通过输出false 和编译报错 有什么不同?
- 编译报错意味着X和Y就不存在任何关系(比如X和Y都继承A,就会报错)
- false意味着,虽然X指向的引用类型虽然和Y有继承关系,但是X的实际类型跟Y并没有直接关系
- 多态的使用条件:父类的引用指向子类的对象
- 继承+方法重写
- 类型转换:
- 子类转型为父类:向上转型 (可以直接转换
- 父类转型成子类:向下转型(强制转换)
- 多态的作用:方便方法的调用,使代码更加简洁
后续还有 抽象类 和 接口 更加抽象的内容
核心理念就是:抽象的编程思想



