继承关系存在的安全隐患,引出abstract
1.父类是多个子类抽取的共性内容,希望这个父类不可以被实例化对象【没有叫动物的动物】
2.父类中抽取多个子类相同且需要重写的方法,希望在父类声明这个方法的时候
省略方法体。public void eat();
3.程序员重写父类的方法的时,偶尔会忘记重写某一个类的方法,但不提示。希望代码编译报错
抽象类:
抽象类:被abstract修饰的类,称为加强版的父类。
1.被abstract修饰的类不可以被实例化对象。
2.抽象类中可以含有构造器,构造器的作用不再是创建对象时使用,而是创建子类
对象时,初始化父类成员用的。
抽象方法:被abstract修饰且没有方法体的方法。
//抽取子类共性且需要重写的方法
public abstract void eat();
1.抽象类可以没有抽象方法,但是抽象方法一定出现在抽象类中。
2.继承抽象类的子类必须重写父类所有的抽象方法。除非该子类也
是抽象类。
final关键字
修饰:类,方法,变量。
- 被final修饰的类不可以被继承 public final class 类名{} ,比如String类
- 被final修饰的方法不可以被重写
- 被final修饰的变量不可以被重新赋值.其实就是自定义常量
局部常量:
jvm会将final修饰且直接声明初始化的自定义常量当成字面值常量使用
public static void main(String[] args) {
byte b1 = 3;
byte b2 = 4;
byte b3 = b1 + b2;//编译报错。byte类型参与运算会提升类型为int
byte b4 = 8 + 9;//编译不报错。字面值常量,jvm编译器完成
/*直接声明初始化*/
final byte b11 = 3;
final byte b22 = 4;
byte b33 = b11 + b22;//编译不报错,此时会把吧b11和b22当成字面值常量
/*先声明后初始化*/
final byte b111;
final byte b222;
b111 = 2;
b222 = 3;
byte b333 = b111 + b222;//编译会报错 b111和b222是常量,但不会当成字面值常量
}
实例常量:
被final关键字修饰的实例变量:jvm不会进行默认赋值
final int NUM=10;//直接声明初始化实例常量
注意点:实例常量加载的时候, jvm不会对其进行默认赋值操作。
//先声明后初始化实例常量
final int VALUE;
public SubClass(){
VALUE=10;//实例常量在new对象时创建。所以把赋值实例常量的过程写在构造器中
}
注意点:如果实例常量先声明后初始化,需要在所有构造器完成实例常量的赋值操作。
如果所有构造器给该实例常量赋值都相同,可以提取赋值操作到构造器代码块。
如果所有构造器给该实例常量赋值出现不同,就只能在每个构造器进行赋值操作。
-----------------------
静态常量:被final修饰的静态变量
静态常量加载的时候, jvm不会对其进行默认赋值操作
直接声明初始化静态常量
static final int NUM=10;
先声明后初始化静态常量,必须且只能在静态代码块中给该静态常量进行初始化赋值操作
static final int VALUE;
static{
VALUE=10;
}
final和abstract不可以修饰同一个类。
final和abstract不可以修饰同一个方法。(且抽象方法没有方法体)
接口:
接口是定义一组固定数据【常量】和行为的标准
一类公司:制定游戏规则的人
二类公司:做产品
三类公司:做服务
接口一共6个成员
内部接口(暂不涉及)
1.静态常量
2.抽象方法
3.默认方法(jdk8.0新增特性)
4.静态方法(jdk8.0新增特性)
5.私有方法(jdk9.0新增特性)
---------------------------------
1.接口成员只有6个,除此之外没有任何内容,没有构造器
2.接口无法直接创建对象,但是可以通过接口创建实现类对象
实现类:实现类与接口的关系是实现关系(和继承类似,但些许不同)
--------------------------------
接口使用步骤:【拿到接口怎么用】
1. 创建接口的实现类
2.重写接口中的抽象方法
3.在测试类中创建接口的实现类对象,调用实现类对象的方法完成需求
静态常量调用:接口名.静态常量名调用【在外界可以直接用】
注意:
1.接口中的静态常量只能直接声明初始化。无法先声明再初始化
2.[ ]中的关键字在声明接口中的静态常量时,可以省略不写【任意个数不写都行】,不写有jvm隐式补全补全。
3.实现类可以继承接口当中的静态常量
接口中的抽象方法
重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
-------------
接口的默认方法(jdk8.0)
就是接口实现类的实例方法,为了满足JavaBean设计规范,将实例方法提取到接口中
以默认方法声明
学习默认方法的目的:
1.源码中存在默认方法,得会看
2.面试会用到:面试题或笔试题
默认方法注意事项:
1、一个类继承父类同时实现父接口,当父类的实例方法和父接口中的默认方法重名,通过
子类对象调用这个同名的方法,执行的是父类当中的实例方法。
2、一个类不继承父类,但是实现多个父接口,且多个父接口中存在同名的默认方法。
此时必须重写父接口中的同名默认方法,否则编译报错。
使用接口的默认方法完善猫狗类
定义接口
public interface MyInterface {
void eat();
default void sleep(){
System.out.println("动物都会睡觉觉");
}
}
定义动物类实现接口
public abstract class Animal implements MyInterface {
//该类完全变成JavaBean格式
private String name;
public Animal() {
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
定义猫狗类
public class Cat extends Animal{
public Cat(String name) {
super(name);
}
public void CatchMouse() {
System.out.println(this.getName()+"正在抓老鼠");
}
@Override
public void eat() {
System.out.println(this.getName()+"会吃鱼");
}
}
public class Dog extends Animal{
public Dog() {
}
public Dog(String name) {
super(name);
}
//狗狗特有的
public void lookHome(){
System.out.println(this.getName() +"会看门");
}
@Override
public void eat() {
System.out.println(this.getName() +"正在吃骨头");
}
}
测试类:
public class DemoExt {
public static void main(String[] args) {
Cat tom = new Cat("tom");
tom.CatchMouse();
tom.eat();
tom.sleep();
System.out.println("---------------");
Dog doudou = new Dog("doudou");
doudou.lookHome();
doudou.eat();
doudou.sleep();
}
}
1
接口中的静态方法(jdk8.0)
接口中的私有方法:(jdk9.0新增特性)
因为有了默认方法和静态方法这样具有具体实现的方法,那么就可能出现多个方法由共同的
代码可以抽取,而这些共同的代码抽取出来的方法又只希望在接口内部使用,所以就增加了私有方法。
继承关系和实现关系区别:
1.在继承关系中,子类可以继承父类的静态方法。
在实现关系中,实现类不可以继承父接口的静态方法,也就是说接口中定义的静态方法只能通过接口来调用。
2.
继承关系
如果是类与类关系:单继承
如果是接口与接口关系:支持多继承
-------------
实现关系:
类与接口之间的关系:多实现