MyClass.class和初始化类的研究

对于MyClass.class和getClass()方法的一点疑惑,查了一些资料,也没有找到说的很清楚的,根据一些相关的资料和自己做的一点小实验,做了几点猜测,有什么不正确的地方希望大家指正。
对于一个类,MyClass.class返回的是一个java.lang.Class,也就是一个类的描述信息。但是并没有对类进行初始化,类的static fields也没有被调用,所以应该只是载入了类的变量和方法的信息。
运行以下的类,可以看到c1,c2和c3都是相等的,也就是类的信息在jvm中只会装载一次,这次的装载可能是在声明这个类的时候或者调用MyTest.class的时候.

public   class  Try1  {

 
public static void main(String args[])
 
{
  Class c1 
= Temp.class;
  Class c2 
= Temp.class;
    
  System.out.println(c1);
  System.out.println(c2);
  Class c3 
= new Temp().getClass();
  System.out.println(c3);
  
  System.out.println(c1.getName());
  System.out.println(c2.getName());
  System.out.println(c3.getName());
  
  System.out.println(
"c1=c2 "+(c1==c2));
  System.out.println(
"c1=c3 "+(c1==c3));
  System.out.println(
"c2=c3 "+(c2==c3)); 
  
  
 }

}


 

类在声明的时候并不会调用static fields和初始化static变量,以下的程序可以很容易看出.运行只会打印Hello world,不会打印Temp中其他信息.

 

public   class  MyTest  implements  Init
 
static Class t2 = Temp.class;
 
static Temp tt; //NOTICE 
 
 MyTest()
{}
 
public static void main(String[] args) {
  System.out.println(
"Hello,World!");
  
 }

}


public   class  Temp  {

 
public Temp(){
  System.out.println(
"==constrocts temp()==");
 }

 
static int ii = 8;
 
static {
  
int i = 100/0;
  System.out.println(
"==init temp()==");
  System.out.println(ii
+"in it");
 }

 
static Temp t = new Temp();
}


 

当访问一个static 变量,clinit方法会被调用,关于clinit和init方法,下面zz的一篇文章解释的很清楚,也是看到这篇文章受到的启发.

 

public   class  MyTest  implements  Init {
 
 
static Temp tt;
 
 
static {
  System.out.println(Temp.ii);
 }
 
 
//Temp t = new Temp();  //NOTICE HERE
 MyTest(){}
 
public static void main(String[] args) {
  System.out.println(
"Hello,World!");
  MyTest m 
= new MyTest();
  
//MyTest mm;
  
//System.out.println(MyTest.i);
  
//System.out.println(m.t1==m.t2);
  
 }

}

 

运行可以看到如下错误信息:
java.lang.ExceptionInInitializerError
 at MyTest.<clinit>(MyTest.java:12)
Caused by: java.lang.ArithmeticException: / by zero
 at Temp.<clinit>(Temp.java:12)
 ... 1 more
Exception in thread "main"

把刚刚注释掉的Temp t = new Temp()取消注释 ,然后把System.out.println(Temp.ii)注释掉,运行会发现如下的错误.

Hello,World!
Exception in thread "main" java.lang.ExceptionInInitializerError
 at MyTest.<init>(MyTest.java:16)
 at MyTest.main(MyTest.java:20)
Caused by: java.lang.ArithmeticException: / by zero
 at Temp.<clinit>(Temp.java:12)
 ... 2 more

 

 

public   class  Temp  {

 
public Temp(){
  System.out.println(
"==constrocts temp()==");
 }

 
static int ii = 8;
 
static {
 
// int i = 10/0;
  System.out.println("==init temp()==");
  System.out.println(ii
+"in it");
 }

 
//static Temp t = new Temp();
 Temp2 t2 = new Temp2();
}

public   class  Temp2  {
 
static {
  
int i = 100/0
 }

}

public   class  MyTest {
 
static 
  System.out.println(Temp.ii);  
 }

 MyTest()
{}
 
public static void main(String[] args) {
  System.out.println(
"Hello,World!");
  MyTest m 
= new MyTest();
  
 }

}



由此可以发现初始化一个变量调用的是init方法对类进行初始化,而访问static变量时,调用的是clinit方法对类初始化.
初步猜测类的加载由以下三个步骤构成:

声明或MyTest.class:   加载类的变量和方法名,获得类的基本信息.
clinit:   对类的static fields调用,初始化static变量.不会为非static变量赋值.
init:      对非static变量赋值,调用构造函数.

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值