final
- final可以修饰类、方法、变量
- final修饰的类不可被继承
- final修饰的方法不可被重写
- final修饰的变量是一个常量,只能被赋值一次
- 内部类只能访问被final修饰的局部变量
- final修饰的变量格式:AAA_BBB_CCC (全字母大写,单词与单词之间使用下滑线分割)
抽象类、抽象方法
- 关键字:abstract
- 抽象方法必然存在于抽象类中(有抽象方法必然是抽象类)
abstract class A{
abstract void test();
}
- 抽象方法只声明方法不进行具体方法的实现,示例:
abstract void test();
只能说明有这个功能却不能具体的知道是要实现什么,所以不进行具体的实现。 - 抽象类是用于继承的,示例:
class A extends B{}
- 抽象类不能被实例化,因为没有具体方法的实现,所以实例化没有意义
- 子类必须重写所有继承的抽象类的所有方法后才能进行实例化,否则该子类还是抽象类。
- 抽象类有构造函数,用于给子类进行初始化
- 抽象类可以不定义抽象方法,目的是为了不让该抽象类创建对象,AWT的适配器就是这种抽象类
- abstract不能于private、static、final相互组合
- 抽象类于普通类的异同点:
- 相同点:
- 都是用来描述事物,都定义成员(变量、函数)
- 不同点:
- 普通类有足够的信息描述事物
- 抽象类可能描述不足
- 普通类中不能定义抽象方法,
- 抽象类中既可以定义普通方法也可以定义抽象方法(定义一般方法时需要有方法体)
- 普通类可以进行实例化
- 抽象类不能进行实例化
- 相同点:
- 抽象类一定是一个父类,因为它需要子类重写他的方法后才对子类进行实例化
抽象类练习题
- 问题:员工有姓名、工号、工资、工作;经理有姓名、工号、工资、工作、奖金。
- 进行数据建模,进行抽象
package com.bixiangdong.oop;
//抽象
abstract class Person{
String name;
int id;
double money;
Person(String name,int id,double money){
this.name=name;
this.id=id;
this.money=money;
}
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 double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
abstract void work();
}
//employee
class Employee extends Person{
Employee(String name,int id,double money){
super(name,id,money);
//继承的方式 子类构造函数 的第一行默认调用父类的构造函数,
// 如果没有无参构造那么就要显示的定义有参构造
}
@Override
void work() {
System.out.println(name+" "+id+" "+money+"我是员工,我工作");
}
}
class Manager extends Person{
double bous;
Manager(String name,int id,double money,double bous){
super(name,id,money);
this.bous=bous;
}
@Override
void work() {
System.out.println(name+" "+id+" "+money+" "+bous+"我是经理,我工作");
}
}
public class Demo03 {
public static void main(String[] args) {
new Employee("高鹏",1,10.00).work();
new Manager("经理",10,10.0,1000.0).work();
}
}
接口
- 格式:interface A{}
- 接口中的成员修饰符是固定的(如果没有写 前面的固定修饰符是默认存在的):
- 成员常量:public static final 名称
- 成员函数:public abstract 名称
- 成员都是public修饰的
- 接口可以多实现,另类的多继承
- 如果一个抽象类中的方法都是抽象方法的时候,可以定义为接口
- 接口就是一个纯种的抽象类,所以也不能进行初始化
接口的实现 implements
- 格式:class BImpl implements B{}
- BImpl需要重写B中的所有抽象方法
多实现
package com.bixiangdong.oop;
interface Demo04 {
public static final int A = 0;
public abstract void c();
}
interface DemoA{
public abstract void d();
public abstract void c();
}
class DemoImpl implements Demo04,DemoA{
@Override
public void c() {
}
@Override
public void d() {
}
}
重点:因为多继承调用方法时会出现调用不确定的情况(如果继承的两个类里面有同一个方法),所以Java使用多实现的机制进行另类的多继承(这是基于接口的特性来进行的,因为接口中的方法都是抽象方法,所以方法是没有具体的实现的,需要实现类来重写接口中的方法,此时就算多实现时有两个接口具有同样的抽象方法,也是在实现类中进行一次重写,如此实现类实例化之后调用的方法也是实现类中的方法不存在调用不确定的情况)
疑问:接口中的抽象方法是没有具体实现的,实现类进行实现,那么多实现的意义在哪?
继承-实现-组合使用
- 接口的出现解决了单继承的局限性
接口与接口之间是继承关系,而且接口可以多继承
- 为什么接口可以多继承?
- 因为所有的抽象方法都由子类实现,所以不会存在调用不确定性问题
interface Demo04 {
public static final int A = 0;
public abstract void c();
}
interface DemoB{
}
interface DemoA{
public abstract void d();
public abstract void c();
}
interface Test extends DemoA,DemoB{
}
接口的特点
- 接口时对外暴露的规则
- 接口是程序的功能扩展
- 接口的出现降低了耦合性(解耦)
- 接口可以用来多实现
- 类与接口之间是实现关系,类可以继承一个类的同时实现多个接口
- 接口与接口之间可以有继承关系(可以多继承)