封装、继承、多态
封装
封装即数据的隐藏,通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
注意事项:
- 设计程序追求“高内聚,低耦合”。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
- 属性私有(private),get/set
封装的用处:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统的可维护性增加
数据类的封装
package com.oop.demo04;
//封装get、set
public class Student {
private String name;//private 私有属性
private int id;
private int age;//alt+fn+insert 调用get、set方法快捷键
private char sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>120 || age<0){
this.age = 3;
}else{
this.age = age;
}
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
调用数据类的方法(即封装的类)
package com.oop;
//一个项目只存在一个main方法
import com.oop.demo04.Student;
public class Application {
public static void main(String[] args) {
//new 实例化的对象
Student s1 = new Student();//新建对象s1
s1.setName("西饼");
System.out.println(s1.getName());
s1.setAge(121);
System.out.println(s1.getAge());
s1.setId(2020214394);
System.out.println(s1.getId());
s1.setSex('m');
System.out.println(s1.getSex());
}
}
继承
继承的本质是对某一批类的抽象
注意事项:
- Java中类只有单继承,没有多继承
- 继承关系中的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
super
注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或构造方法中
- super和this不能同时调用构造方法
Vs this:
代表的对象不同
this:本身调用的这个对象
super:代表父类对象的应用
前提
this:没有继承也可以使用
super:只能在继承条件才可以使用
构造方法
this();本类的构造
super();父类的构造
方法重写
重写需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同,否则与重载一样(注意区分
- 修饰符:范围可以扩大,但不能缩小 public>protected>default>private
- 抛出的异常:范围可以缩小,但不能扩大 ClassNotFoundException<Exception
重写,子类和父类的方法必须一致,方法体不同!
为什么要重写?
-
父类的功能,子类不一定需要,或者不一定满足
快捷键:Alt+FN+Insert ;override
以下情况不能够被重写:
- static方法,属于类,不属于实例
- final常量
- private方法
Application类:
package com.oop;
//一个项目只存在一个main方法
import com.oop.demo05.A;
import com.oop.demo05.B;
public class Application {
//静态方法和非静态方法有区别,重写只和非静态有关!
public static void main(String[] args) {
//静态方法:方法的调用只和左边定义的数据类型有关
A a = new A();
a.test();//A
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();//A
}
}
A类:
package com.oop.demo05;
//A类继承B类,A是子类,B是父类
public class A extends B {
@Override//重写,有功能的注释!
/*去掉static后,Crtl+FN+Insert后点击
Override Methods自动生成*/
public void test() {
System.out.println("A->test");
}
}
B类:
package com.oop.demo05;
//重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B=>test()");
}
}
多态
多态即同一个方法可以根据发送对象的不同而采用多种不同的行为方式
注意事项:
-
方法的多态,属性无多态
-
父类的子类有联系,类型转换异常 ClassCastException
-
存在条件:
-
继承关系
-
方法需要重写;父没有的方法,自动执行子类的
-
父类的引用指向子类对象 Father f1 = new son();
Application类:
package com.oop; //一个项目只存在一个main方法 import com.oop.demo06.Person; import com.oop.demo06.Student; public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //new Student(); //new Person(); //可以指向的应用类型就不确定了,父类的引用可以指向子类 //Student 能调用的方法是自己或父类的 Student s1 = new Student(); //Person父类型可以指向子类,但不嫩调用子类独有的方法 Person s2 = new Student(); Object s3 = new Student(); //对象能执行什么方法,主要看对象左边的类型 s2.run();//子类重写了父类的方法,执行子类的方法 s1.eat(); s1.run(); ((Student)s2).eat();//(强制转换)子类重写了父类的方法,执行子类的方法 } }
-
Person 类:
package com.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
Student类:
package com.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
instanceof
用于判断两个对象之间有无父子关系,有返回ture,否则返回false
System.out.println(x instanceof y);//用于判断x和y之间是否存在父子关系,若存在则能编译通过;反之,则不能
类型转换:
注意事项:
- 父类引用指向子类的对象
- 子类转换为父类,向上转型
- 父类转换为子类,向下转型(强制转换)
- 方便方法的调用,减少重复的代码。