Java学习笔记 07、面向对象—重要知识点(二)

简介: Java学习笔记 07、面向对象—重要知识点(二)

六、Interface接口


1、介绍Interface


定义成员,通过implements来实现接口


Interface:接口仅仅只是有相同的行为特征,继承是"是不是"的关系,接口是"能不能"的关系,也支持多态,可以取代具体的子类或抽象父类作为参数或返回类型,那么就可以传入任何实现该接口的东西。


接口定义成员:


JDK7之前:只能定义全局常量(public static final)与抽象方法(public abstract),并且这些前缀可不写效果依旧。


interface Skill{
    int flyTime = 100;//默认与右边相同:public static final int flyTime = 100;
    void fly();//默认与右边相同:public abstract void fly();
}


JDK8:除了全局常量和抽象方法,还可以定义静态、默认方法(技术角度来看是合法的,看起来违背了接口理念)


静态方法(static):可通过接口.静态方法直接调用方法,并执行方法体。


默认方法(default):可通过创建实现类(先实现接口)对象,调用接口的默认方法,执行方法体。


//接口
interface Skill{
  //静态方法
    static void walk(){
        System.out.println("走路....");
    }
  //默认方法:包含实现体
    default void fly() {
        System.out.println("fly......");
    }
}
//实现接口
class Person implements Skill{
}
public class Main {
    public static void main(String[] args){
      //直接接口调用
        Skill.walk();//走路....
        //实现类调用默认方法
        new Person().fly();//fly......
    }
}


注意:接口没有构造器!!!


相关设计模式:代理模式、工厂模式



2、接口特性


实现多接口

格式:class 类名称 extends 类 implements 接口1,接口2{}


特点:弥补了Java单继承的局限性。


接口冲突案例:实现多个接口时都有同名同参数方法需要重写其方法


interface Skill{
    //默认方法
    default void fly() {
        System.out.println("skill接口的fly......");
    }
}
interface Clothes{
    //默认方法
    default void fly() {
        System.out.println("clothes会飞......");
    }
}
//实现两个接口
class Student implements Skill,Clothes {
    //重写方法
    @Override
    public void fly() {
        System.out.println("student自己会飞");
    }
}
public class Main {
    public static void main(String[] args){
        new Student().fly();//student自己会飞
    }
}


说明:实现多个接口时,若是都有同名同参数,会出现接口冲突,需要对冲突方法进行重写,否则会报错!!



接口多继承


多继承:接口与接口之间是可以继承的,并且能够多继承!


interface AA{
    void sleep();
}
interface BB{
    void walk();
}
//这里使用到了extends继承
interface CC extends AA,BB{
}


注意:如果类实现多继承的接口,那么必须实现所有的抽象方法,才能进行实例化;没有实现抽象方法的则会变为抽象类。



匿名接口类


接口类的实现方式:就是创建一个类实现其接口。


匿名接口类:与匿名抽象类有点类似,如下


interface USB{
    void start();
    void stop();
}
//Flash驱动
class Flash implements USB{
    @Override
    public void start() {
        System.out.println("Flash开始准备工作.....");
    }
    @Override
    public void stop() {
        System.out.println("Flash结束传输工作.....");
    }
}
public class Main {
    public static void main(String[] args){
        //接口类实例化
        USB usb = new Flash();
        //匿名接口类 (可作为参数传递到方法中,实现多态)
        new USB() { //也可用USB u = new USB(){实现} 多态形式接收
            @Override
            public void start() {
                System.out.println("xxx驱动启动了.....");
            }
            @Override
            public void stop() {
                System.out.println("xxx驱动结束运行了.....");
            }
        };
    }
}


接口注意点(3点)

下面的接口与类是接下来注意点中的使用部分:


interface Skill{
    //默认方法
    default void fly() {
        System.out.println("skill接口的fly......");
    }
}
class Person{
    //与接口同名同参数方法
    public void fly(){
        System.out.println("Person的fly...");
    }
}


注意点如下:


实现接口,若是其接口有默认方法可以进行重写。


若是继承父类以及实现的接口中都有同名同参数的方法时,子类再没有重写情况下,会调用父类中的方法。


//继承Person以及实现Skill接口   extends写在前
class Student extends Person implements Skill{
}
public class Main {
    public static void main(String[] args){
        //调用的是父类的方法
        new Student().fly();//fly......
    }
}


对于父类、接口以及自己重写的方法该如何去调用同名同参数的方法?三种


//继承Person以及实现Skill接口   extends写在前
class Student extends Person implements Skill{
    @Override
    public void fly() {
        System.out.println("Student自己会飞啦");
    }
    //测试调用不同的fly方法
    public void executeMethod(){
        fly();//调用自己重写的fly()方法
        super.fly();//调用父类的fly()方法
        Skill.super.fly();//调用实现接口的fly()方法,若是有其他接口也如这样调用
    }
}
public class Main {
    public static void main(String[] args){
        new Student().executeMethod();
    }
}


针对于父类、接口的属性获取方式:


class A{
    public int m = 5;
}
interface B{
    int m=6;
}
class C extends A implements B{
    public C(){
        System.out.println(super.m);//直接super.属性,与上面获取父类方法一致
        System.out.println(B.m);//直接B.属性,因为接口中属性是static
    }
}
public class Main {
    public static void main(String[] args){
        new C();
    }
}


3、接口实例演示


接口与多态应用

接口与我们生活中的USB接口也有类似的地方,会定义一些传输数据,以及例如传输数据、开始与结束的方法。


使用:满足多态,实际上定义了一种规范,在开发中很多都面向接口编程。


实例:接口的一种使用方式


//定义了USB的两个规范方法
interface USB{
    void start();
    void stop();
}
//Flash驱动
class Flash implements USB{
    @Override
    public void start() {
        System.out.println("Flash开始准备工作.....");
    }
    @Override
    public void stop() {
        System.out.println("Flash结束传输工作.....");
    }
}
//打印机驱动
class Printer implements USB{
    @Override
    public void start() {
        System.out.println("Printer开始准备工作.....");
    }
    @Override
    public void stop() {
        System.out.println("Printer结束传输工作.....");
    }
}
//电脑主机
class Computer{
    /**
     * 用于主机进行装配驱动并传输数据
     * @param usb 多态,传入不同驱动
     */
    public void transferData(USB usb){
        usb.start();
        System.out.println("传输数据.....");
        usb.stop();
    }
}
public class Main {
    public static void main(String[] args){
        new Computer().transferData(new Flash());
        System.out.println("更换设备....");
        new Computer().transferData(new Printer());
    }
}


USB接口:相当于一种规范,让不同的驱动实现其中的固定步骤。

Flash、Printer实现类:用于实现USB接口的方法,两个驱动都有其不一样的启动与结束

Computer类:单独电脑类,其中传输方法中的参数就是需要指定驱动类传入,这样的话我想用哪个驱动传入进来即可



包含了多态的使用!



4、接口面试题


题1:一个类、一个接口,类与接口中有相同属性名,如何调用获取


interface A{
    int x=0;
}
class B{
    int x=1;
}
public class C extends B implements A{
    public void pX(){
        System.out.println(super.x);
        System.out.println(A.x);
    }
    public static void main(String[] args) {
        new C().pX(); 
    }
}


对于继承父类:super.属性


对于实现接口属性:接口名.属性 因为属性默认为public static final静态常量,所以可直接接口名获取



七、内部类


1、介绍内部类及分类


内部类:java中允许将一个B类声明放入到A类中,那么B就是内部类,A就是外部类。


//类,也称外部类
class A{
    //内部类
    class B{
    }
}


分类:


成员内部类:静态、非静态

局部内部类:方法内,代码块内,构造器内

分类举例如下:


class Person{
    //1.1静态成员内部类
    static class A{
    }
    //1.2非静态成员内部类
    class B{
    }
    public void method(){
        //2.1 局部内部类(局部方法中)
        class C{
        }
    }
    {
        //2.2 局部内部类(代码块中)
        class D{
        }
    }
    public Person(){
        //2.3 局部内部类(构造器中)
        class E{
        }
    }
}


2、内部类属性方法调用


成员内部类:一方面作为外部类的成员,另一方面作为一个类


作为外部类成员:可调用外部类的接口;可static修饰;可使用四种权限符

作为一个类:可定义属性、方法、构造器等,可被final修饰,可被abstract修饰


①针对于static内部类:其内部方法中无法调用外部类的属性及方法,因为想要调用首先外部类必须是静态的,但是作为外部类是不能被static修饰的。


②针对于非static内部类:其内部方法可以调用外部属性与方法。


外部类属性与方法(static):外部类名.属性 或 外部类名.方法

外部类属性与方法(非static):外部类名.this.属性 或 外部类名.this.方法名

示例演示:


②中的调用外部类属于与方法(static):正常通过类名调用即可


class Person{
    private static String name;
    public static void eat(){
        System.out.println("eat吃东西");
    }
    //内部类(非静态)
    class P{
        private String name;
        public void eat(){
            //调用外部类静态属性
            Person.name = "123";
            //调用外部类静态方法
            Person.eat();
        }
    }
}


②中的调用外部类属于与方法(非static):需要类名+this,与之前实现接口调用属性有点类似


class Person{
    private String name;
    public void eat(){
        System.out.println("eat吃东西");
    }
    //内部类(非静态)
    class P{
        private String name;
        public void eat(){
            //调用外部类属性(非静态)
            Person.this.name = "123";
            //调用外部类方法(非静态)
            Person.this.eat();
        }
    }
}


3、三个主要问题


实例化内部类

内部类也分为两种:静态与非静态


class Person{
  //静态内部类
    static class A{
        public void show(){
            System.out.println("我是A的show()");
        }
    }
    //内部类
    class B{
        public void show(){
            System.out.println("我是B的show()");
        }
    }
}


根据上面的代码我们准备好了静态内部类以及内部类:


静态内部类实例:Person.A a = new Person.A(); 直接创建静态内部类实例


内部类实例:


//首先实例化外部类
Person person = new Person();
//接着再实例化内部类,很合理
Person.B b = person.new B();


区分内部类与外部类属性

见代码:之前内部属性调用也有说明


class Person{
    //①外部类属性
    String name="小明";
    public class Bird{
        //②内部类属性
        String name="麻雀";
        //③参数属性
        void show(String name){
            //输出外部类的name
            System.out.println(Person.this.name);  //调用Person类中的this(相当于Bird)的name属性
            //输出成员内部类Bird的name
            System.out.println(name);              //直接name,就是离得最近的形参
            //输出show中的形参name
            System.out.println(this.name);         //this(指的是Person类) 调用这个类的属性
        }
    }
}


开发中内部类应用(Comparable接口)

【1】返回局部内部类实现comparable接口的匿名实例


class MyTest{
    //返回一个非匿名接口实现类
    public Comparable<Object> getComparable(){
        //实现Comparable接口
        class MyComparable implements Comparable<Object>{
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        return new MyComparable();
    }
}


【2】不实现接口实现类,直接返回匿名接口类对象


class MyTest{
    //返回一个匿名接口类
    public Comparable<Object> getComparable(){
        return new Comparable<Object>() {
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        };
    }
}


参考资料

[1]. java类什么时候加载?,加载原理机制是怎么样的?


[2]. 书籍《head first java 2.0》

相关文章
|
12天前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
10 2
|
2月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
33 4
|
2月前
|
Java
接口和抽象类【Java面向对象知识回顾②】
本文讨论了Java中抽象类和接口的概念与区别。抽象类是不能被实例化的类,可以包含抽象和非抽象方法,常用作其他类的基类。接口是一种纯抽象类型,只包含抽象方法和常量,不能被实例化,且实现接口的类必须实现接口中定义的所有方法。文章还比较了抽象类和接口在实现方式、方法类型、成员变量、构造方法和访问修饰符等方面的不同,并探讨了它们的使用场景。
接口和抽象类【Java面向对象知识回顾②】
|
30天前
|
安全 Java 编译器
Java基础-知识点(二)
Java基础-知识点(二)
12 0
|
30天前
|
存储 缓存 安全
Java基础-知识点(一)
Java基础-知识点(一)
16 0
|
30天前
|
存储 Java 程序员
Java基础-面向对象
Java基础-面向对象
15 0
|
1月前
|
Java 数据安全/隐私保护
java学习笔记(基础习题)
java学习笔记(基础习题)
31 0
|
1月前
|
Java 程序员 开发工具
java学习笔记
java学习笔记
34 0
|
5月前
|
Java 开发者
Java 面向对象新视界:揭秘子类如何“继承”父类精华,再添“创新”之笔
【6月更文挑战第16天】在Java的面向对象世界,子类继承父类的特性,如`Circle`继承`Shape`,展示“is-a”关系。子类不仅保留父类的`color`和`display`方法,还添加了`radius`属性及定制的显示逻辑。这种继承与创新允许代码复用,增强灵活性和可扩展性,使得构建复杂系统变得更加高效和模块化。通过持续的继承与定制,开发者能构建出一系列独具特色的类,充分展现面向对象编程的力量。
151 57
|
4月前
|
Java 编译器
Java面向对象(三)详解: 封装 | 继承 | 方法重写 | 抽象类
Java面向对象(三)详解: 封装 | 继承 | 方法重写 | 抽象类
下一篇
无影云桌面