`
BradyZhu
  • 浏览: 245421 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

通过类字面常量解释接口常量为什么只能定义为static final,类加载过程---Thinking in java

 
阅读更多

曾经被一哥们问题个问题,为什么接口的常量只能定义为static final,我当时还说他一个接口你定义点方法就行了,还弄什么常量,不过话又说回来,我确实没有解决他的这个问题,以前看Thinking in java貌似解决了类初始化为对象的过程,今天看了一下CLass的类字节变量,感觉又明白许多,下面将代码贴上,逐个分析

package com.bird.thinking;

import java.util.Random;

/**
 * @use 探寻Java的Class类内幕
 * @author bird
 *
 */

class Initable{
	public static final int staticFinal = 47;//他的值不变
	public static final int staticFinal2 = //他的值是变化的
		ClassInitialization.rand.nextInt(1000);
	static {
		System.out.println("初始化 Initable");
	}
}

class Initable2{
	public static int stationNonFinal = 147;//注意没有final
	static{
		System.out.println("初始化 Initable2");
	}
}

class Initable3{
	public static int staticNonFinal = 74;
	static{
		System.out.println("初始化 Intiable3");
	}
}

public class ClassInitialization {
	public static Random rand = new Random(47);
	@SuppressWarnings("unchecked")
	public static void main(String [] args) throws ClassNotFoundException{
		@SuppressWarnings("unused")
		Class initable = Initable.class;//只是加载字节码进入虚拟机,获得引用没有初始化
		System.out.println("After creating Initable ref");
		System.out.println(Initable.staticFinal);//请求访问static final定值
		System.out.println(Initable.staticFinal2);//请求访问static final 为直接定义的值
		
		System.out.println(Initable2.stationNonFinal);//访问static的值
		
		@SuppressWarnings("unused")
		Class initable3 = Class.forName("com.bird.thinking.Initable3");//装载并且初始化
		System.out.println("After creating Initable3 ref");
		System.out.println(Initable3.staticNonFinal);
	}
}

运行结果如下

After creating Initable ref
47
初始化 Initable
258
初始化 Initable2
147
初始化 Intiable3
After creating Initable3 ref
74


1.首先说一下第39行,他的意思是仅仅使用Class的方法将


Initable.java的字节码装载到虚拟机中,得到对类的引用,并不初


始化类,更不可能执行static代码块


2.加载完字节码后,直接访问Initable的static final常量,没有任何


问题,说明虽然类没有被初始化,但是static final常量已经可以被


访问(这个是解释接口的重点)



3.当访问Initable的在编译时候没有指定值的static final常量的时


候,他就不能直接访问,看运行结果可知道,他需要初始化类,


即调用static静态代码块,才可以使用.



4.当调用Initable2的static变量的时候,类就必须被执行初始化才能


被访问

5.当调用Class.Forname()方法的时候,将类装载进入虚拟机,就


果断执行了static代码块,初始化后才能继续访问.



6.因此总结一下,一个类的初始化准备工作如下


6.1加载:这个由类加载器完成,他去查找字节码,并且创建一个


Class对象


6.2连接:验证类中的字节码,为静态域分配存储空间,并且如果


必须的话,将解析这个类创建的对其他类的引用


6.3初始化:如果这个类有超类,则对其进行初始化,执行静态初


始化器和静态初始化代码块


6.4初始化被延迟到了对静态方法(构造器是隐士的静态方法)或


非静态方法的首次引用才执行


7.由上面可以知道,接口不能被初始化,如果想定义常量,必须是


在接口的字节码被装载到虚拟机的时候他的常量就得被访问,所

以他必须是static final的


8static final叫编译期常量,不需要初始化就能读取。

分享到:
评论

相关推荐

    2023-04-06-项目笔记-第一阶段-课前小分享 4.5.1 字面常量

    2023-04-06-项目笔记-第一...写代码注意代码风格 4.3.1 变量的使用 4.4 变量的作用域与生命周期 4.4.1 局部变量的作用域 4.4.2 全局变量的作用域 4.4.3 局部变量的生命周期 4.4.4 全局变量的生命周期 4.5.1 字面常量

    JAVA常量

    常量值又称为字面常量,它是通过数据直接表示的,因此有很多种数据类型,像整型和字符串型等。下面一一介绍这些常量值。 (二)分类 《1》整型常量值 Java 的整型常量值主要有如下 3 种形式。 十进制数形式【……】 ...

    JVM常量池教程吐血整理干货.md

    运行时常量池是在类加载阶段,将class二进制数据加载到内存, 并将数据保存到方法区,其中class文件中的常量池将保存到 运行时常量池(数据都在方法区,常量池肯定也在方法区)。 也就是说一个Class文件常量池对应一个...

    java中常量以及常量池

    1、举例说明 变量 常量 字面量  1 int a=10;  2 float b=1.234f;  3 String c="abc";  4 final long d=10L;  a,b,c为变量,d为常量 两者都是左值;10,1.234f,"abc",10L都是字面量;  2、常量池: ...

    2023-04-06-项目笔记-第一阶段-4.5.3 #define 定义的标识符常量

    2023-04-06-项目笔记-第一阶段-4.3.1 变量的使用 4.4 变量的作用域与生命周期 4.4.1 局部变量的作用域 4.4.2 全局变量的作用域 4.4.3 局部变量的生命周期 4.4.4 全局变量的生命周期 4.5.1 字面常量 4.5.2 const 修饰...

    Kotlin 1.3 基础课程第三章 数据类型字面常量及下

    Kotlin 1.3 基础课程第三章 数据类型字面常量及下划线表示

    java-7-openjdk-amd64.tar.gz

    但如果仅从“开源”字面意义(开放可阅读的源码)上看,其实Sun自JDK 1.5之后就开始以Java Research License(JRL)的形式公布过Java源码,主要用于研究人员阅读(JRL许可证的开放源码至JDK 1.6 Update 23为止)。...

    Java-study 自学复习笔记.rar

    注释是程序中用来解释代码的文本,它不会被编译器识别为代码。Java中有三种注释方式:单行注释、多行注释和文档注释。单行注释以“//”开头,多行注释以“/*”开头,“*/”结尾,文档注释以“/**”k开头,“*/”...

    JAVA解惑.pdf

    Java 谜题 谜题 20:我的类是什么? 下面的程序被设计用来打印它的类文件的名称。如果你不熟悉类字面常量,那么 我告诉你 Me.class.getName()将返回 Me 类完整的名称,即 “com.javapuzzlers.Me”。那么,这个程序...

    2023-04-06-项目笔记-第一阶段-4.5.4 枚举常量

    2023-04-06-项目笔记-第一阶段-4.3.1 变量的使用 4.4 变量的作用域与生命周期 4.4.1 局部变量的作用域 4.4.2 全局变量的作用域 4.4.3 局部变量的生命周期 4.4.4 全局变量的生命周期 4.5.1 字面常量 4.5.2 const 修饰...

    Java常见面试问题整理.docx

    2.方法区(元空间):方法区用于存储已被虚拟机加载的类信息、常量、静态变量,如static修饰的变量加载类的时候就被加载到方法区中。运行时常量池是方法区的一部分,class文件除了有类的字段、接口、方法等描述信息...

    Java同步机制浅谈

    Java 对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized 关键 字就可以轻松地解决多线程共享数据同步问题。...object reference(对象引用)、static 函数和class literals(类名称字面常量)身上。

    java深入解析

    103 话题18 一成不变——不可修改的String对象 107 话题19 钩深索隐——String字符最大长度的探索 111 话题20 追本溯源——追寻String字面常量的“极限” 116 话题21 旧调重弹——再论equals方法与“==”的 区别 ...

    Java之词义相似度计算(语义识别、词语情感趋势、词林相似度、拼音相似度、概念相似度、字面相似度)

    Java之词义相似度计算(语义识别、词语情感趋势、词林相似度、拼音相似度、概念相似度、字面相似度)

    Java中的字符串常量池详细介绍

    主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池,需要的朋友可以参考下

    详解C++中常量的类型与定义

    常量就像是常规的变量,只不过常量的值在定义后不能进行修改。 整数常量 整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。 整数常量...

    跟我一起学C++

    为什么要学习C++ 编程语言的需求总结为四个:效率(efficiency),灵活(flexibility),抽象(abstraction),生产力(productivity)。C语言注重前两者,C++注重前三者,JAVA、.net这些注重后两者。 2 从C到C++(一) 2.1 ...

    深入解析Java编程中final关键字的作用

    final关键字正如其字面意思一样,意味着最后,比如被final修饰后类不能集成、变量不能被再赋值等,以下我们就来深入解析Java编程中final关键字的作用:

    局部全局常量2019 07 121

    (1)字面常量 : (2)const 修饰的“常变量”: (3)#define 定义的标识符常量 (4)枚举常量

    Java synchronized详细解读.docx

    如果 再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。 无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而...

Global site tag (gtag.js) - Google Analytics