接口
- 接口是对行为的抽象,接口中的成员变量被隐性制定为public static final,方法被制定为public abstract。子类可以实现多个接口【多实现】。
- 多实现本质上是提高子类的扩展性,让子类可以实现更多功能的方法。
- 接口之间可以【多继承】。继承多个接口。类不可以多继承。
- 接口:对外暴露规则,功能扩展,降低耦合性,多实现。
- 多种类可以实现同一个接口,【多态的体现】。
- 注意:接口中可以有default方法,该方法有具体实现,不用被实现,可以参考iterable接口的源码。
- 抽象类和接口一旦被继承或实现,其中的所有抽象方法也必须都要被实现。否则,这个子类就是一个抽象类。
抽象类和接口的区别
语法层面的区别
- 抽象类可以有成员方法的实现细节,而接口只能存在抽象方法【java8中可以有default方法,是具体实现的方法】。
- 抽象类的成员变量可以是各种类型,但是接口中成员变量只能是public static final。
- 接口中不能含有静态代码块和静态方法(java8可以了),而抽象类可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,但却可以实现多个接口。
设计层面的区别
- 抽象类是对整个类整体进行抽象,包括属性,行为。但是接口是对类局部(行为)进行抽象。
- 抽象类作为很多子类的父类,他是一种模板式设计【BaseDAO<>里面就是四个具体实现增删改查的方法,这四个方法就是模板,供子类DAOImpl使用】,而接口是一种行为规范,规定了实现DAO的DAOImpl就得有增删改查的功能。
- 对于第二点的理解,举一个例子:DAOImpl继承BaseDAO并实现DAO。
- 继承是一个“是不是”的关系(共性关系),而接口实现则是“有没有”的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类【FruitDAOImpl是传入泛型Fruit的BaseDAO<>的一种】,而接口实现则是有没有、具不具备的关系。
- 第四点其实是考虑了这种情况:多个类继承同一个类,但是这些类都有相似的方法,可以将需要实现相似方法的一些类使用同一个接口。
静态变量
- 每个类一个,是固定值。(通常用在单例模式和常量【public static final】,因为静态变量在类加载时候就被实例化,而类只会被加载一次,所以可以用在单例模式)实例变量(属性),每个实例对象一个。
- 可以不同实例共享。
- 在类加载时候就被实例化。
类加载机制
- 虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。在 Java 语言中,类型的加载、连接和初始化过程都是在程序运行期间完成的。
- 类只会被加载一次,java中使用的是双亲委派机制,也就是加载过后,就不会再次被加载
- 静态代码块在类加载的时候执行,而且只执行一次(因为类只会加载一次)。一般用来对类初始化数据的定义。
具体如下:
1、调用静态变量和静态方法时会执行静态代码块 。
2、创建对象时,静态代码块会执行。 - 静态代码块与静态方法是2个概念。“静态代码块,在类加载时可以执行,但不一定会执行,主要看有没有初始化”【加载了不一定初始化了】。而静态方法是不会随加载而自动执行的。
- 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。如果只是使用类的静态成员时,,普通代码块并不会执行。【类加载了,对象不一定创建了。】
- 那什么时候开始加载呢?不知道,虚拟机没有规定,但是却规定了初始化的时机【这时,肯定已经加载了】,有且只有以下 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 的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。 - 在加载阶段,虚拟机需要完成 3 件事情。
1 通过一个类的全限定名来获取此类的二进制字节流。
2 将这个字节流所代表的【静态存储】转化为方法区的运行时数据结构。
3 在内存中生成一个代表这个类的 Class 对象。