草庐IT

Java 对象初始化详细过程

runoob 2023-03-28 原文

一个类及其对象初始化的过程

一、什么时候需要初始化一个类

首次创建某个对象时:

Dog dog = new Dog(); 

首次访问某个类的静态方法或者静态字段时:

Dog.staticFields;

Java 解释器就会去找类的路径,定位已经编译好的 Dog.class 文件。

二、获得类的资源

然后 jvm 就会载入 Dog.class,生成一个 class 对象。这个时候如果有静态的方法或者变量,静态初始化动作都会被执行。这个时候要注意啦,静态初始化在程序运行过程中只会在 Class 对象首次加载的时候运行一次。这些资源都会放在 jvm 的方法区。

方法区又叫静态区,跟堆一样,被所有的线程共享。

方法区中包含的都是在整个程序中永远唯一的元素,包含所有的 class 和 static 变量。

三、初始化对象 Dog dog = new Dog()

  • 1.第一次创建 Dog 对象先执行上面的一二步
  • 2.在堆上为 Dog 对象分配足够的存储空间,所有属性和方法都被设置成默认值(数字为 0,字符为 null,布尔为 false,而所有引用被设置成 null)
  • 3.执行构造函数检查是否有父类,如果有父类会先调用父类的构造函数,这里假设 Dog 没有父类,执行默认值字段的赋值即方法的初始化动作。
  • 4.执行构造函数。

有父类情况下的初始化

假设: Dog extends Animal

1、执行第一步,找出 Dog.class 文件,接着在加载过程中发现他有一个基类(通过 extends 关键字),于是先执行 Animal 类的第一二步,加载其静态变量和方法,加载结束之后再加载子类 Dog 的静态变量和方法。

如果 Animal 类还有父类就以此类推,最终的基类叫做根基类。

注意:因为子类的 static 初始化可能会依赖于父类的静态资源,所以要先加载父类的静态资源。

2、接着要 new Dog 对象,先为 Dog 对象分配存储空间 -> 到 Dog 的构造函数 -> 创建默认的属性。这里其构造函数里面的第一行有个隐含的 super(),即父类构造函数,所以这时会跳转到父类 Animal 的构造函数。

Java 会帮我们完成构造函数的补充,Dog 实际隐式的构造函数如下:
Dog() { 
    //创建默认的属性和方法 
    //调用父类的构造函数super()(可显式写出) 
    //对默认属性和方法分别进行赋值和初始化 
}

3、父类 Animal 执行构造函数前也是分配存储空间 -> 到其构造函数 -> 创建默认的属性 -> 发现挖槽我已经没有父类了,这个时候就给它的默认的属性赋值和方法的初始化。

4、接着执行构造函数余下的部分,结束后跳转到子类 Dog 的构造函数。

5、子类 Dog 对默认属性和方法分别进行赋值和初始化,接着完成构造函数接下来的部分。

一、为什么要执行父类 Animal 的构造方法才继续子类 Dog 的属性及方法赋值?

因为子类 Dog 的非静态变量和方法的初始化有可能使用到其父类 Animal 的属性或方法,所以子类构造默认的属性和方法之后不应该进行赋值,而要跳转到父类的构造方法完成父类对象的构造之后,才来对自己的属性和方法进行初始化。

这也是为什么子类的构造函数显示调用父类构造函数 super() 时要强制写在第一行的原因,程序需要跳转到父类构造函数完成父类对象的构造后才能执行子类构造函数的余下部分。

二、为什么对属性和方法初始化之后再执行构造函数其他的部分?

因为构造函数中的显式部分有可能使用到对象的属性和方法。

Tips:其实这种初始化过程都是为了保证后面资源初始化用到的东西前面的已经初始化完毕了。很厉害,膜拜 Java 的父亲们。

说了这么多还是来个例子吧。

这里注意 main 函数也是一个静态资源,执行 Dog 类的 main 函数就是调用 Dog 的静态资源。

实例


//父类Animal class Animal { /*8、执行初始化*/ private int i = 9; protected int j; /*7、调用构造方法,创建默认属性和方法,完成后发现自己没有父类*/ public Animal() { /*9、执行构造方法剩下的内容,结束后回到子类构造函数中*/ System.out.println("i = " + i + ", j = " + j); j = 39; } /*2、初始化根基类的静态对象和静态方法*/ private static int x1 = print("static Animal.x1 initialized"); static int print(String s) { System.out.println(s); return 47; } } //子类 Dog public class Dog extends Animal { /*10、初始化默认的属性和方法*/ private int k = print("Dog.k initialized"); /*6、开始创建对象,即分配存储空间->创建默认的属性和方法。 * 遇到隐式或者显式写出的super()跳转到父类Animal的构造函数。 * super()要写在构造函数第一行 */ public Dog() { /*11、初始化结束执行剩下的语句*/ System.out.println("k = " + k); System.out.println("j = " + j); } /*3、初始化子类的静态对象静态方法,当然mian函数也是静态方法*/ private static int x2 = print("static Dog.x2 initialized"); /*1、要执行静态main,首先要加载Dog.class文件,加载过程中发现有父类Animal, *所以也要加载Animal.class文件,直至找到根基类,这里就是Animal*/ public static void main(String[] args) { /*4、前面步骤完成后执行main方法,输出语句*/ System.out.println("Dog constructor"); /*5、遇到new Dog(),调用Dog对象的构造函数*/ Dog dog = new Dog(); /*12、运行main函数余下的部分程序*/ System.out.println("Main Left"); } }

测试输出结果为:

static Animal.x1 initialized
static Dog.x2 initialized
Dog constructor
i = 9, j = 0
Dog.k initialized
k = 47
j = 39
Main Left

原文地址:https://blog.csdn.net/qq_25665807/article/details/74452181

有关Java 对象初始化详细过程的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  3. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  4. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  5. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  6. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  7. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  8. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  9. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  10. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

随机推荐