JVM_类的加载、连接与初始化(三)

接口的初始化

*当一个接口在初始化时,并不是要求其父接口都完成了初始化。(但是实际中根本就没有加载类,哪来的舒适化...)

*当有在真正使用到父类接口时候(如使用了父类中的常量),才会被初始化。

接口中默认的属性就是public static final

这里了解下深度内存解析Java关键字:Static与Final

 调用继承父接口的子接口并且其中的常量时编译时确定的

上代码:

public class Test2 {
    public static void main(String[] args){
        System.out.println(Child2.a);
    }
}

interface Parent2{
    int a = 5;
}

interface Child2 extends Parent2{
    int b = 6;
}

截取部分以上类加载信息:

这里值加载了Test2,并没有加载两个接口。

 调用继承父接口的子接口并且其中的常量是运行时确定的

import java.util.Random;

import static staticpackage.PrintHelper.*;
public class Test2 {
    public static void main(String[] args){
        println(Child2.b);
    }
}

interface Parent2{
    int a = 6;
}

interface Child2 extends Parent2{
    int b = new Random().nextInt();
}

调用继承父接口的类

public class Test2 {
    public static void main(String[] args){
        System.out.println(Child2.b);
    }
}

interface Parent2{
    int a = 6;
}

class Child2 implements Parent2{
    static int b = 5;
}

被基础的子类有final修饰的数据其值编译时确定

public class Test2 {
    public static void main(String[] args){
        System.out.println(Child2.b);
    }
}

interface Parent2{
    int a = 6;
}

class Child2 implements Parent2{
    static final int b = 5;
}

被基础的子类有final修饰的数据其值运行时确定

import java.util.Random;

public class Test2 {
    public static void main(String[] args){
        System.out.println(Child2.b);
    }
}

interface Parent2{
    int a = 6;
}

class Child2 implements Parent2{
    static final int b = new Random().nextInt();
}

public class Test3 {
    //编译期常量指的就是程序在编译时就能确定这个常量的具体值
    //非编译期常量就是程序在运行时才能确定常量的值,因此也称为运行时常量
    //定义上来说,声明为final类型的基本类型或String类型并直接赋值(非运算)的变量就是编译期常量,即:
    public static void main(String[] args){
        System.out.println(Parent3.c);
    }

}
class Parent3{
    // 编译期常量
    final static int a = 3;
    final int b =3 ;
    // 运行期常量
    static int c = 3;
    int d = 3;
    // 运行期常量
    final static int f = new Integer(3);
    final int g = new Integer(3);
    // 运行期常量
    static int h = new Integer(3);
    int i = new Integer(3);
}

编译编译器常量:

Compiled from "Test3.java"
public class Test3 {
  public Test3();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: iconst_3      //由此可见该常量直接在Test3类的常量池中,与Paren3无关
       4: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
       7: return

 运行期间常量

Compiled from "Test3.java"
public class Test3 {
  public Test3();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: getstatic     #3                  // Field Parent3.c:I  //与Parent3有关
       6: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
       9: return
}

小结:

1.被final修饰的且其值编译时候就确定了的情况下,该类不会被加载。

2.被final修饰的且其值运时候就确定了的情况下,该类及其父类都会被加载,被加载并不等于初始化。

因此,一个父接口并不会因为他的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才会导致接口的初始化。

参考两篇文章:JVM常量池浅析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值