类和对象:
1.封装
2.继承
3.多态
(1)向上转型
(2)子类父类有同名的覆盖方法,通过父类引用调用这个方法
(3)动态绑定
❤❣
抽象类:
1.使用abstract修饰的方法,叫做抽象方法。
2.包含抽象方法的类,必须设计为抽象类,使用abstract修饰此类
3.抽象类不能进行实例化
4.抽象类当中可以有和普通类一样的方法,成员。最突出的和普通类不一样的地方就是抽象类不能进行实例化。
5.抽象类可以被继承(抽象类的存在就是为了被继承)
6.当一个普通类继承这个抽象类之后,如果这个抽象类当中包含抽象方法,那么需要重写这个抽象方法,否则代码不能通过编译。
7.如果一个抽象类A继承另一个抽象类B,那么此时这个抽象类A可以不重写B当中的抽象方法。
8.抽象方法不能是private的、static的、final的。
接口:
1.使用interface来修饰接口
2.接口当中的成员变量,默认都是public static final修饰的
3.接口当中的成员方法默认都是public abstract修饰的
4.接口当中的普通成员方法,是不能有具体实现的
5.接口当中的普通成员方法,如果要有具体的实现,必须加上default修饰【JDK8开始】
6.接口当中可以有静态的成员方法。但是不管是静态的方法还是default方法,都是public修饰的。
7.接口也是不能进行实例化的
8.类和接口的关系使用implements来关联的
9.一个接口可以引用 具体实现类的 向上转型
10.接口当中不能有静态 示例代码块 构造方法
11.一个抽象类实现一个接口,可以不重写这个抽象方法(但是不建议)
♀️♂️♂️♀️♀️♂️♀️❤️❤️❤️❤️❤️❤️
在面向对象的概念中,所有对象都是通过类来描述的,但是不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
说明:
1.三角形圆形矩形都是图形,所以与shape类的关系是继承关系
2.shape类不是具体图形,其中的draw方法实际是没有办法实现的,因此可将shape类设计为“抽象类”
说明:
1.Fruit类是水果类,每种水果都有生长环境,但Fruit不是一种具体的水果,因此内部的grow()方法不能具体实现
2.Apple是苹果类,是一种水果,与fruit是继承关系,其次是一种具体的水果,长在树上,其grow()方法可以实现
3.grape是葡萄,是一种水果,与fruit是继承关系,其次是一种具体的水果,长在架子上,其grow()方法可以实现
4.因此:Fruit类可以设计为“抽象类”
在打印图形的例子中,我们发现,父类shape中的draw方法好像并没有什么实际工作,主要绘制图形都是由Shape的各种子类的draw方法来完成的。像这种没有实际工作的方法,我们可以把它设计成一个抽象方法,包含抽象方法的类叫做抽象类。
抽象方法不用给出具体的实现体
//抽象类:被abstract修饰的类
public abstract class Fruit{
//抽象方法:被abstract修饰的方法,没有方法体
abstract public void grow();
abstract void color();
//抽象类也是类,可以增加普通方法和属性
public double Price(){
return price;
}
protected double price;//价格
}
注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法
1.抽象类不能直接实例化对象
Shape shape = new Shape();
//编译出错
Error:(30,23)java:Shape是抽象的,无法实例化
2.抽象方法不能是private的
abstract class Fruit{
abstract private void grow();
}
//编译出错:
Error:(4,27)java:非法的修饰组合:abstract和private
注意:抽象方法没有加访问限定符时,默认是public
3.抽象方法不能被final和static修饰,因为抽象方法要被子类重写
public abstract class Shape{
abstract final void methodA();
abstract public static void methodB();
}
//编译报错
//Error:(20,25)java:非法的修饰符组合:abstract和final
//Error:(21,35)java:非法的修饰符组合:abstract和static
4.抽象类必须被继承,并且子类要重写父类的抽象方法,否则子类也是抽象类,必须要使用abstract修饰
5.抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类。
6.抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
普通类也可以被继承,普通方法也可以被重写,为什么非得用抽象类和抽象方法呢?
使用抽象类相当于多了一重编译器的校验
使用抽象类实际工作不应该由父类完成,而应由子类完成。那么此时如果不小心误用成父类了,使用普通编译器是不会报错的,但是父类是抽象类就会在实例化的时候提示错误,让我们尽早发现问题。
很多语法存在的意义都是为了“预防错误”,我们曾经使用的final也是类似,创建的变量不去修改,不就相当于常量吗?但是加上final能够在误修改的时候,让编译器及时提醒我们。
充分编译器的校验,在实际开发中是非常有意义的。
在java中,接口可以看成是:多个类的公共规范,是一种引用数据类型
接口定义形式与类定义形式基本相同,将class关键字换成interface关键字,就定义了一个接口。
public interface 接口名称{
//接口方法
public abstract void mathod1();//public abstract 是固定搭配,可以不写
public void method2();
abstract void method3();
void method4();
//注意:在接口中上述写法都是抽象方法,更推荐最后一种,代码更简洁
}
提示:
1.创建接口时,接口的命名一般以大写字母I开头
2.接口的命名一般使用“形容词”词性的单词
3.阿里编码规范中约定,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性
接口不能直接使用,必须需要有一个“实现类”来实现该接口,实现接口中所有的抽象方法
public class 类名 implements 接口名称{
//.....
}
请实现笔记本电脑使用USB鼠标、USB键盘的例子
1.USB接口:包含打开设备,关闭设备功能
2.笔记本类:包含开机功能、关机功能、使用USB设备功能
3.鼠标类:使用USB接口,并具备点击功能
4.键盘类:使用USB接口,并具备输入功能
//USB接口
public interface USB {
void openDevice();
void closeDevice();
}
//鼠标类,实现USB接口
public class Mouse implements USB{
@Override
public void openDevice(){
System.out.println("打开鼠标");
}
@Override
public void closeDevice(){
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("鼠标点击");
}
}
//键盘类,实现USB接口
public class KeyBoard implements USB{
@Override
public void openDevice(){
System.out.println("打开键盘");
}
@Override
public void closeDevice(){
System.out.println("关闭键盘");
}
public void inPut(){
System.out.println("键盘输入");
}
}
//笔记本类:使用USB设备
public class Computer {
public void powerOn(){
System.out.println("打开笔记本电脑");
}
public void powerOff(){
System.out.println("关闭笔记本电脑");
}
public void useDevice(USB usb){
usb.openDevice();
if(usb instanceof Mouse){
Mouse mouse = (Mouse)usb;
mouse.click();
}else if(usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.inPut();
}
usb.closeDevice();
}
}
//测试类
public class TestUSB {
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();
//使用鼠标设备
computer.useDevice(new Mouse());
//使用键盘设备
computer.useDevice(new KeyBoard());
computer.powerOff();
}
}
1.重写接口中方法时,不能使用default访问权限修饰
public interface USB{
void openDevice(); //默认是public的
void closeDevice(); //默认是public的
}
public class Mouse implements USB{
@Override
void openDevice(){
System.out.println("打开鼠标");
}
//...
}
//编译报错,重写USB中openDevice方法时,不能使用默认修饰符
//正在尝试分配更低的访问权限;以前为public
2.接口中含有的变量会被隐式指定为public static final变量
public interface USB{
double brand = 3.0;//默认被final public static修饰
void openDevice();
void closeDevice();
}
public class TestUSB{
public static void main(String[] args){
System.out.println(USB.brand);//可以直接通过接口名访问,说明是静态的
//编译报错:Error:(12,12)java:无法为最终变量brand分配值
USB.brand = 2.0; //说明brand具有final属性
}
}
3.接口中不能有静态代码块和构造方法
public interface USB{
//编译失败
public USB(){
}
{} //编译失败
void openDevice();
void closeDevice();
}
4.接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
8.如果类没有实现接口中的所有抽象方法,则类必须设置为抽象类
9.jdk8中:接口还可以包含default方法
在Java中,类与类之间是单继承的,一个类只能有一个父类,即java中不支持多继承,但是一个类可以实现多个接口。
class Frog extends Animal implements IRunning,ISwimming{
//...
}
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类
提示:IDEA中使用ctrl+i快速实现接口
代码展示了java面向对象编程中最常见的用法:一个类继承一个父类,同时实现多重接口
继承表达的含义是is-a语义,而接口表达的含义是具有XXX特性
青蛙是一种动物,既能跑也能游泳
这样设计的好处,牢记多态的好处:让程序猿忘记类型。有了接口以后,类的使用者就不必关心具体类型,而只关注某个类是否具备某种能力
接口和接口之间可以多继承,即:用接口可以达到多继承的目的
接口可以继承一个借口,达到服用的效果,使用extends关键字
interface IRunning{
void run();
}
interface ISwimming{
void swim();
}
//两栖的动物,既能跑也能游泳
interface IAmphibious extends IRunning,Swimming{
}
class Frog implements IAmphibious{
...
}
接口的继承相当于把多个接口和并在一起