类和对象的初始化

C++初阶——类和对象(六)初始化列表、static成员、友元、内部类 阅读详情

上一篇博文简要分析了Java程序的执行流程,现在再来深入了解一下类和对象的初始化,下面是转载的博文,人家整理的不错,就拿来主义了,哈哈。


类的生命周期:分为装载,链接,初始化 
如图:


1)装载:查找并装载类型的二进制数据
2)连接:执行验证,准备,和解析(可选)
         a) 验证:确保导入类型正确
         b) 准备:为类变量分配内存,并将其初始化为默认值
         c) 解析:把类型中的符号引用转换成直接引用
3)初始化:把类变量初始化为默认初值

      随着Java虚拟机装载了一个类,并执行了一些它选择进行的验证之后,类就可以进入准备阶段了。在准备阶段,Java虚拟机为类变量分配内存,设置默认初始值:但在到达初始化阶段之前,类变量都没有被初始化为真正的初始值。(在准备阶段是不会执行Java代码的。)在准备阶段,虚拟机把给类变量新分配的内存根据类型设置为默认值。

 为了准备让一个类或者接口被"首次主动"使用,最后一个步骤就是初始化,也就是为类变量赋予正确的初始值。这里的”正确”初始值指的是程序员希望这个类变量所具备的起始值。正确的初始值是和在准备阶段赋予的默认初始值对比而言的。前面说过,根据类型的不同,类变量已经被赋予了默认初始值。而正确的初始值是根据程序员制定的主观计划面生成的。

在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。
 1)一个类变量初始化语句是变量声明后面的等号和表达式:
 2)静态初始化语句是一个以static开头的程序块
 example : 
    public class Example1 {
      
     // 类变量初始化语句
     static int value = (int) (Math.random()*6.0);
     
     // 静态初始化语句
     static{
      System.out.println("this is example");
     }
    }
所有的类变量初始化语句和类型的静态初始化器都被Java编译器收集在—起,放到——个特殊的方法中。对于类来说,这个方法被称作类初始化方法;对于接口来说,它被称为接口初始化方法。在类和接口的Javaclass文件中,这个方法被称为”<clinit>”。通常的Java程序方法是无法调用这个<clinit>方法的。这种方法只能被Java虚拟机调用


clinit>()方法
    前面说过,Java编译器把类变量初始化语句和静态初始化浯句的代码都放到class文件的
<clinit>()方法中,顺序就按照它们在类或者接门声明中出现的顺序。
 example: 
  public class Example1 {
    static int width;
    static int height = (int) (Math.random()*6.0);


    static{
     width = (int) (Math.random()*3.0);
    }
 }
java 编译器生成下面<clinit>方法:
0 invokestatic java.lang.Math.random 
3 ldc2_w 6.0 (double) 
6 dmul 
7 d2i 
8 putstatic Example1.height 
11 invokestatic java.lang.Math.random 
14 ldc2_w 3.0 (double) 17 dmul 
18 d2i 
19 putstatic Example1.width 
22 return


clinit 方法首先执行唯一的类变量初始化语句初始化heght,然后在静态初始化语句中初始化width(虽然它声明在height之前,但那仅仅是声明了类变量而不是类变量初始化语句).

除接口以外,初始化一个类之前必须保证其直接超类已被初始化,并且该初始化过程是由 Jvm 保证线程安全的。另外,并非所有的类都会拥有一个 <clinit>() 方法。
1)如果类没有声明任何类变量,也没有静态初始化语句,那么它不会有<clinit>()方法。
2)如果声明了类变量但是没有使用类变量初始化语句或者静态初始化语句初始它们,那么类不会有<clinit>()方法。 
   example: 
      public class example{
       static int val;
      }
     
3)如果类仅包含静态 final 变量的类变量初始化语句,并且类变量初始化语句是编译时常量表达式,类不会有<clinit>()方法。
    example:
    public class Example {
     static final String str ="abc";
     static final int value = 100;
    }
这种情况java编译器把 str 和 value 被看做是常量,jvm会直接使用该类的常量池或者在字节码中直接存放常量值。该类不会被加载。
  
如果接口不包含在编译时解析成常量的字段初始化语句,接口中就包含一个<clinit>()方法。
example:
 interface Example{
  int i =5;
  int hoursOfSleep = (int) (Math.random()*3.0);
  
 }
字段hoursOfSleep会被放在<clinit>()方法中(比较诡异???它被看作类变量了),而字段i被看作是编译时常量特殊处理(JAVA语法规定,接口中的变量默认自动隐含是public static final)。
 java 编译器生成下面<clinit>方法:
0 invokestatic java.lang.Math.random
3 ldc2_w 3.0 (double)
6 dmul
7 d2i
8 putstatic Example.hoursOfSleep
11 return


主动使用和被动使用
    在前面讲过,Java虚拟机在首次主动使用类型时初始化它们。只有6种活动被认为是主动使
用:
 1)创建类的新实例,
 2)调用类中声明的静态方法,
 3)操作类或者接口中声明的非常量静态字段,
 4)调用JavaAPI中特定的反射方法
 5)初始化一个类的子类;
 6)以及指定一个类作为Java虚拟机启动时的初始化类。
 
   使用一个非常量的静态字段只有当类或者接口的确声明了这个字段时才是主动使用、比如,类中声明的字段可能会被子类引用;接口中声明的字段可能会被子接口或者实现了这个接口的类引用。对于子类、子接口和实现接口的类来说.这就是被动使用(使用它们并不会触发它们的初始化)。下面的例子说明了这个原理:


class NewParement{
 static int hoursOfSleep = (int) (Math.random()*3.0);
 
 static{
  System.out.println("new parement is initialized.");
 }
}


class NewbornBaby extends NewParement{
 static int hoursOfCry = (int) (Math.random()*2.0);
 
 static{
  System.out.println("new bornBaby is initialized.");
 }
}




public class Example1 {
 
 public static void main(String[] args){
  int hours = NewbornBaby.hoursOfSleep;
  System.out.println(hours);
 }
 static{
  System.out.println("example1 is initialized.");
 }
 
}
运行结果: 
example1 is initialized.
new parement is initialized.
0
NewbornBaby 没有被初始化,也没有被加载。




对象的生命周期

        当java虚拟机创建一个新的类实例时不管明确的还是隐含的,首先要在堆中为保存对象的实例变量分配内存,包含所有在对象类中和它超类中声明的变量(包括隐藏的实例变量)都要分配内存。其次赋默认初值,最后赋予正确的初始值。


java编译器为每个类都至少生成一个实例初始化方法 "<init>()"与构造方法相对应。


如果构造方法调用同一个类中的另一个构造方法(构造方法重载),它对应的init<>():
1)一个同类init<>()调用。
2)对应构造方法体代码的调用。
如果构造方法不是通过this()调用开始,且对象不是Object 它对应的init<>():
1)一个超类init<>()调用。
2)任意实例变量初始化代码调用。
3)对应构造方法体代码的调用。
如果上述对象是Object,则去掉第一条。如果构造方法明确使用super()首先调用对应超类init<>()其余不变。
下面的例子详细说明了实例变量初始化(摘自Java Language Specification)
class Point{
 int x,y;
 Point(){x=1;y=1;}
}
class ColoredPoint extends Point{
 int color = OxFF00FF;
}
class Test{
 public static void main(String[] args){
  ColoredPoint cp = new ColoredPoint();
  System.out.println(cp.color);
 }
}
首先,为新的ColoredPoint实例分配内存空间,以存储实例变量x,y和color;然后将这些变量初始化成默认值在这个例子中都是0。
接下来调用无参数的ColoredPoint(),由于ColorPoint没有声明构造方法,java编译器会自动提供如下的构造方法:ColoredPoint(){super();}。
该构造方法然后调用无参数的Point(),而Point()没有显示的超类,编译器会提供一个对其无参数的构造方法的隐式调用:Point(){super();x=1;y=1}。
因此将会调用到Object();Object类没有超类,至此递归调用会终止。接下来会调用Object任何实例初始化语句及任何实例变量初始化语句。
接着执行Object()由于Object类中未声明这样的构造方法。因此编译器会提供默认的构造方法object(){}。但是执行该构造方法不会产生任何影响,然后返回。
接下来执行Point类实例变量初始化语句。当这个过程发生时,x,y的声明没有提供任何初始化表达式,因此这个步骤未采取任何动作(x,y 仍为0);
接下来执行Point构造方法体,将x,y赋值为1。
接下来会执行类ColoredPoint的实例变量初始化语句。把color赋值0xFF00FF,最后执行ColoredPoint构造方法体
余下的部分(super()调用之后的部分),碰巧没有任何语句,因此不需要进一步的动作,初始化完成。


与C++不同的是,在创建新的类实例期间,java编程语言不会为方法分派来指定变更的规则。如果调用的方法在被
初始化对象的子类中重写,那么就是用重写的方法。甚至新对象被完全初始化前也是如此。编译和运行下面的例子
class Super{
 Super(){printThree();}
 void printThree{System.out.println("Three");}
}
class Test extends Super{
 int three = (int)Math.PI; // That is 3
 public static void main(String args[]){
  Test t = new Test();
  t.printThree();
 }
 void printThree(){System.out.println(three);}
}
输出:
0
3
这表明Super类中的printThree()没有被执行。而是调用的Test中的printThree()。


TP4054芯片实战:手把手教你设计USB锂电充电电路(附PCB散热优化技巧) 本文以TP4054芯片为核心,手把手教你设计稳定可靠的USB锂电池充电电路。文章详细解析了芯片的恒流恒压工作模式、关键外围元件选型计算,并重点分享了PCB布局与散热优化的实战技巧,帮助工程师从“能工作”提升到“工作得好”,确保充电效率与系统稳定性。 阅读详情

相关推荐

IC设计新手必看:如何正确使用去耦电容(decap)避免电源噪声?

本文深入探讨了IC设计中去耦电容(decap)的应用技巧,从核心原理到布局实现,帮助新手工程师有效抑制电源噪声。文章详细解析了MIM、MOM等电容类型的特性与选择策略,并提供了先进的布局技巧和验证方法,特别适用于28nm以下先进工艺的电路设计挑战。

weixin_30555125的博客 114

【C++新特性】 - 类内初始值

如果定义变量时没有指定初值,则变量被默认初始化,此时变量被赋予了“默认值”。默认值到底是什么由变量类型和变量所在位置决定。 如果是内置类型(int, short等)的变量为被显示初始化,它的值由定义的位置决定。定义与任何函数体之外的变量被初始化为0,定义在函数体内部的内置变量将不被初始化,其值时未定义的。 C++11新标准规定可以为数据成员提供一个类内初始值(in-class initializer)。创建对象时,类内初始值将用于初始化数据成员,没有初始值的成员将被默认初始化。 1、类内初始值和赋值类

BruceZong的专栏 4512

零中频架构实战:用Matlab模拟AD9361收发信号(附完整代码)

本文详细介绍了如何使用Matlab模拟AD9361射频收发器的零中频架构,解决镜像干扰等关键挑战。通过完整的代码示例和系统级建模方法,帮助工程师掌握RFIC设计中的自适应校准算法和性能优化技巧,特别适用于SDR系统开发。

weixin_30733003的博客 538

kvm 验证-模拟字节码执行

上篇文章介绍了kvm进行验证的大部分过程.本文来介绍字节码执行的过程. kvm内部定义了枚举,来支持字节码的类型验证.代码如下: enum { ITEM_Bogus, /* 未使用 */ ITEM_Integer, ITEM_Float, ITEM_Double, ITEM_Long, ITEM_Null, /* acons...

qq_26000415的博客 5365

FastDDS之共享内存

transport层负责为DDS用户数据收发和服务发现提供通信。包含UDP,TCP,SHM。

u010378559的博客 3084

HFSS实战项目——微带一分四功分器

呕心沥血保姆级教程!!!!手把手教会你做功分器,史上最详细步骤!!!

2401_87464239的博客 2672

字节码指令集与解析

字节码指令

m0_56863607的博客 425

YOLO11改进-注意力-引入自调制特征聚合模块SMFA

SMFA(自调制特征聚合模块): SMFA模块用于协同建模局部和非局部信息,它分为两个分支:一个是EASA(Efficient Approximation of Self-Attention,简化的自注意力分支),用于捕获非局部信息;另一个是LDE(Local Detail Estimation,局部细节估计分支),用于捕获局部细节。EASA通过对输入特征进行下采样,然后利用全局特征的方差进行调制,再与原始特征进行聚合,提取非局部结构信息。LDE分支则通过卷积操作提取输入特征中的高频局部信息。

qq_64693987的博客 2206

字节码指令

ldc2_w 将一个 long 压入操作数栈(分两次压入,因为 long 是 8 个字节)这里小的数字都是和字节码指令存在一起,超过 short 范围的数字存入了常量池。将一个 byte 压入操作数栈(其长度会补齐 4 个字节),类似的指令还有。sipush 将一个 short 压入操作数栈(其长度会补齐 4 个字节)* 演示 字节码指令 和 操作数栈、常量池的关系。完成 main 方法调用,弹出 main 栈帧。接着上一节,研究一下两组字节码指令,一个是。传递参数,执行新栈帧中的字节码。

weixin_60257072的博客 2006

Unity中使用TCP和UDP传输摄像头视频的实践

本文探讨了在Unity中通过TCP和UDP协议传输摄像头视频的实现方法。TCP通过自定义消息帧保证数据完整性但效率较低,UDP传输速度快但可能丢帧。文章提供了Python和Unity的代码示例,分析了两种协议的适用场景:TCP适合要求数据完整性的应用,UDP则适合追求实时性的场景。最终选择取决于具体需求,并需要注意线程安全与同步机制。

m0_74337424的博客 145

YOLOv5/v7/v8首发革新改进——轻巧、创新的LADH检测头

本文介绍了一种原创改进的轻量化非对称多级压缩LADH检测头,该检测头能够实现即插即用,并在YOLOv5/v7/v8检测器中取得了显著的性能提升。本文将介绍一种原创改进的轻量级非对称多级压缩LADH(Lightweight Asymmetric Dual-Head)检测头,该检测头能够实现即插即用,并显著提升YOLO检测器的性能。因此,我们提出了一种非对称多级压缩的方法,即对不同类别的检测头采用不同的压缩比例。然而,为了进一步提高YOLO的性能,我们进行了一项原创改进,设计了一种轻巧且创新的LADH检测头。

IpyVariable的博客 2725

类的初始化和对象的初始化

在类加载过程中,准备阶段是正式为类变量(static成员变量)分配内存并设置初始值的阶段,而初始化阶段是真正开始执行类中定义的java程序代码(字节码)并按程序猿的意图去初始化类变量的过程。更直接的说初始化阶段是执行类构造器方法的过程。()方法是由编译器自动收集类中的所有类变量的赋值动作和静态代码块static{}中的语句合并产生的,其中编译器收集的顺序是由语句在源文件中出现的顺序锁决定。  类构造器()与实例构造器()不同,它不需要程序员进行显式调用,虚拟机会保证在子类类构造器()执行之前,父类的类构造(

joyblur的博客 1833

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

64. Java 类和对象 - 初始化字段

最简单的是在字段声明处直接赋值,但在实际开发中,初始化往往需要考虑更复杂的逻辑,如错误处理、数据准备或循环填充等。为了应对这些需求,Java 提供了多种初始化方式,包括构造函数初始化、静态初始化块、实例初始化块以及通过。对于实例变量来说,当初始化逻辑涉及到参数传递、判断或循环填充等复杂情况时,通常在构造函数中完成初始化。这种方式适用于那些在初始化过程中需要执行较复杂逻辑、循环、或错误处理的场景,并且希望在类加载时就完成初始化,而非在创建对象时。方法来封装初始化逻辑,并在构造函数或实例初始化块中调用。

yaoxin521123的博客 1356

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

类的加载(也叫类的初始化)和对象初始化

如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的信息推断出数组的大小。如果Java堆中的内存并不是规整的,已被使用的内存和空闲的内存相互交错在一起,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录,这种分配方式称为“空闲列表”(Free List)。

glenshappy的专栏 1137

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

java如何初始化类对象_Java中的类和对象初始化

java如何初始化类对象 Java中的类和对象必须在使用前进行初始化。 您之前已经了解到 ,在加载类时,将类字段初始化为默认值,并且通过构造函数初始化了对象,但是还有更多要初始化的内容。 本文介绍了Java的所有用于初始化类和对象的功能。 下载 获取代码 下载本教程中示例应用程序的源代码。 由Jeff Friesen为JavaWorld创建。 如何初始化Java类 在探讨Ja...

cxu0262的博客 2024

类和对象(1) —— 类和对象的概念、类的实例化和初始化、构造方法和this关键词

学习Java中的类和对象对于掌握面向对象编程(OOP)至关重要,类是创建对象的蓝图或模板,而对象是类的实例。学习Java类和对象不仅对于理解面向对象编程至关重要,而且对于提高你的编程技能、解决问题的能力和就业前景都非常有帮助。

2301_80030290的博客 1632

(五)C++类和对象之对象的初始化和清理

C++类和对象之对象的初始化和清理

今天也要加油呀ʕ ᵔᴥᵔ ʔ 1275

Java中的类和对象初始化

必须先初始化Java中的类和对象,然后才能使用它们。您以前已经了解到,在加载类时,将类字段初始化为默认值,并且通过构造函数初始化了对象,但是还有更多初始化内容。本文介绍了Java的所有用于初始化类和对象的功能。 如何初始化Java类 在探讨Java对类初始化的支持之前,让我们回顾一下初始化Java类的步骤。考虑清单1。 清单1.将类字段初始化为默认值 class SomeClass { st...

qq_41806546的博客 531

java的point类初始化_类和对象的初始化

上一篇博文简要分析了Java程序的执行流程,现在再来深入了解一下类和对象的初始化,下面是转载的博文,人家整理的不错,就拿来主义了,哈哈。类的生命周期:分为装载,链接,初始化如图:1)装载:查找并装载类型的二进制数据2)连接:执行验证,准备,和解析(可选)a) 验证:确保导入类型正确b) 准备:为类变量分配内存,并将其初始化为默认值c) 解析:把类型中的符号引用转换成直接引用3)初始化:把类变量初始...

weixin_34007888的博客 1128

C++类和对象(下)——初始化列表、static成员和友元

C++类和对象——初始化列表、static成员和友元一、再谈构造函数1.1 构造函数整体赋值1.2 初始化列表三级目录 关于C++类和对象的学习 C++类和对象(上)——类的基本概念、类的限定符及封装和类成员函数的this指针 C++类和对象(中)——类的6个默认成员函数(构造、析构、拷贝构造、赋值运算符重载) 一、再谈构造函数 1.1 构造函数整体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。例如我们之前创建的Date类 class Date { public: D

8178

Java 对象初始化和类初始化的区别、new一个对象的详细过程、类加载、类初始化、实例初始化

Java 初始化的深认知(第二篇)Java 类初始化和对象初始化明解Java中new一个对象的详细过程,JVM执行了那些操作new一个对象的详细过程什么时候需要初始化一个类获得类的资源初始化对象 Dog dog = new Dog()创建一个对象时jvm在干什么:Java 对象的使用:对对象的访问定位类加载过程(第一次使用该类)双亲委派机制更多知识 首先,大家看一下这段代码的执行顺序,你是否理解的如注释所写: //父类Animal class Animal { /*8、执行初始化*/ pri

qq_42603181的博客 3064

C++类和对象的初始化

C++类和对象的初始化 1.什么是类? 类是多个对象的共同属性和行为的抽象。 例: 类 :熊猫 基本属性:数据成员修饰、数据类型; 性别、动物名 行为:用成员函数去描述行为,即写在类中的成员函数 吃竹子、睡觉 对象:类的具体化。 2.代码产生类 class 类名{ //不加权限限定词时,默认时是私有属性。 public: //对象能在类外进行访问的属性,类的行为。 protected: //保护属性,类属性写在这个属性下方。 private: //私有属性 }; 3.类和对象初始化 #include

qq_51969153的博客 656

C++ 类和对象、初始化列表、explicit

第二篇,加油

m0_68102654的博客 1001
上一篇: 图解Java对象初始化过程以及方法调用
下一篇: 图解Java单例模式内存分配
flowciyu
博客等级 码龄15年 65粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值