Java类加载的一道笔试题目

 
  1. class A {

  2. static {

  3. System.out.print("a");//只有在类加载时候会执行一次

  4. }

  5.  
  6. public A() {

  7. System.out.print("x");

  8. }

  9.  
  10. }

  11.  
  12. class B extends A {

  13. static {

  14. System.out.print("b");

  15. }

  16.  
  17. public B() {

  18. System.out.print("y");

  19. }

  20. }

  21.  
  22. public class Test {

  23.  
  24. public static void main(String[] args) {

  25.  
  26. A ab = new B();

  27. System.out.println();

  28. ab = new B();

  29.  
  30. }

  31.  
  32. }


输出:abxy   xy 

 

 

执行过程:

 

A ab = new B();

执行时候第一使用到A、B类,JVM发现没有加载A、B的信息,故先加载,由于B继承了A类,所以会先加载A再加载B,在加载的过程中会执行static块完成类的初始化。所以会先输出ab,此时创建B对象时候,会先执行A的构造方法在执行B的构造方法,故在输出xy,所以最后输出abxy

 

 

当执行:

 

ab = new B();

 

时候发现已经加载过A、B的字节码了,故不会再加载了,所以不会输出ab,直接输出xy即可

 

 

如果代码修改为:

 

 
  1. class A {

  2. static {

  3. System.out.print("a");// 只有在类加载时候会执行一次

  4. }

  5.  
  6. public A() {

  7. System.out.print("x");

  8. }

  9.  
  10. }

  11.  
  12. class B extends A {

  13. static {

  14. System.out.print("b");

  15. }

  16.  
  17. public B() {

  18. System.out.print("y");

  19. }

  20. }

  21.  
  22. public class Test {

  23.  
  24. public static void main(String[] args) {

  25.  
  26. B ab = new B(); // 由于A ab = new B()=> B ab = new B()

  27. System.out.println();

  28. ab = new B();

  29. }

  30. }


输出还是:

 

abxy
xy

 

当执行B ab = new B()时候,由于JVM事先就会知道B是继承至A的,所以需要先加载A,如果不先加载A的话,无法完成子类B的加载!所以类的加载顺序和构造器执行顺序一致,先父类再子类!

注意:容易糊涂的地方是,以为B ab =new B();以为创建B所以先加载B之后再加载A,这种理解就错误了,因为对于对象的创建是从父类开始的!

 

拓展:非静态代码块的执行顺序也是先父类,在子类!但是非静态代码块执行顺序在静态代码块之后,构造器之前!静态代码块只会执行一次(类加载时候执行),而非静态代码块会多在创建对象时候多次执行!

 

实践代码:

 

 
  1. class A {

  2. static {

  3. System.out.print("a");// 只有在类加载时候会执行一次

  4. }

  5.  
  6. {

  7. System.out.print("a-a");

  8. }

  9.  
  10. public A() {

  11. System.out.print("x");

  12. }

  13.  
  14. }

  15.  
  16. class B extends A {

  17. static {

  18. System.out.print("b");

  19. }

  20. {

  21. System.out.print("b-b");

  22. }

  23.  
  24. public B() {

  25. System.out.print("y");

  26. }

  27. }

  28.  
  29. public class Test {

  30.  
  31. public static void main(String[] args) {

  32.  
  33. B ab = new B(); // 由于A ab = new B()=> B ab = new B()

  34. System.out.println();

  35. ab = new B();

  36. }

  37. }


输出:

 

aba-axb-by
a-axb-by

 

 

 

如果两个类没有继承关系的话,类的加载顺序就是按照代码的执行顺序进行加载的。

 

 
  1. class C {

  2. static {

  3. System.out.print("c");

  4. }

  5.  
  6. public C() {

  7. System.out.print("x");

  8. }

  9.  
  10. }

  11.  
  12.  
  13. class D {

  14. static {

  15. System.out.print("d");

  16. }

  17.  
  18. public D() {

  19. System.out.print("y");

  20. }

  21.  
  22. }

  23.  
  24.  
  25. public class Test1 {

  26.  
  27. public static void main(String[] args) {

  28.  
  29. C c=new C();

  30. System.out.println();

  31. D d=new D();

  32.  
  33.  
  34. }

  35.  
  36. }


 

 

输出:

cx
dy

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值