跳至主要內容

抽象、接口和内部类

村雨遥原创大约 8 分钟Java 基础Java

抽象、接口和内部类

共勉

不要哀求,学会争取。若是如此,终有所获。

抽象方法

定义

所谓抽象方法,就是将公共的行为(方法)抽取到一个父类后,由于每个子类中执行的内容是不一致的,所以父类中无法确认具体的方法体,此时就可以将该方法定义为抽象方法。

格式

要定义一个抽象方法,那么需要遵循以下的格式,要注意,抽象方法一般都是没有定义

public abstract 返回值类型 方法名(参数列表);

以下是一个抽象方法定义的具体实例。

public abstract void welcome(String name);

抽象类

定义

知道了什么是抽象方法,那么抽象类就很简单了,如果我们发现一个类中存在着抽象方法,那么这个类一定要声明为抽象类。

格式

public abstract class 类名{

}
public abstract class Person{

}

注意

  1. 抽象类不能实例化。
  2. 抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类。
  3. 抽象类中可以有构造方法。
  4. 如果一个类的父类是抽象类,那么这个类要么是抽象类,要么重写父类中所有的抽象方法。

作用

在抽取共性时,如果无法确定方法体,此时就可以将该方法定义为抽象方法。然后强制让子类按照某种格式重写。

接口

定义

接口是一种规则,是对行为的抽象。

格式

public interface 接口名{

}

注意

  1. 接口和抽象类一样,不能被实例化。
  2. 接口和类之间是实现关系,通过关键字 implements 表示,实现格式为:
public class 类名 implements 接口名{

}
  1. 如果一个类实现了某个接口,那么这个类要么是抽象类,要么就得重写接口中所有的抽象方法。
  2. 不同于类单继承的特点,一个类是可以实现多个接口的。

成员的特点

  1. 成员变量

接口中,成员变量只能是常量,默认修饰符为 public static final

  1. 构造方法

接口中不存在构造方法。

  1. 成员方法

JDK 7 之前,只能是抽象方法,其默认修饰符为 public abstractJDK 8 时,能够定义有方法体的方法,JDK 9 中,有带来了可以定义私有方法的特性。

默认方法

JDK 8 之后,就允许在接口中定义默认方法,但是需要使用关键字 default 来修饰,从而解决接口升级的问题。

接口中的默认方法的定义格式为:

public default 返回值类型 方法名(参数列表){}

使用默认方法时,需要注意:

  • 接口中的默认方法不是抽象方法,所以没有要求强制被重写。但如果要重写默认方法,重写时就需要去掉默认方法的关键字 default
  • 默认方法中的权限空置房 public 可以省略不写,但关键字 default 不能省略。
  • 如果一个类实现了多个接口,而且着多个接口中还存在着重名的默认方法,那么该类就必须对重名的默认方法进行重写。

以下是一个存在重名默认方法必须重写的实例。

public interface InterOne{
    public abstract void method1();

    public default void method2(){
        System.out.println("默认方法 method2");
    }
}
public interface InterTwo{

    public default void method2(){
        System.out.println("默认方法 method2");
    }

    public abstract void method3();
}
public class Main implements InterOne, InterTwo{
    @Override
    public void method1(){
        System.out.println("抽象方法 1");
    }

    @Override
    public void method3(){
        System.out.println("抽象方法 3");
    }

    @Override
    // 注意重写需要去掉关键字 default
    public void method2(){
        System.out.println("默认方法 2");
    }
}

静态方法

除了默认方法,JDK 8 以后还可以在接口中定义静态方法,此时需要用关键字 static 修饰。

接口中 静态方法 的定义格式为:

public static 返回值类型 方法名(参数列表){}

在接口中使用静态方法时,需要注意:

  • 静态方法只能通过接口名调用,不能通过实现接口的类名或者对象名来调用。
  • 权限控制符 public 可以省略,但关键字 static 不能省略。

以下是一个在接口中定义静态方法和调用接口中静态方法的实例。

public interface Inter{

    public static void method(){
        System.out.println("静态方法 method");
    }
}
public class Main implements Inter{
    public static void main(String[] args){
        // 调用接口中的静态方法
        Inter.method();
    }
}

私有方法

除了上述的静态方法和默认方法之外,JDK 9 中又引入接口中定义私有方法的特性。

其中,接口中定义私有方法的格式如下:

private 返回值类型 方法名(参数列表){}
private static 返回值类型 方法名(参数列表){}

两者的区别在于:静态的私有方法(带关键字 static)是为接口中的静态方法服务,而非静态的私有方法(不带关键字 static) 则是为接口中的默认方法服务。

以下是在接口中定义私有方法的实例:

  1. 私有方法
public interface Inter{

	private void method(){
        System.out.println("私有方法 method");
    }

    public default void method1(){
        method();
        System.out.println("默认方法 method1");
    }
}
  1. 静态私有方法
public interface Inter{

	private static void method(){
        System.out.println("私有方法 method");
    }

    public static void method1(){
        method();
        System.out.println("静态方法 method1");
    }
}

接口和类之间的关系

  1. 类和类的关系

类与类之间只能存在继承关系,且只限于单继承,不能多继承,但是可以多层继承。

  1. 类和接口的关系

类和接口之间是实现关系,既可以单实现,也可以多实现,还能在继承一个类的同时实现多个接口。

  1. 接口和接口的关系

接口之间是继承关系,但不同于类和类之间的关系,接口之间既可以单继承,也可以多继承。

内部类

定义

顾名思义,所谓内部类就是定义在类中的类。比如说在 A 类的内部定义了一个 B 类,那么我们就说 B 是内部类。其中 B 类表示的是 A 类的一部分,而且 B 类单独存在时没有任何意义。

public class Outer{
    public class Inner{

    }
}

特点

如果一个类中定义了一个内部类,那么这个内部类就能够直接访问外部类的所有成员,包括私有成员。

但是,如果一个外部类要访问内部类的成员,那么此时就必须创建对象。

public class Outer{
    private String name;
    private String address;

    public class Inner{
        String id;
        String age;

        public void show(){
            // 内部类可以直接访问外部类的所有成员
            System.out.println(id + " " + age + " " + name + " " + address)
        }
    }
}

分类

Java 中,内部类主要分为以下四种:

  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类

成员内部类

写在成员位置,属于外部类的成员,其中成员内部类也能够被常用的修饰符 public、private、protected、static 等所修饰。

public class Outer{
    private String name;
    private String address;

    public class Inner{
        String id;
        String age;
    }
}

要想获取成员内部类对象,可以通过以下两种方式:

  1. 在外部类中编写方法,然后对外提供内部类的对象。
public class Outer{
    private String name;
    private String address;

    public class Inner{
        String id;
        String age;
    }

    public Inner getInnerInstance(){
        return new Inner();
    }
}
  1. 直接创建,创建格式为:外部类名.内部类名 对象名 = 外部类对象.内部类对象
public class Main{
    public static void main(String[] args){
        Outer.Inner inner = new Outer().new Inner();
    }
}

静态内部类

静态内部类就是用关键字 static 修饰的内部类。静态内只能访问外部类中的静态变量和静态方法,如果要访问非静态的变量和方法就需要创建对象。

public class Outer{
    private String name;
    private String address;
    static String birth = "20220222";

    static class Inner{
        String id;
        String age;

        public static void show(){
            System.out.println("静态方法" + birth);
        }

        public void display(){
            System.out.println("非静态方法");
        }

    }
}

创建静态内部类对象的格式为:外部类名.内部类对象名 = new 外部类名.内部类名();

调用非静态方法的格式:先创建对象,然后用对象调用。

调用静态方法的格式:外部类名.内部类名.方法名();

public class Main{
    public static void main(String[] args){
        Outer.Inner inner = new Outer().new Inner();
        // 调用非静态方法
        inner.display();
        // 调用静态方法
        Outer.Inner.show();
    }
}

局部内部类

如果一个类被定义在方法中,那么这个类就叫做局部内部类。外界是无法直接使用局部内部类,需要在方法内部创建对象并使用。同时,这个内部类既可以访问外部类的成员,也可以访问方法中的局部变量。

public class Outer{
    public String id;
    public void show(){
        class Inner{
            String name;

            public void show(){
                System.out.println("局部类内部方法");
                System.out.println(id);
                System.out.println(name);
            }
        }
        Inner inner = new Inner();
        System.out.println(inner.name);
        inner.show();
    }
}

匿名内部类

匿名内部类就是没有名字的内部类,也正因为名字,所以匿名内部类只能使用一次。而且使用匿名内部类还有个前提条件:必须继承一个父类或者实现一个接口。

new 类名/接口名(){
    重写方法;
}
public interface Inner{
    public abstract void method();
}
public class Main{
    public static void main(String[] args){
        new Inner(){
            @Override
            public void method(){
                System.out.println("方法重写");
            }
        }
    }
}

⏳ 联系

想解锁更多知识?不妨关注我的微信公众号:村雨遥(id:JavaPark)

扫一扫,探索另一个全新的世界。

上次编辑于:
贡献者: 村雨遥