包用于划分类的命名空间,使得不同包中的同名类不会冲突。
Java 使用文件夹存储包,文件夹名和包名一致。
Java 运行时系统从当前目录中、CLASSPATH 变量定义的值、-classpath 指定的值这三种途径寻找包。

包和成员访问

可访问性 private 无修饰符 protected public
同一个类
同一个包的子类
同一个包的非子类
不同包的子类
不同包的非子类

一个源文件中只能有一个 public 类,并且该文件必须以这个类的名称命名。

导入包

import 语句位于 package 语句之后,其他语句之前。
java.lang 包由编译器隐含导入。
如果使用全限定名,则不需要 import 语句。

接口

一个类可以实现任意数量的接口,一个接口可以被任意数量的类实现。

modifier interface name {
  type name(parameterList);
  
  type name = value;
}

没有修饰符时,接口只能被同一个包下的其他对象使用。public 接口在一个源文件中只能有一个,并且这个文件的名字必须和这个接口同名。接口中的方法本质上都是抽象方法。每个实现接口的类必须实现这个接口的全部方法。

从 JDK8 开始,接口中的方法允许有默认实现,也有了静态方法。从 JDK9 开始,接口中可以有私有方法。

接口中可以定义变量,这些变量默认是 final 和 static 的,必须初始化,不能被实现类改变。

接口中所有方法和变量默认为 public。

class name implements interface[,interface...] {
  // body
}

若某个类实现了两个接口,同时这两个接口定义了完全一样的方法,则类实现这个方法,表示同时实现了这两个接口定义的该方法。

实现接口的方法时,方法必须定义为 public 并且方法签名必须和接口中的定义一致。

接口类型变量可以引用任何实现了该接口的类实例,这个变量调用方法时,调用的是类实例中对应的方法。能够通过该变量调用的方法必须在接口中有定义,不能调用接口中没有定义的方法。

实现接口的类没有实现接口中全部方法时,该类必须定义为抽象类,该类的子类必须实现接口的全部方法或者定义为抽象类。

接口作为一个类或者另一个接口的成员时,该接口分别称为成员接口、nested 接口。nested 接口可以用 public、private 或 protected 修饰。在定义 nested 接口的作用域外使用该接口时,使用完全限定名,如 ClassName.interfaceName

实现仅定义了变量的接口的类,具有该接口定义的所有变量,这些变量本质上是常量。(不推荐这种做法。)

接口也可以像类一样,进行继承。实现了某个接口的类必须实现该接口的所有方法,如果该接口还继承了其他接口,那么所有继承自其他接口的方法也必须被实现。

默认接口方法

从 JDK8 开始,接口中允许定义默认方法,默认方法是接口提供了实现的方法,也称 extension method。
默认方法提出的主要动机是,当使用广泛的接口突然加入新的方法,由于之前使用该接口的代码没有实现这个新方法,涉及到这个接口的旧代码都会出错。如果使用了默认方法,则旧代码不会受到影响。
默认方法的另一个动机是,有时接口的部分方法某些实现类不需要,此时只能将该方法实现为空方法,冗余。默认方法解决了这个问题。

接口和类的很大不同之处在于,接口不能维护状态信息。接口不能实例化。

default type name(parameterList) {
  // body
}

实现接口的类可以实现,也可以不实现接口的默认方法。

当一个类实现了两个接口,这两个接口具有相同的默认方法时,1)如果该类重写了这个默认方法,则之后使用的是类重写的方法;2)如果没有重写这个默认方法,则报错。

当一个类实现了一个接口 A,A 继承了接口 B。这两个接口具有相同的默认方法时,类没有重写该默认方法,则使用的是接口 A 定义的默认方法。访问另一个默认方法的形式为:interfaceName.super.methodName()

interface IA {
  default void m() {
    System.out.println("a");
  }
}

interface IB extends IA {
  default void m() {
    // 调用 IA 的默认方法
    // 只能调用直接父接口的方法
    IA.super.m();
    System.out.println("b");
  }
}

public class InterfaceTest implements IB {

  public static void main(String[] args) {
    // 不允许使用 IA.super.m()
    // 可以使用 IB.super.m()
    new InterfaceTest().m();
  }
}

接口中使用静态方法

JDK8 开始,接口允许定义静态方法。静态方法的使用与在类中定义时相似,都不需要实例化即可调用。interface.staticMethod()
静态方法不能被继承,无论是子接口还是实现了该接口的类。

私有接口方法

JDK9 开始,接口允许定义私有方法。私有方法不能被继承,包括子接口。私有方法只能被同一个接口的默认方法和私有方法使用。

提供私有方法的目的是给其他方法提供通用的代码段,避免代码冗余。

参考

[1] Herbert Schildt, Java The Complete Reference 11th, 2019.
[2] 接口相关

 posted on 2024-04-18 15:02  x-yun  阅读(9)  评论(0编辑  收藏  举报