java的初始化块、静态初始化块、构造函数的执行顺序

LangChain实战:用FAISS搭建本地文档问答系统(含Word文件处理避坑指南) 本文详细介绍了如何利用LangChain框架和FAISS向量数据库构建本地化智能文档问答系统,特别针对Word文档处理中的技术难点提供实用解决方案。通过模块化设计、本地化支持和多格式兼容,实现高效文档处理与精准问答,满足企业对数据隐私和安全的需求。 阅读详情
<span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念。下面探究一下它的执行顺序与可能的用途。</span></p>
<h3><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">执行顺序</span></h3>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  首先定义A, B, C三个类用作测试,其中B继承了A,C又继承了B,并分别给它们加上静态初始化块、非静态初始化块和构造函数,里面都是一句简单的输出。</span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  主类Main里面也如法炮制。</span></p>
<div class="cnblogs_code" onclick="cnblogs_code_show('569f199d-483b-44d7-8c22-9728510ac299')"><img id="code_img_closed_569f199d-483b-44d7-8c22-9728510ac299" class="code_img_closed" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_569f199d-483b-44d7-8c22-9728510ac299" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('569f199d-483b-44d7-8c22-9728510ac299',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_569f199d-483b-44d7-8c22-9728510ac299" class="cnblogs_code_hide">
<pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> A {
</span><span style="color: #008080;"> 2</span>     <span style="color: #0000ff;">static</span><span style="color: #000000;"> {
</span><span style="color: #008080;"> 3</span>         System.out.println("Static init A."<span style="color: #000000;">);
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">    }
</span><span style="color: #008080;"> 5</span> 
<span style="color: #008080;"> 6</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 7</span>         System.out.println("Instance init A."<span style="color: #000000;">);
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    }
</span><span style="color: #008080;"> 9</span> 
<span style="color: #008080;">10</span> <span style="color: #000000;">    A() {
</span><span style="color: #008080;">11</span>         System.out.println("Constructor A."<span style="color: #000000;">);
</span><span style="color: #008080;">12</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">13</span> <span style="color: #000000;">}
</span><span style="color: #008080;">14</span> 
<span style="color: #008080;">15</span> <span style="color: #0000ff;">class</span> B <span style="color: #0000ff;">extends</span><span style="color: #000000;"> A {
</span><span style="color: #008080;">16</span>     <span style="color: #0000ff;">static</span><span style="color: #000000;"> {
</span><span style="color: #008080;">17</span>         System.out.println("Static init B."<span style="color: #000000;">);
</span><span style="color: #008080;">18</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">19</span> 
<span style="color: #008080;">20</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">21</span>         System.out.println("Instance init B."<span style="color: #000000;">);
</span><span style="color: #008080;">22</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">23</span> 
<span style="color: #008080;">24</span> <span style="color: #000000;">    B() {
</span><span style="color: #008080;">25</span>         System.out.println("Constructor B."<span style="color: #000000;">);
</span><span style="color: #008080;">26</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">27</span> <span style="color: #000000;">}
</span><span style="color: #008080;">28</span> 
<span style="color: #008080;">29</span> <span style="color: #0000ff;">class</span> C <span style="color: #0000ff;">extends</span><span style="color: #000000;"> B {
</span><span style="color: #008080;">30</span> 
<span style="color: #008080;">31</span>     <span style="color: #0000ff;">static</span><span style="color: #000000;"> {
</span><span style="color: #008080;">32</span>         System.out.println("Static init C."<span style="color: #000000;">);
</span><span style="color: #008080;">33</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">34</span> 
<span style="color: #008080;">35</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">36</span>         System.out.println("Instance init C."<span style="color: #000000;">);
</span><span style="color: #008080;">37</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">38</span> 
<span style="color: #008080;">39</span> <span style="color: #000000;">    C() {
</span><span style="color: #008080;">40</span>         System.out.println("Constructor C."<span style="color: #000000;">);
</span><span style="color: #008080;">41</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">42</span> <span style="color: #000000;">}
</span><span style="color: #008080;">43</span> 
<span style="color: #008080;">44</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Main {
</span><span style="color: #008080;">45</span> 
<span style="color: #008080;">46</span>     <span style="color: #0000ff;">static</span><span style="color: #000000;"> {
</span><span style="color: #008080;">47</span>         System.out.println("Static init Main."<span style="color: #000000;">);
</span><span style="color: #008080;">48</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">49</span> 
<span style="color: #008080;">50</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">51</span>         System.out.println("Instance init Main."<span style="color: #000000;">);
</span><span style="color: #008080;">52</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">53</span> 
<span style="color: #008080;">54</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> Main() {
</span><span style="color: #008080;">55</span>         System.out.println("Constructor Main."<span style="color: #000000;">);
</span><span style="color: #008080;">56</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">57</span> 
<span style="color: #008080;">58</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
</span><span style="color: #008080;">59</span>         C c = <span style="color: #0000ff;">new</span><span style="color: #000000;"> C();
</span><span style="color: #008080;">60</span>         <span style="color: #008000;">//</span><span style="color: #008000;">B b = new B();</span>
<span style="color: #008080;">61</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">62</span> }</pre>
</div>
<span class="cnblogs_code_collapse">测试代码</span></div>
<p>&nbsp;</p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  当然这里不使用内部类,因为内部类不能使用静态的定义;而用静态内部类就失去了一般性。</span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  那么可以看到,当程序进入了main函数,并创建了一个类C的对象之后,输出是这样子的:</span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div>
<pre>Static init Main.
Static init A.
Static init B.
Static init C.
Instance init A.
Constructor A.
Instance init B.
Constructor B.
Instance init C.
Constructor C.</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div>
<p>&nbsp;</p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  观察上面的输出,可以观察到两个有趣的现象:</span></p>
<ol>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">Main类是肯定没有被实例化过的,但是由于执行main入口函数用到了Main类,于是static初始化块也被执行了;</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">所有的静态初始化块都优先执行,其次才是非静态的初始化块和构造函数,它们的执行顺序是:</span></li>
<ol>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">父类的静态初始化块</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">子类的静态初始化块</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">父类的初始化块</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">父类的构造函数</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">子类的初始化块</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">子类的构造函数</span></li>
</ol></ol>
<p><span style="font-family: 'Microsoft YaHei';"><span style="font-size: 16px; line-height: 24px;">  那么如果有多个实例化对象,又会不会发生变化呢?于是在第一个C类的对象后面,再实例化一个B类的对象,再观察输出:</span></span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div>
<pre>Static init Main.
Static init A.
Static init B.
Static init C.
Instance init A.
Constructor A.
Instance init B.
Constructor B.
Instance init C.
Constructor C.
Instance init A.
Constructor A.
Instance init B.
Constructor B.</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div>
<p>&nbsp;</p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  可以发现这输出跟前面的基本长得一样对吧?只是在后面多了4行,那是新的B类对象实例化时产生的信息,同样也是父类A的初始化块和构造函数先执行,再轮到子类B的初始化块和构造函数执行;同时还发现,静态初始化块的输出只出现了一次,也就是说每个类的静态初始化块都只在第一次实例化该类对象时执行一次。</span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  无论如何,初始化块和构造函数总在一起执行是件有趣的事情,让我们反编译一下看看吧!</span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  查看生成目录发现已经生成了4个.class文件,分别是A.class, B.class, C.class, Main.class,先看看Main.class的结构(这里重新注释了new B):</span></p>
<div class="cnblogs_code">
<pre><span style="color: #008080;">1</span> javap -c Main</pre>
</div>
<div class="cnblogs_code" onclick="cnblogs_code_show('03b903ac-5e54-4294-8c77-60be2b898fac')"><img id="code_img_closed_03b903ac-5e54-4294-8c77-60be2b898fac" class="code_img_closed" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_03b903ac-5e54-4294-8c77-60be2b898fac" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('03b903ac-5e54-4294-8c77-60be2b898fac',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_03b903ac-5e54-4294-8c77-60be2b898fac" class="cnblogs_code_hide">
<pre><span style="color: #008080;"> 1</span> Compiled from <span style="color: #800000;">"</span><span style="color: #800000;">Main.java</span><span style="color: #800000;">"</span>
<span style="color: #008080;"> 2</span> <span style="color: #000000;">public class Main {
</span><span style="color: #008080;"> 3</span> <span style="color: #000000;">  public Main();
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">    Code:
</span><span style="color: #008080;"> 5</span>        <span style="color: #800080;">0</span><span style="color: #000000;">: aload_0
</span><span style="color: #008080;"> 6</span>        <span style="color: #800080;">1</span>: invokespecial #<span style="color: #800080;">1</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Method java/lang/Object."&lt;init&gt;":()V</span>
<span style="color: #008080;"> 7</span>        <span style="color: #800080;">4</span>: getstatic     #<span style="color: #800080;">2</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Field java/lang/System.out:Ljava/io/PrintStream;</span>
<span style="color: #008080;"> 8</span>        <span style="color: #800080;">7</span>: ldc           #<span style="color: #800080;">3</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> String Instance init Main.</span>
<span style="color: #008080;"> 9</span>        <span style="color: #800080;">9</span>: invokevirtual #<span style="color: #800080;">4</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Method java/io/PrintStream.println:(Ljava/lang/String;)V</span>
<span style="color: #008080;">10</span>       <span style="color: #800080;">12</span>: getstatic     #<span style="color: #800080;">2</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Field java/lang/System.out:Ljava/io/PrintStream;</span>
<span style="color: #008080;">11</span>       <span style="color: #800080;">15</span>: ldc           #<span style="color: #800080;">5</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> String Constructor Main.</span>
<span style="color: #008080;">12</span>       <span style="color: #800080;">17</span>: invokevirtual #<span style="color: #800080;">4</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Method java/io/PrintStream.println:(Ljava/lang/String;)V</span>
<span style="color: #008080;">13</span>       <span style="color: #800080;">20</span><span style="color: #000000;">: return
</span><span style="color: #008080;">14</span> 
<span style="color: #008080;">15</span> <span style="color: #000000;">  public static void main(java.lang.String[]);
</span><span style="color: #008080;">16</span> <span style="color: #000000;">    Code:
</span><span style="color: #008080;">17</span>        <span style="color: #800080;">0</span>: new           #<span style="color: #800080;">6</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> class C</span>
<span style="color: #008080;">18</span>        <span style="color: #800080;">3</span><span style="color: #000000;">: dup
</span><span style="color: #008080;">19</span>        <span style="color: #800080;">4</span>: invokespecial #<span style="color: #800080;">7</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Method C."&lt;init&gt;":()V</span>
<span style="color: #008080;">20</span>        <span style="color: #800080;">7</span><span style="color: #000000;">: astore_1
</span><span style="color: #008080;">21</span>        <span style="color: #800080;">8</span><span style="color: #000000;">: return
</span><span style="color: #008080;">22</span> 
<span style="color: #008080;">23</span> <span style="color: #000000;">  static {};
</span><span style="color: #008080;">24</span> <span style="color: #000000;">    Code:
</span><span style="color: #008080;">25</span>        <span style="color: #800080;">0</span>: getstatic     #<span style="color: #800080;">2</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Field java/lang/System.out:Ljava/io/PrintStream;</span>
<span style="color: #008080;">26</span>        <span style="color: #800080;">3</span>: ldc           #<span style="color: #800080;">8</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> String Static init Main.</span>
<span style="color: #008080;">27</span>        <span style="color: #800080;">5</span>: invokevirtual #<span style="color: #800080;">4</span>                  <span style="color: #008000;">//</span><span style="color: #008000;"> Method java/io/PrintStream.println:(Ljava/lang/String;)V</span>
<span style="color: #008080;">28</span>        <span style="color: #800080;">8</span><span style="color: #000000;">: return
</span><span style="color: #008080;">29</span> }</pre>
</div>
<span class="cnblogs_code_collapse">Main.class的反编译结果</span></div>
<p>&nbsp;</p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  可以看到整个Main类被分成三个部分,static {}部分很显然,就是我们的static初始化块,在里面调用了println并输出了String“Static init Main.”;而main入口函数也很清晰,首先新实例化了一个类C的对象,然后调用了类C的构造函数,最后返回;而上面public Main();的部分就很有意思了,这是类Main的构造函数,但我们看到里面调用了两次println,分别输出了String“Instance init Main.”和String“Constructor Main.”。难道初始化块和构造函数被合并到一起了?</span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  我们再看看C类的反编译结果吧:</span></p>
<div class="cnblogs_code">
<pre><span style="color: #008080;">1</span> javap -c C</pre>
</div>
<div class="cnblogs_code" onclick="cnblogs_code_show('d5b28da1-f393-4afc-87af-f6175e29e926')"><img id="code_img_closed_d5b28da1-f393-4afc-87af-f6175e29e926" class="code_img_closed" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_d5b28da1-f393-4afc-87af-f6175e29e926" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('d5b28da1-f393-4afc-87af-f6175e29e926',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_d5b28da1-f393-4afc-87af-f6175e29e926" class="cnblogs_code_hide">
<pre>Compiled from "Main.java"
class C extends B {
  C();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method B."&lt;init&gt;":()V
       4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: ldc           #3                  // String Instance init C.
       9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      12: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      15: ldc           #5                  // String Constructor C.
      17: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      20: return

  static {};
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #6                  // String Static init C.
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}</pre>
</div>
<span class="cnblogs_code_collapse">C.class的反编译结果</span></div>
<p>&nbsp;</p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  静态初始化块仍然单独分出一部分,输出了我们的调试语句。而另一部分,仍然还是类C的构造函数C();,可以看到它先调用了父类B的构造函数,接着输出了我们初始化块中的语句,然后才输出我们写在构造函数中的语句,最后返回。多次试验也都是如此。于是我们能够推断:初始化块的代码是被加入到子类构造函数的前面,父类初始化的后面了。</span></p>
<p>&nbsp;</p>
<h3><span style="font-family: 'Microsoft YaHei';"><span style="font-size: 16px; line-height: 24px;">可能的用途:</span></span></h3>
<p><span style="font-family: 'Microsoft YaHei';"><span style="font-size: 16px; line-height: 24px;">  既然执行顺序和大概原理都摸清了,那么就要探讨一下初始化块的可能的用途。</span></span></p>
<h5><span style="font-family: 'Microsoft YaHei';"><span style="font-size: 16px; line-height: 24px;"> 静态初始化块</span></span></h5>
<p><span style="font-family: 'Microsoft YaHei';"><span style="font-size: 16px; line-height: 24px;">  1. &nbsp;用于初始化静态成员变量<br></span></span></p>
<p><span style="font-family: 'Microsoft YaHei';"><span style="font-size: 16px; line-height: 24px;">  比如给类C增加一个静态成员变量sub,我们在static块里面给它赋值为5:</span></span></p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div>
<pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span> C <span style="color: #0000ff;">extends</span><span style="color: #000000;"> B {
</span><span style="color: #008080;"> 2</span> 
<span style="color: #008080;"> 3</span>     <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> a;
</span><span style="color: #008080;"> 4</span> 
<span style="color: #008080;"> 5</span>     <span style="color: #0000ff;">static</span><span style="color: #000000;"> {
</span><span style="color: #008080;"> 6</span>         a = 5<span style="color: #000000;">;
</span><span style="color: #008080;"> 7</span>         System.out.println("Static init C."<span style="color: #000000;">);
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    }
</span><span style="color: #008080;"> 9</span> 
<span style="color: #008080;">10</span> <span style="color: #000000;">......
</span><span style="color: #008080;">11</span> 
<span style="color: #008080;">12</span> }</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  main函数里输出这个静态变量C.sub:</span></p>
<div class="cnblogs_code">
<pre><span style="color: #008080;">1</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
</span><span style="color: #008080;">2</span>     System.out.println("Value of C.sub: " +<span style="color: #000000;"> C.sub);
</span><span style="color: #008080;">3</span> }</pre>
</div>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  则输出结果:</span></p>
<div class="cnblogs_code">
<pre>Static init Main.
Static init A.
Static init B.
Static init C.
Value of C.sub: 5</pre>
</div>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  符合类被第一次加载时执行静态初始化块的结论,且C.sub被正确赋值为5并输出了出来。</span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  但是乍一看似乎没有什么用,因为静态成员变量在定义时就可以顺便赋值了。因此在赋值方面有点鸡肋。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  2. &nbsp;执行初始化代码<br></span></p>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  比如可以记录第一次访问类的日志,或方便单例模式的初始化等。对于单例模式,可以先用static块初始化一些可能还被其他类访问的基础参数,等到真正需要加载大量资源的时候(getInstance)再构造单体,在构造函数中加载资源。</span></p>
<p>&nbsp;</p>
<h5><span style="font-family: 'Microsoft YaHei'; font-size: 16px;"> 非静态初始化块</span></h5>
<p><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">  这个就没什么好说的了,基本跟构造函数一个功能,但比构造函数先执行。最常见的用法应该还是<strong>代码复用</strong>,即多个重载构造函数都有若干段相同的代码,那么可以把这些重复的代码拉出来放到初始化块中,但仍然要注意它的执行顺序,对顺序有严格要求的初始化代码就不适合使用了。</span></p>
<p>&nbsp;</p>
<h3><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">总结:</span>&nbsp;</h3>
<ol>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">静态初始化块的优先级最高,也就是最先执行,并且仅在<strong>类第一次被加载时</strong>执行;</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">非静态初始化块和构造函数后执行,并且在<strong>每次生成对象时</strong>执行一次;</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">非静态初<strong>始化块的代码会在类构造函数之前执行</strong>。因此若要使用,应当养成把初始化块写在构造函数之前的习惯,便于调试;</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">静态初始化块既可以用于<strong>初始化静态成员变量</strong>,也可以<strong>执行初始化代码</strong>;</span></li>
<li><span style="font-family: 'Microsoft YaHei'; font-size: 16px;">非静态初始化块可以针对多个重载构造函数进行<strong>代码复用</strong>。</span>
参考 http://www.cnblogs.com/BlackStorm/p/5699965.html
从零构建2.4G无线通信系统:MSPM0G3507与NRF24L01的深度协同设计 本文详细介绍了基于MSPM0G3507微控制器与NRF24L01射频模块构建2.4G无线通信系统的深度协同设计方案。内容涵盖系统架构、SPI通信优化、功耗管理、抗干扰机制及中断/DMA高效利用,为工业物联网应用提供高可靠、低功耗的无线传输解决方案。 阅读详情

相关推荐

气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型

本文通过建立不同类型干旱传播过程的触发阈值模型,解析了在不同等级气象干旱胁迫下诱发次一级干旱类型的触发阈值。通过贝叶斯概率模型,我们推导了气象干旱与水文干旱、农业干旱、地下水干旱之间的条件概率关系,进一步明确了气象干旱引发水文干旱、农业干旱和地下水干旱的概率及其触发阈值。该模型有效揭示了气象干旱对各级干旱类型的传播机制及其动态变化,为干旱预警系统的建立和水资源管理提供了理论依据和技术支持。

frankgis的博客 2503

Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究

  Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念。下面探究一下它的执行顺序与可能的用途。 执行顺序   首先定义A, B, C三个类用作测试,其中B继承了A,C又继承了B,并分别给它们加上静态初始化块、非静态初始化块和构造函数,里面都是一句简单的输出。   主类Main里面也如法炮制。 1...

weixin_30830327的博客 228

AI产品经理必备:Agent评测维度、指标与工程化落地指南

随着大模型从单轮问答走向复杂的Agent应用,如何科学地评测一个Agent是否真正“办成了事”,成为AI产品经理必须掌握的核心能力。与传统大模型评测关注回答质量不同,Agent评测需要综合评估任务规划、工具调用、多轮对话一致性以及失败自愈等行为。任务完成率与工具调用成功率是最关键的两个量化指标,同时还需关注延迟与Token成本等工程约束。在实际落地中,评测集的设计要覆盖业务主流程与边界场景,并通过批量回归测试与版本对比,为产品选型、算法迭代和上线决策提供数据支持。本文系统拆解了Agent评测的完整流程,帮助

weixin_29057163的博客 344

浅谈 JAVA中静态初始化块和非静态初始化块的区别

众所周知在JAVA编程语言中有两种初始化块: 静态初始化块非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别 静态初始化块 定义:         static{} 执行优先级高于非静态的初始化块,它会在对象装载到系统的时候执行一次,执行完成便销毁,它仅能初始化类变量,即static修饰的数据成员。 执行优先级:1 非静态初始化块

技术成就梦想 8558

CST-Python(Pycharm如何与CST联合仿真,获取S参数)

我们想使用Python与CST联合仿真,其实是不需要自己下载Python的,因为CST在下载的时候就自带了Python3.6,我们只需要找到并将软件的环境设置到相应位置,即可联合仿真。(我的保存路径为D:\Program Files (x86)\CST Studio Suite 2020,在寻找时可以将前面切换成自己的保存路径,后面不需要修改)在CST帮助文档(打开CST软件,按F11即可直接访问帮助文档)里面,进行如下操作,便可以看到CST适配的Python版本为Python3.6!

weixin_52696285的博客 5649

ConnectionResetError 10054 根因分析与全链路防御指南

ConnectionResetError(错误码10054)是TCP协议中服务端主动发送RST包导致的强制断连,本质并非网络连接失败,而是服务端基于空闲超时、连接满载、TLS协商失败等策略做出的确定性终止决策。理解其底层原理有助于跳出‘重试’误区,转向连接生命周期管理。该错误高频出现在HTTP长连接、WebSocket、第三方API对接等场景,尤其在Nginx反向代理、负载均衡器(如AWS ALB)、WAF设备及内核conntrack机制下极易触发。本文结合Wireshark抓包分析、客户端心跳保鲜、协议指

weixin_30225755的博客 638

静态初始块和非静态初始块有什么区别?

静态初始块和非静态初始块有什么区别? 非静态初始块主要用于对象的初始化操作,在每一次创建对象时都要调用一次,其执行顺序在构造方法之前。 如果初始化块前有static关键字修饰,那么该初始块称为静态初始块。由于非静态成员不能再静态方法中使用,同样也不能在静态初始块中,因此,静态初始块主要用于初始化静态变量和静态方法。静态初始块只调用一次,是在类被第一次加载到内存时,并非一定要创建对象才执行。 静态初...

YEEZY_H的博客 1964

RK3588 buildroot 双网口bonding调试

本文介绍了Rockchip Buildroot中配置网络冗余的方法,通过bonding技术将多个物理网口合并为逻辑接口。主要内容包括:1)7种常见bonding模式的特点及适用场景;2)RK3588的具体配置流程,包括内核配置(启用bonding驱动、修改dts)、添加ifenslave工具;3)系统编译和网络状态检查。

501846585_QQAndroid_java 459

Java初始化中静态初始化块,非静态初始化块,构造器执行顺序

静态初始化块 和 非静态初始化块 在什么时候执行? 静态初始化块:当类第一次加载时执行。创建子类型的对象时,也会导致父类型的静态初始化模块的执行。 非静态初始化块(普通初始化块):非静态初始化块会在构造函数执行时,且在构造函数主体代码执行之前被执行。 他们的区别: 1、执行次数不同 静态块只执行一次,初始化块可以执行多次。 2、作用不同 静态初始化块仅能初始化类变量,即static修饰的数据成员。 非静态初始化块可以初始化类的实例变量。 执行顺序 执行两次Leaf()来看下,在Java中执行的顺序。 p

kevin的博客 309

【unity小技巧】委托(Delegate)的基础使用和介绍

在Unity中,委托(Delegate)是一种用于处理方法回调的特殊类型。它允许您将方法作为参数传递给其他方法,并在需要时调用这些方法。委托在游戏开发中非常有用,特别是在事件处理、消息传递和异步操作方面。它提供了一种灵活的方式来注册和触发方法,而无需显式地知道这些方法的实现细节。个人理解:可以把委托理解为一个容器,容器里面放可以放很多函数方法。一调用委托,里面所有的函数方法都会同步被执行。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 7239

【ARMv8 异常模型入门及渐进7 - GIC及安全中断介绍】

GIC-v3中,引入了支持2种安全状态(secure state),也就是对于中断,根据secure状态,分为安全中断和非安全中断。当然也可以只支持一种安全状态。这里的2种安全状态和1种安全状态,主要是影响中断分组,所使用IRQ和FIQ管脚的映射,以及gic中的寄存器访问。

CodingCos的博客 2116

静态初始化器与构造方法的区别

总结这两种的区别: 第一点从’对象‘出发 构造方法:对新创建的对象进行初始化 静态初始化器:对类自身初始化 第二点从执行的状态 构造方法:使用new 运算符 创建新的对象 系统自动执行 静态初始化器:不能由程序调用,所属的类被加载到内存时,系统调用 第三点从执行次数 构造方法:使用new运算符创建多少个对象,就调用多少次 静态初始化器:在该类被加载时,就执行一次。与对象无关 最后静态初始化器不是方...

weixin_44168259的博客 1320

PoE 的三大国际标准:PoE、PoE+、PoE++

很多人知道 PoE 能“一根网线,既供电又传数据”,但鲜少有人能说清楚:PoE 供电到底分几种标准?差别有多大?哪些设备要用 PoE,哪些必须上 PoE+ 或 PoE++?今天,我们就来一次彻底的“拆解”,把 PoE 的三大国际标准——讲得明明白白,顺便也帮你厘清网络工程中的常见“供电疑惑”。

网络技术联盟站 1549

Java中静态块,初始化块及构造函数的执行顺序

我们可以将执行顺序大致看作:          1. 静态成员变量          2. 静态代码块        //静态的域或方法只在加载类时执行一次 ...

wjc_hbu的博客 529

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

java 内部类构造函数执行顺序_Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究...

Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念。下面探究一下它的执行顺序与可能的用途。执行顺序首先定义A, B, C三个类用作测试,其中B继承了A,C又继承了B,并分别给它们加上静态初始化块、非静态初始化块和构造函数,里面都是一句简单的输出。主类Main里面也如法炮制。1 classA {2 static{...

weixin_29214199的博客 188

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

java基础学习笔记——静态初始化块,初始化块,构造函数的执行顺序

代码: class A { static { System.out.println("Static init A."); } { System.out.println("Instance init A."); } A() { System.out.println("Constructor A."); ...

copbint 352

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java初始化块,静态初始化块,构造函数执行顺序及其变量存放位置

一. Java类的初始化和实例化 1. 类的初始化 完成程序执行前的准备工作。在这个阶段,静态的(变量,方法,代码块)会被执行。同时会在开辟一块存储空间用来存放静态的数据。初始化只在类加载的时候执行一次。 2. 类的实例化(实例化对象) 创建一个对象的过程。在这个过程中会在堆中开辟内存,将一些非静态的方法,变量存放在里面。在程序执行的过程中,可以创建多个对象,既多次实例化。每次实例化都会开辟一块新的内存。(就是调用构造函数) 在每个类初始化使用前,都会先对该类进行加载(不是指类的实例化) 类加载有几个步骤,

chenmi123321的博客 1511

java初始化块_Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究...

Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念。下面探究一下它的执行顺序与可能的用途。执行顺序首先定义A, B, C三个类用作测试,其中B继承了A,C又继承了B,并分别给它们加上静态初始化块、非静态初始化块和构造函数,里面都是一句简单的输出。主类Main里面也如法炮制。1 classA {2 static{...

weixin_36261424的博客 187

Java--代码执行顺序(静态初始化块,初始化块,构造函数)

执行顺序:先执行静态初始化块,然后时初始化块,最后是构造函数   书写格式:              注意事项:                 ● 静态初始化块不需要在main方法中调用,即使没有main方法它也会执行                 ● 在通过构造函数进行实例化的时候,如果有初始化块,初始化块会在构造函数执行前执行                 ● 如果对...

m0_37618340的博客 1118

Java的初始化块、静态初始化块、构造函数的执行顺序

前两天做Java笔试题碰到了这么一个问题,代码没有记下来,靠着大概印象以及参考网上类似的题写出来,大致如下: package com.forTest.testCLassInitialization; /** * Name: Test * Author: xian * Email: * Comment: //TODO * Date: 2018-03-31 16:28 */ cl...

qq_39309971的博客 265

Java中静态变量、静态初始化块、普通初始化块与构造函数的执行顺序

1.问题    这是一道京东笔试题: public class jdtest{ public static void main(String[] args){ System.out.println("A"); new jdtest(); new jdtest(); } public jdtest(){ System.out.println("B"); } { Sy...

Roger_gr的博客 763

java静态/动态成员变量、初始化块,父类/子类构造函数执行顺序问题

package job; public class TestConsSeq { public static void main(String[] args) { /* * 几大原则 * 一、静态成员变量(Static) * 1、静态成员变量为类变量,所有对象共享同一内存空间 * 2、静态成员变量的声明和定义仅在首次加载类时执行一次 *

shijinupc的专栏 9257

Java 父类与子类初始化块,静态块,构造函数执行顺序

被static修饰的变量,块,方法都是会在类被加载的时候就会执行,而且是先与构造函数执行。 public class A { { System.out.println("A 初始化块"); } static{ System.out.println("A 静态块"); } private static Integer integer=getInt

learner_and_thinker的博客 988
上一篇: Java中子类的实例化过程
下一篇: java中的守护线程
billion_Fu
博客等级 码龄9年 3粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值