代码块的理解

news2025/1/10 14:13:17

如果成员变量想要初始化的值不是一个硬编码的常量值,而是需要通过复杂的计算或读取文件、或读取运行环境信息等方式才能获取的一些值,该怎么办呢?此时,可以考虑代码块(或初始化块)。

  • 代码块(或初始化块)的作用

  • 对Java类或对象进行初始化

  • 代码块(或初始化块)的分类

    • 一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块(static block)

    • 没有使用static修饰的,为非静态代码块。

 静态代码块

在代码块的前面加static,就是静态代码块。

【修饰符】 class 类{
    static{
        静态代码块
    }
}

 静态代码块的特点
  1. 可以有输出语句。

  2. 可以对类的属性、类的声明进行初始化操作。

  3. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。

  4. 若有多个静态的代码块,那么按照从上到下的顺序依次执行。

  5. 静态代码块的执行要先于非静态代码块。

  6. 静态代码块随着类的加载而加载,且只执行一次。

package com.atguigu.keyword;

public class Chinese {
//    private static String country = "中国";

    private static String country;
    private String name;

    {
        System.out.println("非静态代码块,country = " + country);
    }

    static {
        country = "中国";
        System.out.println("静态代码块");
    }

    public Chinese(String name) {
        this.name = name;
    }
}

 

package com.atguigu.keyword;

public class TestStaticBlock {
    public static void main(String[] args) {
        Chinese c1 = new Chinese("张三");
        Chinese c2 = new Chinese("李四");
    }
}

 

 非静态代码块

 语法格式

【修饰符】 class 类{
    {
        非静态代码块
    }
    【修饰符】 构造器名(){
        // 实例初始化代码
    }
    【修饰符】 构造器名(参数列表){
        // 实例初始化代码
    }

 非静态代码块的作用

和构造器一样,也是用于实例变量的初始化等操作。

 非静态代码块的意义

如果多个重载的构造器有公共代码,并且这些代码都是先于构造器其他代码执行的,那么可以将这部分代码抽取到非静态代码块中,减少冗余代码。

 非静态代码块的执行特点
  1. 可以有输出语句。

  2. 可以对类的属性、类的声明进行初始化操作。

  3. 除了调用非静态的结构外,还可以调用静态的变量或方法。

  4. 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。

  5. 每次创建对象的时候,都会执行一次。且先于构造器执行。

举例

举例1:

(1)声明User类,

  • 包含属性:username(String类型),password(String类型),registrationTime(long类型),私有化

  • 包含get/set方法,其中registrationTime没有set方法

  • 包含无参构造,

    • 输出“新用户注册”,

    • registrationTime赋值为当前系统时间,

    • username就默认为当前系统时间值,

    • password默认为“123456”

  • 包含有参构造(String username, String password),

    • 输出“新用户注册”,

    • registrationTime赋值为当前系统时间,

    • username和password由参数赋值

  • 包含public String getInfo()方法,返回:“用户名:xx,密码:xx,注册时间:xx”

(2)编写测试类,测试类main方法的代码如下:

    public static void main(String[] args) {
        User u1 = new User();
        System.out.println(u1.getInfo());

        User u2 = new User("song","8888");
        System.out.println(u2.getInfo());
    }

如果不用非静态代码块,User类是这样的:

package com.atguigu.block.no;

public class User {
    private String username;
    private String password;
    private long registrationTime;

    public User() {
        System.out.println("新用户注册");
        registrationTime = System.currentTimeMillis();
        username = registrationTime+"";
        password = "123456";
    }

    public User(String username,String password) {
        System.out.println("新用户注册");
        registrationTime = System.currentTimeMillis();
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public long getRegistrationTime() {
        return registrationTime;
    }
    public String getInfo(){
        return "用户名:" + username + ",密码:" + password + ",注册时间:" + registrationTime;
    }
}

 

 如果提取构造器公共代码到非静态代码块,User类是这样的:

package com.atguigu.block.use;

public class User {
    private String username;
    private String password;
    private long registrationTime;

    {
        System.out.println("新用户注册");
        registrationTime = System.currentTimeMillis();
    }

    public User() {
        username = registrationTime+"";
        password = "123456";
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public long getRegistrationTime() {
        return registrationTime;
    }
    public String getInfo(){
        return "用户名:" + username + ",密码:" + password + ",注册时间:" + registrationTime;
    }
}

举例2:

private static DataSource dataSource = null;

static{
    InputStream is = null;
    try {
        is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");
        Properties pros = new Properties();
        pros.load(is);
        //调用BasicDataSourceFactory的静态方法,获取数据源。
        dataSource = BasicDataSourceFactory.createDataSource(pros);
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        if(is != null){
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }        
        }        
    }        
}

 

小结:实例变量赋值顺序

 

 练习

练习1:分析加载顺序

class Root{
    static{
        System.out.println("Root的静态初始化块");
    }
    {
        System.out.println("Root的普通初始化块");
    }
    public Root(){
        System.out.println("Root的无参数的构造器");
    }
}
class Mid extends Root{
    static{
        System.out.println("Mid的静态初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid(){
        System.out.println("Mid的无参数的构造器");
    }
    public Mid(String msg){
        //通过this调用同一类中重载的构造器
        this();
        System.out.println("Mid的带参数构造器,其参数值:"
            + msg);
    }
}
class Leaf extends Mid{
    static{
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }    
    public Leaf(){
        //通过super调用父类中有一个字符串参数的构造器
        super("尚硅谷");
        System.out.println("Leaf的构造器");
    }
}
public class LeafTest{
    public static void main(String[] args){
        new Leaf(); 
        //new Leaf();
    }
}

练习2:分析加载顺序

class Father {
    static {
        System.out.println("11111111111");
    }
    {
        System.out.println("22222222222");
    }

    public Father() {
        System.out.println("33333333333");

    }

}

public class Son extends Father {
    static {
        System.out.println("44444444444");
    }
    {
        System.out.println("55555555555");
    }
    public Son() {
        System.out.println("66666666666");
    }


    public static void main(String[] args) { 
        System.out.println("77777777777");
        System.out.println("************************");
        new Son();
        System.out.println("************************");

        new Son();
        System.out.println("************************");
        new Father();
    }

}
 

 

练习3:

package com.atguigu05.field.interview;

/**
 * @author 尚硅谷-宋红康
 * @create 16:04
 */
public class Test04 {
    public static void main(String[] args) {
        Zi zi = new Zi();
    }
}
class Fu{
    private static int i = getNum("(1)i");
    private int j = getNum("(2)j");
    static{
        print("(3)父类静态代码块");
    }
    {
        print("(4)父类非静态代码块,又称为构造代码块");
    }
    Fu(){
        print("(5)父类构造器");
    }
    public static void print(String str){
        System.out.println(str + "->" + i);
    }
    public static int getNum(String str){
        print(str);
        return ++i;
    }
}
class Zi extends Fu{
    private static int k = getNum("(6)k");
    private int h = getNum("(7)h");
    static{
        print("(8)子类静态代码块");
    }
    {
        print("(9)子类非静态代码块,又称为构造代码块");
    }
    Zi(){
        print("(10)子类构造器");
    }
    public static void print(String str){
        System.out.println(str + "->" + k);
    }
    public static int getNum(String str){
        print(str);
        return ++k;
    }
}
 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1566306.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Harmony创建Page省事小技巧

在创建Page页面时,选择ArkTS File时,创建的文件不会自动生成基础代码,也不会自动在main_page.json中自动进行注册,如何解决问题呢,其实很简单创建Page页面时选择Page项后就会创建Page文件,创建完的页面会自…

基于深度学习的铁轨缺陷检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要:本文深入研究了基于YOLOv8/v7/v6/v5的铁轨缺陷检测系统。核心技术上,文章采用了最先进的YOLOv8,并整合了YOLOv7、YOLOv6、YOLOv5算法,进行了性能指标的对比分析。文中详细阐述了国内外铁轨缺陷检测的研究现状、数据集处理方法…

封装一个vue3的公共组件

在Vue 3中,封装公共组件的场景包括但不限于以下几种情况: 重复使用的组件:如果你发现某个组件在多个地方重复使用,那么将其封装成公共组件是很有意义的。比如,页面中的各种表单控件(输入框、下拉框、日期选…

超级AI大脑产品架构图解析

一、概述 超级AI大脑是一个集成了先进的人工智能技术,为用户提供全方位、智能化的服务的产品。其产品架构图设计旨在清晰展现其技术层次、功能模块与业务流程,以确保用户能够高效、便捷地利用该产品。 二、技术层次 基础设施层: 服务器&…

大模型学习笔记八:手撕AutoGPT

文章目录 一、功能需求二、演示用例三、核心模块流程图四、代码分析1)Agent类目录创建智能体对象2)开始主流程3)在prompt的main目录输入主prompt和最后prompt4)增加实际的工具tools 一、功能需求 目的 设计一个 Agent&#xff0c…

yolov8姿态识别与绘制

YOLOv8姿态检测是一种基于深度学习的计算机视觉技术,用于识别图像或视频中人体的姿态。作为YOLO系列算法的最新版本,YOLOv8在姿态检测任务上展现出了卓越的性能和效率。以下将详细介绍YOLOv8姿态检测的原理、特点、应用以及训练过程。 一、YOLOv8姿态检…

快消企业数字化转型实战解析:探寻未来增长新动力

2024年,快消行业正站在数字化转型的风口浪尖。 “今年是过去十年最差的一年,但却可能是未来十年最好的一年。”这句话几乎成为了今年的流行语。 但是这句话是情绪,不是事实。未来十年,中国会成为全球最大的消费品市场&#xff0…

CSS基础选择器 小案例复习(画三个小盒子)

(大家好,前面我们学习了基础的选择器,俗话说:温故而知新。所以今天我们将通过小案例来复习前面学过的小知识点。另,十分感谢大家对我文章的支持❤️) 通过这个案例复习两个地方: 类选择器的使用…

AJAX —— 学习(三)

目录 一、jQuery 中的 AJAX (一)get 方法 1.语法介绍 2.结果实现 (二)post 方法 1.语法介绍 2.结果实现 (三)通用型的 AJAX 方法 1.语法介绍 2.结果实现 二、AJAX 工具库 axios (…

js 基础知识 forEach 和 map 的区别,及 map 不加 return 返回什么

问题一:forEach 和 map 之间的区别: 1、forEach 不返回新数组,map 返回新数组,其中包含回调函数的返回值。 2、用途:如果只想要遍历数组并对每个元素执行某些操作而不产生新数组,那么应该使用 forEach&am…

全网最强JavaWeb笔记 | 万字长文爆肝JavaWeb开发——day04_Maven入门

万字长文爆肝黑马程序员2023最新版JavaWeb教程。这套教程打破常规,不再局限于过时的老套JavaWeb技术,而是与时俱进,运用的都是企业中流行的前沿技术。笔者认真跟着这个教程,再一次认真学习一遍JavaWeb教程,温故而知新&…

ETL工具-nifi干货系列 第八讲 处理器PutDatabaseRecord 写数据库(详细)

1、本节通过一个小例子来讲解下处理器PutDatabaseRecord,该处理器的作用是将数据写入数据库。 如下流程通过处理器GenerateFlowFile 生成数据,然后通过处理器JoltTransformJSON转换结构,最后通过处理器PutDatabaseRecord将数据写入数据库。如…

软件架构风格_4.虚拟机体系结构风格

虚拟机体系结构风格的基本思想是人为构建一个运行环境,在这个环境之上,可以解析与运行自定义的一些语言,这样来增加架构的灵活性。虚拟机体系结构风格主要包括解释器风格和规则系统风格。 1.解释器体系结构风格 一个解释器通常包括完成解释工…

首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!

CodeGeeX是一款免费的智能编程助手。 继CodeGeeX在Visual Studio Code、JetBrains IDEs全家桶、HBuilderX、deepin-IDE等主流IDE中上线后,用户呼声最高的Visual Studio平台的适配插件产品也正式推出上线了!成为首个适配Visual Studio平台的国产智能编程…

docker导出导入镜像

docker导出镜像 查看要导出的镜像 docker images主要有两列 REPOSITORY TAG 导出命令 导出公式 docker save -o xxxx.tar REPOSITORY:TAG例子 docker save -o minio.tar minio/minio:latestminio/minio:latest可以使用image id代替,但是使用image id会导致导…

笔记: JavaSE day15 笔记

第十五天课堂笔记 数组 可变长参数★★★ 方法 : 返回值类型 方法名(参数类型 参数名 , 参数类型 … 可变长参数名){}方法体 : 变长参数 相当于一个数组一个数组最多只能有一个可变长参数, 并放到列表的最后parameter : 方法参数 数组相关算法★★ 冒泡排序 由小到大: 从前…

基于springboot实现校园周边美食探索及分享平台系统项目【项目源码+论文说明】

基于springboot实现园周边美食探索及分享平台系统演示 摘要 美食一直是与人们日常生活息息相关的产业。传统的电话订餐或者到店消费已经不能适应市场发展的需求。随着网络的迅速崛起,互联网日益成为提供信息的最佳俱渠道和逐步走向传统的流通领域,传统的…

2024 ccfcsp认证打卡 2023 05 01 重复局面

2023 05 01 重复局面 题目题解1题解2区别:数据存储方式:时间复杂度:空间复杂度: 总结: 题目 题解1 import java.util.*;public class Main {public static void main(String[] args) {Scanner input new Scanner(Sys…

vivado eFUSE 寄存器访问和编程

eFUSE 寄存器访问和编程 注释 : 在 MPSoC 和 Versal 器件上不支持以下 eFUSE 访问和编程方法。 7 系列、 UltraScale 和 UltraScale 器件具有一次性可编程位用于执行特定功能 , 称为 eFUSE 位。不同 eFUSE 位类型如 下所述: • …

利用Winform实现简陋版的温度计(仅供参考)

本人水平有限,如有写得不对的地方,望指正。为了简单化,做了一个简陋版的温度计控件,有点丑哈。本文的内容仅供参考 测试环境: visual studio 2017 .net framework 4.0 效果图如下: 步骤如下:…