**
* @author 270
* 接口是多个类的公共规范
* 接口是一种引用类型,最重要的是内容是其中的——>【抽象方法】
* 定义接口:
* public interface 接口名称{
* //接口内容
* }
* 备注:换成了关键字interface之后,编译生成的字节码文件仍然是: .java-->.class
*
* 接口可以包含的内容有:
* 1.常量
* 2.抽象方法
* 3.默认方法
* 4.静态方法
* 5.私有方法
*
* 接口使用步骤:
* 1.接口不能直接使用,必须有一个"实现类"来"实现"该接口
* 格式:
* public class 实现类名称 implements 接口名称{
* //...
* }
* 2.接口的实现类必须覆盖重写(实现)接口中所有的抽象方法
* 实现:去掉Abstract关键字,加上方法体大括号。
* 3.创建实现类的对象,进行使用
*
* 注意事项:
* 如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
*/
public class Interface {
public static void main(String[] args) {
//【注意】:MyInterfaceAbstract 是接口,不能直接new,要通过实现类来调用
MyInterfaceAbstractImpl impl = new MyInterfaceAbstractImpl();
impl.methodAbs1();
impl.methodAbs4();
}
}
/**
* @author 270
* 在任何版本的Java中,接口都能定义抽象方法:
*格式:
* public abstract 返回值类型 方法名称(参数列表);
*
* 注意事项:
* 1.接口中的抽象方法,修饰符必须是 public abstract
* 2.这两个关键字修饰符虽然不能省略,但是能选择性省略
* 3.方法的三要素可以随意定义
* 4.接口内定义的抽象方法是没有方法体的
*/
public interface MyInterfaceAbstract {
public abstract void methodAbs1();
public void methodAbs2();
abstract void methodAbs3();
void methodAbs4();
}
package Demo01;
/**
* @author 270
* Java允许接口里定义默认方法。
* 格式:
* public defalut 返回值类型 方法名称(参数列表){
* 方法体
* }
*
* 备注:接口中的默认方法。可以解决接口升级的问题。
* 接口升级指的是
* 默认方法会被实现类继承下去的
*
*/
public interface MyInterfaceDefault {
/**
* 抽象方法
*/
public abstract void methodAbs1();
//抽象方法
/**新添加抽象方法,这样实现类也需要再覆盖重写新的方法
*可以通过改成默认方法就没有这个影响了
* methodDefault是新添加的默认方法
* 默认方法不用覆盖重写
*/
public default void methodDefault(){
System.out.println("默认方法");
}
}
package Demo01;
/**
* @author 270
*/
public class MyInterfaceDefaultImpl implements MyInterfaceDefault{
@Override
public void methodAbs1() {
System.out.println("实现了抽象方法,AAA");
}
}
package Demo01;
/**
* @author 270
*/
public class MyInterfaceDefaultImplB implements MyInterfaceDefault{
@Override
public void methodAbs1() {
System.out.println("实现了抽象方法,BBB");
}
}
package Demo01;
/**
* @author 270
* 1.接口的默认方法,可以通过接口实现类对象,直接调用
* 2.接口的默认方法,也可以通过接口实现类进行覆盖重写
*/
public class Interface02 {
public static void main(String[] args) {
//创建了实现类对象
MyInterfaceDefaultImpl Impl = new MyInterfaceDefaultImpl();
Impl.methodAbs1();
//通过接口来调用默认方法,其实在实现类中没有写
//调用默认方法,如果在实现类中没有,会向上找接口
Impl.methodDefault();
MyInterfaceDefaultImplB b = new MyInterfaceDefaultImplB();
b.methodAbs1();
b.methodDefault();
}
}
package Demo01;
/**
* @author 270
* 接口当中允许定义静态方法。
* 格式:
* public static 返回值类型 方法名称(参数列表){
* 方法体
* }
* 提示:就是将abstract或者default换成static即可,带上方法体
*/
public interface MyInterfaceStatic {
public static void methodStatic(){
System.out.println("接口的静态方法");
}
}
package Demo01;
/**
* @author 270
* 【注意】:不能通过接口实现类的对象来调用接口中的静态方法。
* 正确用法:通过接口名称,直接调用静态方法
*/
public class Demo01Interface {
public static void main(String[] args) {
MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl();
MyInterfaceStatic.methodStatic();
}
}
package Demo01;
/**
* @author 270
*不需要在实现类里覆盖重写默认方法和静态方法(static和default)
*/
public class MyInterfaceStaticImpl implements MyInterfaceStatic{
}
package Demo01;
/**
* @author 270
* 抽取一个公共方法,解决两个默认方法之间重复代码的问题
* 但是这个共有方法不应该让实现类使用,应该是私有化的
*
* 解决:在接口中定义私有方法
* 1.普通私有方法,解决多个默认方法之间重复代码问题
* 格式:
* private 返回值类型 方法名称(参数列表){
* 方法体
* }
* 2.静态私有方法,解决多个静态方法之间重复代码问题
* 格式:
* private static 返回值类型 方法名称(参数列表){
* 方法体
* }
*/
public interface MyInterfacePrivateB {
public static void methodStatic1(){
System.out.println("静态方法1");
methodCommon();
}
public static void methodStatic2(){
System.out.println("静态方法2");
methodCommon();
}
/**
* 将methodCommon方法变为私有方法
* 这样只有接口里的方法能够调用此方法
* 实现类中的方法无法调用
*/
private static void methodCommon(){
System.out.println("AAA");
System.out.println("BBB");
System.out.println("CCC");
}
}
package Demo01;
/**
* @author 270
* 接口当中定义"成员变量"
* 但是必须使用public static final三个关键字进行修饰
* 从效果上来看,这就是接口的【常量】
* 【格式】
* public static final 数据类型 常量名称 = 数据值
*
*
* 【注意事项】
* 1.接口当中的常量,可以省略public static final,注意:不写也照样是这个格式
* 2.接口当中的常量必须进行赋值,不能不赋值
* 3.常量的名称一定要大写,所有字母都要大写,并使用下划线进行分隔
* 4.
*
*/
public interface MyInterfaceConst {
//num其实就是常量,一旦赋值无法修改
//public:指都能使用
//static:指不同通过实现类实现,可以直接调用
//final:说明不可改变
public static final int NUM = 10;
}
在Java 9+版本中,接口的内容可以有:
成员变量其实是常量,格式:
[public] [static] [final] 数据类型 常量名称 = 数据值;
注意:
常量必须进行赋值,而且一旦赋值不能改变。
常量名称完全大写,用下划线进行分隔。
接口中最重要的就是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表);
注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。
从Java 8开始,接口里允许定义默认方法,格式:
[public] default 返回值类型 方法名称(参数列表) { 方法体 }
注意:默认方法也可以被覆盖重写
从Java 8开始,接口里允许定义静态方法,格式:
[public] static 返回值类型 方法名称(参数列表) { 方法体 }
注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
从Java 9开始,接口里允许定义私有很乏,格式:
普通私有方法:private 返回值类型 方法名称(参数列表) { 方法体 }
静态私有方法:private static 返回值类型 方法名称(参数列表) { 方法体 }
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。
package Demo01;
/**
* @author 270
* 1.接口是没用静态代码块或者构造方法的
* 2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
* 格式:public class MyInterface implements MyInterfaceA,MyInterfaceB{
* //覆盖所有抽象方法
* }
* 3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
* 4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类
* 5.如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
* 6.一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突优先使用父类当中的方法。
*/
public class Demo01Interface {
public static void main(String[] args) {
Zi zi = new Zi();
zi.method();
}
}
/** @author 270
* 1.类与类之间是单继承的,直接父类只有一个
* 2.类与接口之间是多实现的,一个类可以实现多个接口。
* 3.接口与接口之间是多继承的
*
* 注意事项:
* 1.多个父接口当中的【抽象】方法如果重复,没关系
* 2.多个父接口当中的【默认】方法如果重复,
* 那么子接口必须进行默认方法的覆盖重写,【必须带有default关键字】
*/
package Demo03Multi;
/**
* @author 270
* 代码当中体现多态性,父类引用指向子类对象
* 格式:
* 父类名称 对象名 = new 子类名称();
* 或者:
* 接口名称 对象名 = new 实现类名称();
*
*/
public class Demo01Multi {
public static void main(String[] args) {
Fu obj = new Zi();
//这里优先用子类方法
obj.method();
//也可以调用父类独有方法
obj.methodFu();
}
}
package Demo04;
/**
* @author 270
* 访问成员变量的两种方法
*
* 1.直接通过对象名称访问,等号左边是谁就优先用谁,没有则向上查找
* 2.间接通过成员方法访问
*/
public class Demo01 {
public static void main(String[] args) {
Fu obj = new Zi();
//访问成员变量
System.out.println(obj.num);
System.out.println("==============");
//访问成员方法,子类有这个方法就先调用子类,没有就通过父类来调用
//子类进行了覆盖重写 即为子
//没有覆盖重写 则为父
obj.showNum();
}
}
package Demo04;
/**
* @author 270
* 在多态的代码中,成员方法的使用规则是:
* 看new的是谁,就优先用谁,没有就向上找
*
* 【成员变量口诀】:编译看左边,运行看右边。
* 比如 Fu obj = new Zi();
* 编译看Fu类,运行看Zi类
* 【成员方法口诀】:编译看左边,运行看右边。
*
*/
public class Demo02MultiMethod {
public static void main(String[] args) {
Fu obj = new Zi();
//成员方法的使用规则是:看new的是谁,就优先用谁
//所以这里优先用子类
obj.method();
//子类没有,所以优先为父类
obj.methodFu();
}
}
package Demo05;
/**
* @author 270
* 向上转型一定是安全的,没有问题的,但是有一个弊端
* 对象一旦向上转型为父类,那么无法调用子类原本持有的内容
*
* 解决方案:用对象的向下转型【还原】
*/
public class Demo01Main {
//对象的向上转型,就是,父类引用指向子类对象
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();
Cat cat = (Cat) animal;
cat.catchMouse();
//下面这行代码是错误的,虽然编译不会报错
//但是无法运行,因为animal已经被设定成一只猫了
//会报错:java.lang.ClassCastException
//类转换异常
Dog dog = (Dog) animal;
}
}
/**
* @author 270
* 如何才能知道一个父类引用的对象,本来是什么子类
* 格式:
* 对象 instanceof 类名称
* 这将会得到一个boolean值结果,也就是判断前面的对象能不能做后面的实例
*/
public class Instanceof {
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.watchHouse();
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
giveMeAPet(new Dog());
}
public static void giveMeAPet(Animal animal) {
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.watchHouse();
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}
package Demo02Laptop;
public class Mouse implements Usb {
@Override
public void open() {
System.out.println("打开鼠标");
}
@Override
public void close() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("鼠标点击");
}
}
package Demo02Laptop;
public class Keyboard implements Usb {
//键盘是usb设备
@Override
public void open() {
System.out.println("打开键盘");
}
@Override
public void close() {
System.out.println("关闭键盘");
}
public void type(){
System.out.println("键盘输入");
}
}
package Demo02Laptop;
/**
* @author 270
*/
public class Computer {
public void powerOn(){
System.out.println("电源开机");
}
public void powerOff(){
System.out.println("电源关机");
}
//使用Usb的方法
public void useDevice(Usb usb){
usb.open();
usb.close();
if(usb instanceof Mouse){
Mouse mouse = (Mouse) usb;
//向下转型
mouse.click();
}else if(usb instanceof Keyboard){
Keyboard keyboard = (Keyboard) usb;
keyboard.type();
//向下转型
}
}
}
package Demo02Laptop;
public class DemoMain {
//创建电脑
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();
//准备鼠标并 首先向上转型
Usb usbMouse = new Mouse();
computer.useDevice(usbMouse);
//参数是usb类型,正好传进去usbmouse这个usb类型
//创建一个usb键盘
Keyboard keyboard = new Keyboard();
//没有使用多态写法
computer.useDevice(keyboard);
//参数是usb,然而参数是usb类型,但是为正确写法,因为这里面也发生了向上转型。
computer.powerOff();
System.out.println("===================");
method(10.0);
//正确:double---->double
method(10);
//正确:int------->double
//自动类型转换。同usb参数类型写Keyboard
}
public static void method(double num){
System.out.println(num);
}
}