- 继承
- 重写Override
- 抽象方法
- 接口
- 默认方法
- 静态方法
- 私有方法
- 常量的使用
- 多态
一、面向对象的三大特征:封装性 继承性 多态性
二、继承是多态的前提 没有继承就没有多态
三、继承主要解决的问题是共性抽取
四、继承可以理解为 师傅会多少武功 大徒弟也都会 小徒弟也都会 大徒弟小徒弟都继承了师傅的武功
五、我们把师傅称谓父类 基类 超类 两个徒弟称为子类 派生类
六、继承关系中的特点:
- 子类可以拥有父类的“内容”
- 子类还可以拥有自己专有的内容
七、在继承关系中 “子类就是一个父类” 也就是说 子类可以被当做父类看待,例如:父类是员工 子类是讲师 那么“讲师就是一个员工” 关系是:子类 is a 父类
八、定义父类的格式:(一个普通的类定义):
public class 父类名称{
//……
}
九、定义子类的格式:
public class 子类名称 extends 父类名称{
//……
}
十、一个父类都不知道自己有多少儿子 不知道自己儿子是谁 也不知道自己儿子在哪里 只有子类才知道自己的父亲是谁
十一、java语言是单继承的 一个类的直接父类只能有唯一一个 一个类只能继承一个类 不能继承多个类 一个儿子只能有一个亲生父亲
十二、java语言可以多级继承 我有一个父亲 我的父亲还有一个父亲 也就是爷爷
十三、object类没有父类
十四、一个子类的直接父亲是唯一的 但是一个父类可以拥有很多个子类 也就是说可以有很多个兄弟姐妹
十五、继承关系中 父子类构造方法的访问特点:
- 子类构造方法中有一个默认隐含的super()调用 所以一定是先调用父类构造
- 子类构造可以通过super关键字来调用父类重载构造
public class Fu2 {
public Fu2(int Number) {
System.out.println("父类构造方法!");
}
}
public Zi2() {
// 因为系统默认赠送的是没有参数的super();
// 如果父类是含有参数的构造方法 那么系统就会报错
// 此时需要自己手动添加一个含参的super
super(10);
System.out.println("子类构造方法!");
}
- super的父类构造调用 必须是子类构造方法的第一个语句 不能一个子类构造调用多次super构造 即 一个子类构造只能有一个super语句
public class Fu2 {
public Fu2() {
System.out.println("父类构造方法!");
}
public Fu2(int Number) {
System.out.println("父类构造方法! " + Number);
}
}
//若子类构造方法用super()
public class Zi2 extends Fu2{
public Zi2() {
System.out.println("子类构造方法!");
}
}
打印输出:
父类构造方法!
子类构造方法!
//若子类构造方法用super(10)
public class Zi2 extends Fu2{
public Zi2() {
super(10);
System.out.println("子类构造方法!");
}
打印输出:
父类构造方法!10
子类构造方法!
十六、【总结】:子类必须调用父类构造方法 不写则赠送super();,写了则用写的指定的super调用 super只能有一个 还必须是第一个
十七、super关键字的用法有三种:
- 在子类的成员方法中 访问父类的成员变量
- 在子类的成员方法中 访问父类的成员方法(Zi2)
- 在子类的构造方法中 访问父类的构造方法(Zi2)
十八、this关键字的用法有三种:
- 在本类的成员方法中 访问本类的成员变量
- 在本类的成员方法中 访问本类的另一个成员方法(Zi2)
- 在本类的构造方法中 访问本类的另一个构造方法(Fu2)
十九、【注】:
- this(……)调用也必须是构造方法的第一个语句
- super和this两种构造调用不能同时使用 在构造方法的开头第一个语句写了this(……)语句 那么默认的super()将会消失
public class Constructor {
public static void main(String[] args) {
Zi2 zi2 = new Zi2();
}
}
二十、在父子类的继承关系当中 如果成员变量重名 则创建子类对象时 访问有两种方式:
- 直接通过子类对象访问成员变量:(子类对象.成员变量)等号左边是谁 就优先用谁 没有则向上找
- 间接通过成员方法访问成员变量:该方法属于谁(该类定义在哪儿)就优先用谁 没有则向上找
二十一、在父子类的继承关系当中 如果局部变量 父类的成员变量 本类的成员变量重名 该怎么办: - 局部变量:直接写成员变量名
- 本类的成员变量名:this.成员变量名
- 父类的成员变量:super.成员变量名
二十二、在父子类的继承关系当中 如果父类的方法和子类的重名了 创建子类对象 访问成员方法的规则:创建的对象是谁 就优先用谁 如果没有则向上找
【注】:无论是成员方法还是成员变量 如果没有都是向上找父类 绝对不会向下找子类
import javax.sound.midi.Soundbank;
public class Inherit2 {
public static void main(String[] args) {
Fu fu = new Fu();
System.out.println(fu.numFu);//只能使用父类的东西 没有任何子类内容 10
Zi zi = new Zi();//等号左边是Zi 优先用子类的
System.out.println(zi.numFu);//10 优先用子类 子类没有 向上找 找到父类中有 用父类的
System.out.println(zi.numZi);//20
System.out.println("父子类成员变量重名:===================");
//直接通过子类对象访问成员变量:(子类对象.成员变量)等号左边是谁 就优先用谁 没有则向上找
System.out.println(zi.num);//优先子类 200
//System.out.println(zi.abc);//优先用子类 子类没有 向上找 发现父类也没有 编译报错
System.out.println("间接方法:======================================");
zi.methodZi();//这个方法是子类的 优先用子类的 没有再向上找 200
zi.methodFu();//这个方法是在父类当中定义的 100
System.out.println("局部变量 父子类成员变量重名:=====================================");
zi.method();
System.out.println("子类父类方法重名:====================================");
zi.name();//创建的是new了子类对象 所以优先用子类方法
}
}
重写Override
一、重写(Override):在继承关系中 方法的名称一样 参数列表也一样 也称覆盖 覆写
二、重写(Override)和重载(Overload)的区别:
- 重写(Override):在继承关系中 方法的名称一样 参数列表也一样
- 重写(Override):方法的名称一样 参数列表不一样
三、重写的特点:创建的是子类对象 就优先用子类方法 new的是谁就优先用谁
四、注意事项:
- 必须保证父子类之间方法的名称相同 参数列表也相同
- @Override:写在覆盖重写的方法前面 用来检测是不是有效的正确覆盖重写 可写可不写 建议写上
- 子类方法的返回值必须小于等于父类方法的返回值范围
- java.lang.Object类是所有类的公共最高父类(祖宗类) java.lang.String是Object的子类
- 子类方法的权限修饰符必须大于等于父类方法的权限修饰符:public > protected > (default) > private,其中,(default)不是关键字default 而是什么都不写 留空
}使用:
public class InterfaceClass { public static void main(String[] args) { MyInterfacePrivateB.methodStatic2(); } }常量的使用一、接口当中也可以定义成员变量 但是必须使用public,static,final三个关键字进行修饰 从效果上来看 这其实就是接口的常量
二、格式:public static final 数据类型 常量名称 = 数据值;- public:谁都可以用
- static:写上之后意味着跟对象没关系了
- final:不可变
【注】: - 接口当中的常量可以选择性省略public,static,final,但是 不写也是这样的
- 接口当中的常量必须进行赋值 不能不赋值 因为成员变量有默认值 如果不赋值 默认值一旦放进来就不能变了
- 不能变的常量的名字要全部大写 如果包含多个单词 用_隔开
public class MyInterfaceConst { //这其实就是一个常量 一旦赋值 不可修改 public static final int NUM_OF_CLASS = 10; }三、如何使用:接口名称.常量名称
public class InterfaceClass { public static void main(String[] args) { System.out.println(MyInterfaceConst.NUM_OF_CLASS);//10 } }多态一、面向对象三大特征:封装性 继承性 多态性
二、extends继承或者implements实现 是多态性的前提
三、假设父类是人类 子类是学生类和员工类 小明是一个学生 但同时也是一个人,小明是一个对象 这个对象既有学生形态 也有人类形态 一个对象拥有多种形态 这就是对象的多态性
四、代码当中体现多态性 其实就是一句话 父类引用指向子类对象
五、格式:父类名称 对象名 = new 子类名称();
或者:接口名称 对象名 = new 实现类名称();
六、访问成员变量的两种方式:- 直接通过对象名称访问:看等号左边是谁 优先用谁 没有则向上找 不能往下找
- 间接通过成员方法访问:该方法属于谁优先用谁 没有则向上找
七、只有成员方法才能覆盖重写 方法不能覆盖重写
八、访问成员方法的规则:看new的是谁 就优先用谁 没有则向上找【注】:
- 成员方法:编译看左 运行看右
- 成员变量:编译看左边 运行还看左边
public class Fu2 { int num = 10; public void method() {System.out.println("父类方法!");} public void methodFu() {System.out.println("父类特有方法!");} public void showNum() {System.out.println(num);} } public class Zi2 extends Fu2{ int num = 20; int age = 16; @Override public void method() {System.out.println("子类方法!");} @Override public void showNum() {System.out.println(num);} public void methodZi() {System.out.println("子类特有方法!");} } public class Polymorphism { public static void main(String[] args) { //使用多态的写法 左侧父类的引用指向了右侧子类的对象 Fu2 objFu2 = new Zi2(); System.out.println("访问成员方法:=================================="); objFu2.method();//子类方法! 成员方法看右边new的是谁就用谁 objFu2.methodFu();//父类特有方法!子类没有则向上找 objFu2.showNum();//子类没有覆盖重写 就是父:10 子类覆盖重写了 就是子:20 System.out.println("访问成员变量:=================================="); System.out.println(objFu2.num);//父:10 //System.out.println(objFu2.age);错误!优先使用父类 父类没有age 不会往下找 而会去object类中找 } }九、对象的向上转型 其实就是多态写法
十、格式: 父类名称 对象名 = new 子类名称();
含义:右侧创建一个子类对象 把他当做父类来看待
假设父类为Animal类 子类为Cat类 则按格式写为:Animal animal = new Cat();创建了一只猫 当做动物看待【注】:向上转型一定是安全的 从小范围的猫转向了大范围的动物
十一、向上转型的弊端:对象一旦向上转型为父类 就被当做父类来看 那么就无法调用子类原本特有的内容
十二、为解决向上转型的弊端 可以将对象向下转型【还原】
十三、对象的向下转型其实就是一个【还原】动作
格式:子类名称 对象名 = (子类名称)父类对象
含义:将父类对象还原为本来的子类对象Animal animal = new Animal();//本来是猫 向上转型成为动物 Cat cat = new cat();//本来是猫 已经被当做动物了 还原回来成为本来的猫
【注】:
- 必须保证对象本来创建的时候就是猫 才能向下转型成为猫
- 如果对象创建时本来不是猫 现在非要向下转型成为猫 就会报错:ClassCastException
public class Polymorphism { public static void main(String[] args) { System.out.println("向上转型:===================================="); //对象的向上转型就是父类引用指向子类对象 Animal animal = new Cat();//本来创建时是一只猫 animal.eat(); //animal.catchMouse();错误!对象一旦向上转型为父类 那么就无法调用子类原本特有的内容 System.out.println("向下转型:===================================="); //向下转型 进行还原 Cat cat = (Cat) animal; cat.catchMouse(); } }



