奇淫巧技!!!面向对象编程之初始化块

2023-11-25 07:18

本文主要是介绍奇淫巧技!!!面向对象编程之初始化块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Java面向对象之初始化块

在程序设计中,让数据域正确地执行初始化一直是一个亘古不变的真理。
那么,有哪些手段可以初始化数据域呢:

  • 在构造器中设置值。

  • 在声明中赋值。

  • 使用初始化块。

  • 本篇探讨关于Java中的初始化块的注意点:Java中的初始化块是类中的一种成员,但是既没有名字,也没有标识,不能够被调用,它仅仅只是在创建Java对象时隐式执行初始化。

普通初始化块

  • 普通的初始化块就是非static修饰的。

  • 声明时以花括号{}包起代码,被包住的就是初始化代码,整体就是一个初始化块。

  • 可以有很多个初始化块,按顺序先后且全部地执行,所以没什么必要分开,一起就完事。

  • 声明实例变量时指定默认值和普通初始化块都被看做是对象的初始化代码,按先后顺序执行。

  • 初始化块总是在构造器之前被调用。

  • 如果多个重载的构造器有相同且与传入形参无关的语句可以一起提入初始化块。

public class NormalBlock {int a = 5;{
//        a = 6;System.out.println("初始化块之后的a为"+a);}
//    {
//        int a = 8;
//        System.out.println("初始化块中重新定义了一个a?"+a);
//    }NormalBlock(){
//加入Java开发交流君样:756584822一起吹水聊天System.out.println("构造器中赋a的值为"+a);}
}
class NormalTest{public static void main(String[] args) {new NormalBlock();}
}

上面注释语句时,结果如下:

  • 初始化块之后的a为5
  • 构造器中赋a的值为5
    可以看到,在这个例子中,声明实例变量指定默认值也被看作初始化代码,且依次执行,先初始化块,后构造器。(可以试着调换它们的位置验证一下哈)

上面解除注释语句之后,我对结果是产生疑惑的:

  • 初始化块之后的a为6
  • 初始化块中重新定义了一个a?8
  • 构造器中赋a的值为6
    我的疑惑点在于,我一开始以为,我在第二个代码块中定义的和之前同名的变量a是同一个(然而并不是)这样也就算了,初始化代码之后,执行构造器时,调用了a,那么这时这个a调用的是哪个呢,于是产生疑惑,希望知道的小伙伴可以为我指点迷津。

我在测试的时候还遇到了ilegal forward reference,即前向引用错误,如下图。

    {age = 50;if(age>40) System.out.println("Father类的初始化块且age>40");System.out.println("Father类的第一个初始化块");}int age =20;

产生原因:是因为在还没有定义该变量时,就引用了它,所以为了避免这样的错误,尽量将初始化块放在成员变量声明之后。

静态初始化块

和普通的对应的就是静态初始化块啦,也就是用static修饰的,也称为类初始化块。根据名称分析,类初始化块负责对类进行初始化,而普通初始化块负责对对象执行初始化。

  • 以static{}的格式包围对类变量的初始化。
  • 由于静态初始化块和类相关,负责对类进行初始化,所以总是比普通初始化块先执行。
    通常用于对类变量执行初始化处理,而不能对实例变量进行初始化处理。
  • 静态初始化块属于类的静态成员,遵循静态成员不能访问非静态成员的规则:即不能访问非静态成员(实例变量和实例方法)。
  • 类似地,静态初始化块和声明静态成员变量时指定初始值都时该类的初始化代码。

初始化块与构造器

关于初始化块与构造器的先后调用顺序,结合代码来理解一下子。

package com.my.pac17;/*** @auther Summerday*///加入Java开发交流君样:756584822一起吹水聊天
public class A {{System.out.println("A.instance initializer");}static {System.out.println("A.static initializer");}public A() {System.out.println("A.A");}
}
class B extends A {{System.out.println("B.instance initializer");}static {System.out.println("B.static initializer");}public B() {System.out.println("B.B");}public B(String m) {this();System.out.println("B.B," + m);}
}
class C extends B {{System.out.println("C.instance initializer");}static {System.out.println("C.static initializer");}public C() {super("ccc");System.out.println("C.C");}//加入Java开发交流君样:756584822一起吹水聊天
}
class BTest {public static void main(String[] args) {new C();System.out.println("*******");new C();}
}

/测试结果/
A.static initializer
B.static initializer
C.static initializer
/类初始化阶段,限制性最顶层父类的静态初始化块
然后依次向下,直到执行当前类的静态初始化块
/

A.instance initializer
A.A
B.instance initializer
B.B//调用B的无参构造器
B.B,ccc//调用B的带参构造器
C.instance initializer//最后执行C
C.C

/对象初始化阶段,先执行最顶层父类的初始化块,
最顶层父类的构造器,然后依次向下,直到执行当前
类的初始化块、当前类的构造器
/


//不用执行静态初始化语句

A.instance initializer
A.A
B.instance initializer
B.B
B.B,ccc
C.instance initializer
C.C

static修饰的静态初始化块,总是先被调用,且在继承关系中,最早的父类中的静态初始化块先执行。
可以看到,第二次创建子类对象时,就没有再执行静态初始化块中的初始化,因为三个类已经加载成功。
普通初始化块和构造器的执行顺序为,普通初始化块在构造器之前执行,从最早的父类一直到当前类。

image

最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:756584822

这篇关于奇淫巧技!!!面向对象编程之初始化块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/423357

相关文章

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++类和对象之初始化列表的使用方式

《C++类和对象之初始化列表的使用方式》:本文主要介绍C++类和对象之初始化列表的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C++初始化列表详解:性能优化与正确实践什么是初始化列表?初始化列表的三大核心作用1. 性能优化:避免不必要的赋值操作2. 强

SpringIOC容器Bean初始化和销毁回调方式

《SpringIOC容器Bean初始化和销毁回调方式》:本文主要介绍SpringIOC容器Bean初始化和销毁回调方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录前言1.@Bean指定初始化和销毁方法2.实现接口3.使用jsR250总结前言Spring Bea

Spring实现Bean的初始化和销毁的方式

《Spring实现Bean的初始化和销毁的方式》:本文主要介绍Spring实现Bean的初始化和销毁的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Bean的初始化二、Bean的销毁总结在前面的章节当中介绍完毕了ApplicationContext,也就

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

Spring组件初始化扩展点BeanPostProcessor的作用详解

《Spring组件初始化扩展点BeanPostProcessor的作用详解》本文通过实战案例和常见应用场景详细介绍了BeanPostProcessor的使用,并强调了其在Spring扩展中的重要性,感... 目录一、概述二、BeanPostProcessor的作用三、核心方法解析1、postProcessB

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization