接口

  1. 接口是对行为的抽象,接口中的成员变量被隐性制定为public static final,方法被制定为public abstract。子类可以实现多个接口【多实现】。
  2. 多实现本质上是提高子类的扩展性,让子类可以实现更多功能的方法。
  3. 接口之间可以【多继承】。继承多个接口。类不可以多继承。
  4. 接口:对外暴露规则,功能扩展,降低耦合性,多实现。
  5. 多种类可以实现同一个接口,【多态的体现】。
  6. 注意:接口中可以有default方法,该方法有具体实现,不用被实现,可以参考iterable接口的源码。
  7. 抽象类和接口一旦被继承或实现,其中的所有抽象方法也必须都要被实现。否则,这个子类就是一个抽象类。

抽象类和接口的区别

语法层面的区别

  1. 抽象类可以有成员方法的实现细节,而接口只能存在抽象方法【java8中可以有default方法,是具体实现的方法】。
  2. 抽象类的成员变量可以是各种类型,但是接口中成员变量只能是public static final。
  3. 接口中不能含有静态代码块和静态方法(java8可以了),而抽象类可以有静态代码块和静态方法。
  4. 一个类只能继承一个抽象类,但却可以实现多个接口。

设计层面的区别

  1. 抽象类是对整个类整体进行抽象,包括属性,行为。但是接口是对类局部(行为)进行抽象。
  2. 抽象类作为很多子类的父类,他是一种模板式设计【BaseDAO<>里面就是四个具体实现增删改查的方法,这四个方法就是模板,供子类DAOImpl使用】,而接口是一种行为规范,规定了实现DAO的DAOImpl就得有增删改查的功能。
  3. 对于第二点的理解,举一个例子:DAOImpl继承BaseDAO并实现DAO。
  4. 继承是一个“是不是”的关系(共性关系),而接口实现则是“有没有”的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类【FruitDAOImpl是传入泛型Fruit的BaseDAO<>的一种】,而接口实现则是有没有、具不具备的关系。
  5. 第四点其实是考虑了这种情况:多个类继承同一个类,但是这些类都有相似的方法,可以将需要实现相似方法的一些类使用同一个接口。

静态变量

  1. 每个类一个,是固定值。(通常用在单例模式和常量【public static final】,因为静态变量在类加载时候就被实例化,而类只会被加载一次,所以可以用在单例模式)实例变量(属性),每个实例对象一个。
  2. 可以不同实例共享。
  3. 在类加载时候就被实例化。

类加载机制

  1. 虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。在 Java 语言中,类型的加载、连接和初始化过程都是在程序运行期间完成的。
  2. 类只会被加载一次,java中使用的是双亲委派机制,也就是加载过后,就不会再次被加载
  3. 静态代码块在类加载的时候执行,而且只执行一次(因为类只会加载一次)。一般用来对类初始化数据的定义。
    具体如下:
    1、调用静态变量和静态方法时会执行静态代码块 。
    2、创建对象时,静态代码块会执行。
  4. 静态代码块与静态方法是2个概念。“静态代码块,在类加载时可以执行,但不一定会执行,主要看有没有初始化”【加载了不一定初始化了】。而静态方法是不会随加载而自动执行的。
  5. 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。如果只是使用类的静态成员时,,普通代码块并不会执行。【类加载了,对象不一定创建了。】
  6. 那什么时候开始加载呢?不知道,虚拟机没有规定,但是却规定了初始化的时机【这时,肯定已经加载了】,有且只有以下 5 种情况必须对类进行初始化。
    1 、遇到 new, getstatic, putstatic, 或 invokestatic 这 4 条字节码指令时。对应的场景是使用 new 新建对象,读取或设置一个类的静态属性的时候,调用一个类的静态方法的时候。
    2 、使用 java.lang.reflect 包的方法对类进行反射调用的时候。
    3 、当初始化一个类的时候,首先初始化该类的父类。
    4 、当虚拟机启动时,虚拟机会先初始化包含 main 函数的主类。
    5 、当使用 JDK1.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果 REF_getStatic, REF_putStatic, REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。
  7. 在加载阶段,虚拟机需要完成 3 件事情。
    1 通过一个类的全限定名来获取此类的二进制字节流。
    2 将这个字节流所代表的【静态存储】转化为方法区的运行时数据结构。
    3 在内存中生成一个代表这个类的 Class 对象。