小言_互联网的博客

《java面试宝典》三 类初始化和类实例化顺序

427人阅读  评论(0)

前言

社长,一个爱学习,爱分享的程序猿,始终相信,付出总会有回报的。知识改变命运,学习成就未来。爱拼才会赢!
程序猿学社的GitHub,已整理成相关技术专刊,欢迎Star:
https://github.com/ITfqyd/cxyxs

社长,4年api搬运工程师,之前做的都是一些框架的搬运工作,做的时间越长,越发感觉自己技术越菜,有同感的社友,可以在下方留言。现侧重于java底层学习和算法结构学习,希望自己能改变这种现状。
为什么大厂面试,更侧重于java原理底层的提问,因为通过底层的提问,他能看出一个人的学习能力,看看这个人的可培养潜力。随着springboot的流行,大部分的开发,起步就是springboot。也不看看springboot为什么简单?他底层是如果实现的。为什么同样出来4年,工资差别都很大?这些问题都值得我们深思(对社长自己说的)。
api工程师,顶天了,最多达到某些公司中级工资上限,很难突破高级这道坎。希望我们大家成就更好的自己。回想起往事,不会后悔。

面试的时候,经常会遇到这样的笔试题:给你两个类的代码,它们之间是继承的,每个类中有一些静态方法,静态代码块,非静态代码块,静态变量。

面试官为什么要这样考?

实际上就是考察我们对类初始化基础知识的掌握情况。

对象初始化顺序:

1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
3.其次,初始化父类的普通成员变量和代码块,再执行父类的构造方法;
4.最后,初始化子类的普通成员变量和代码块,再执行子类的构造方法;

类初始化过程:

1.一个类初始化,实际上就是初始化<clinit>方法。
注意:<clinit>方法,可能不存在,需要有静态方法或者静态代码块。
2.一个子类要想初始化,需要先初始化他的父类。

类实例化过程:

类实例化就是初始化<init>方法

  1. 有几个构造方法,就有<init>方法
  2. 非静态方法和非静态代码块根据代码从上到下的顺序,依次执行。
  3. 构造器最后才调用

<clinit>方法,什么鬼?社长你在给我开玩笑吗?

在我们编写的代码中,不会存在这个方法,但是我们可以通过查看我们java文件对应的class可以发现是能找到这个方法的。

 

为了证明论证只有静态代码块或者静态方法才有<clinit>方法


  
  1. public  class Test1 {
  2.      private  int a= 1;
  3.      public static void main(String[] args) {
  4.     }
  5. }

 


作为一个Java开发者,对技术的追求而不仅仅停留在会用API,如果只是会用,那一辈子就是一个api程序猿,也就是大家所谓的搬砖的,我们应该深入底层,我们大家都知道我们编写的java文件,会编译成class文件,而又有多少人,去看过class文件长什么样子的。实际上class文件就是字节码文件,这涉及汇编的一些知识。后续,社长会整理出如何解析class字节码的相关文章。这里只是了解即可,知道有这么一回事。

 

 

难度系数:1 星


  
  1. package com.fyqd.test.classload;
  2. /**
  3.  * Description:动物园
  4.  * Author: 程序猿学社
  5.  * Date:  2020/1/14 9:35
  6.  * Modified By:
  7.  */
  8. public  class  Zoo {
  9.      public  static String staticPk = staticPk();
  10.      public String pk = pk();
  11.      static {
  12.         System. out.println( "父类静态代码块!");
  13.     }
  14.     {
  15.         System. out.println( "父类非静态代码块");
  16.     }
  17.      public static String staticPk({
  18.         System. out.println( "父类静态方法!");
  19.          return  "PK";
  20.     };
  21.      public  String pk({
  22.         System. out.println( "父类普通方法!");
  23.          return  "PK";
  24.     };
  25.      public Zoo({
  26.        System. out.println( "父类构造器");
  27.     }
  28. }

测试类


  
  1. public  class Main {
  2.      public static void main(String[] args) {
  3.         Zoo zoo=  new Zoo();
  4.     }
  5. }

各位社友觉得输出到控制台的结果应该是多少?

 


结论;我们可以发现运行的顺序排序 静态>非静态>结构。如果是属于同一个等级,例如静态方法和静态代码块,则根据代码的从上到下的顺序来执行。

 

难度系数:2 星


  
  1. package com.fyqd.test.classload;
  2. /**
  3.  * Description:动物园
  4.  * Author: 程序猿学社
  5.  * Date:  2020/1/14 9:35
  6.  * Modified By:
  7.  */
  8. public  class  Zoo {
  9.      public  static String staticPk = staticPk();
  10.      public String pk = pk();
  11.      static {
  12.         System. out.println( "父类静态代码块!");
  13.     }
  14.     {
  15.         System. out.println( "父类非静态代码块");
  16.     }
  17.      public static String staticPk({
  18.         System. out.println( "父类静态方法!");
  19.          return  "PK";
  20.     };
  21.      public  String pk({
  22.         System. out.println( "父类普通方法!");
  23.          return  "PK";
  24.     };
  25.      public Zoo({
  26.        System. out.println( "父类构造器");
  27.     }
  28. }
  29. package com.fyqd.test.classload;
  30. /**
  31.  * Description:  big
  32.  * Author: 程序猿学社
  33.  * Date:  2020/1/14 9:35
  34.  * Modified By:
  35.  */
  36. public  class  Pig  extends   Zoo{
  37.      public  static String staticPk = staticPk();
  38.      public String pk = pk();
  39.      static {
  40.         System. out.println( "子类静态代码块!");
  41.     }
  42.     {
  43.         System. out.println( "子类非静态代码块");
  44.     }
  45.      public static String staticPk({
  46.         System. out.println( "子类静态方法!");
  47.          return  "PK";
  48.     };
  49.      public  String pk({
  50.         System. out.println( "子类普通方法!");
  51.          return  "PK";
  52.     };
  53.      public Pig({
  54.         System. out.println( "子类构造器");
  55.     }
  56. }

测试类:


  
  1. package com.fyqd.test.classload;
  2. /**
  3.  * Description:
  4.  * Author: wude
  5.  * Date:  2020/1/14 9:55
  6.  * Modified By:
  7.  */
  8. public  class Main {
  9.      public static void main(String[] args) {
  10.         Pig pig =  new Pig();
  11.     }
  12. }

有一些社友反馈,社长之前出的题,太简单了,社长出了一道2星级别的题目,大家可以先不看答案,看看输出的控制台的结果是多少?能答对的社友,首先得恭喜下,从青铜,晋级到白银分段。

 


眼尖的社友,可能发现一个问题。
社长,社长,按你说的对象初始化顺序第三条,这里的打印应该是父类普通方法,父类非静态代码块才对。

 

 

社长跟大家说说,为什么会有这种问题出现?是谁在搞事情?

实际上是方法重写在搞事情,通过main方法,我们可以发现new的对象是子类,也就是说当前的this的指向就是子类。而这里本应该要调用父类的方法,由于被子类重写了,通过对象的多态性可知,这里打印的就是子类普通方法。

那些方法不能被重写?

final方法
静态方法
private修饰的方法。

难度3星 黄金段位


  
  1. package com.fyqd.test.classload;
  2. /**
  3.  * Description:  pig
  4.  * Author: 程序猿学社
  5.  * Date:  2020/1/14 9:35
  6.  * Modified By:
  7.  */
  8. public  class  Pig  extends   Zoo{
  9.      public  static String staticPk = staticPk();
  10.      public String pk = pk();
  11.      static {
  12.         System. out.println( "子类静态代码块!");
  13.     }
  14.     {
  15.         System. out.println( "子类非静态代码块");
  16.     }
  17.      public static String staticPk({
  18.         System. out.println( "子类静态方法!");
  19.          return  "PK";
  20.     };
  21.     @ Override
  22.      public  String  pk( ) {
  23.         System. out.println( "子类普通方法!");
  24.          return  "PK";
  25.     };
  26.      public Pig({
  27.         System. out.println( "子类构造器");
  28.     }
  29. }
  30. package com.fyqd.test.classload;
  31. /**
  32.  * Description:动物园
  33.  * Author: 程序猿学社
  34.  * Date:  2020/1/14 9:35
  35.  * Modified By:
  36.  */
  37. public  class  Zoo {
  38.      public  static String staticPk = staticPk();
  39.      public String pk = pk();
  40.      static {
  41.         System. out.println( "父类静态代码块!");
  42.     }
  43.     {
  44.         System. out.println( "父类非静态代码块");
  45.     }
  46.      public static String staticPk({
  47.         System. out.println( "父类静态方法!");
  48.          return  "PK";
  49.     };
  50.      public  String pk({
  51.         System. out.println( "父类普通方法!");
  52.          return  "PK";
  53.     };
  54.      public Zoo({
  55.        System. out.println( "父类构造器");
  56.     }
  57. }
  58. public  class  Main {
  59.      public static void main(String[] args{
  60.         Pig pig =  new Pig();
  61.         System. out.println( "---------");
  62.         pig =  new Pig();
  63.     }
  64. }

各位社友,再看看如上的代码,输出到控制台的结果应该是?

 

 

各位社友觉得这道理相对于前一道题,主要是考的那些方面?

实际上,就是考大家对类的初始化了解多少。实际上类初始化的时候,就会执行<clinit>方法,而<clinit>方法,就是通过静态代码块,静态变量,静态常量方法等组成。

后记

程序猿学社的GitHub,欢迎Star:
https://github.com/ITfqyd/cxyxs
觉得有用,可以点赞,关注,评论,留言四连发。

 


转载:https://blog.csdn.net/qq_16855077/article/details/103993794
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场