简单了解java类的初始化以及类的实例化

前言

上一篇我们知道了一个类的生命周期是:加载->验证->准备->解析->初始化->使用->卸载。
当初始化完成以后,一个类所有的类变量(被static修饰的变量)都被赋值。但是未被static修饰的成员变量又是何时被赋值的呢?

一个类何时会被初始化

一个类何时被初始化可以分为以下几类:

  • 1.创建类的实例(new)。
  • 2.访问某个类或接口的静态变量,或者对该静态变量赋值。
  • 3.调用类的静态方法。
  • 4.通过反射方式执行以上三种行为。
  • 5.初始化子类的时候,会触发父类的初始化。
  • 6.Java虚拟机启动时被标明为启动类的类。(有main方法的类)
  • 7.JDK 1.7开始提供的动态语言支持。(了解即可)

我们来说道说道第3点和第6点

我们平常在使用main方法和调用某个类的静态方法的时候,是不是发现,并不能直接调用静态方法和main方法所在类的非静态方法和非静态变量。

可是明明不是说了在调用静态方法和执行main方法的时候,所在的类已经被初始化了吗?

是的!在上一章节我们就说,类初始化的时候会按照我们编写代码的顺序为类变量(static修饰的变量)进行赋值。注意哦,此时这个类仅仅只有静态变量被正确赋值了哦。

public class People{
  private static String name ="lisi";
  private int age = 18;

  static{
    name ="zhangsan";
  }
}

如上述代码,在该类被初始化之后,首先按照代码顺序将类变量(被static修饰的变量)赋值。所以name被赋值"lishi",然后再将name赋值为 "zhangsan"。此时age并没有值,直接直接调用会报错。

一个类何时被实例化

上一个章节中,我们明白了加载->验证->准备->解析->初始化的具体细节。

当初始化完成后,一个类的静态变量被正确赋值。如果这个对象是被new出来的。那么在初始化完成之后会进入实例化阶段。

实例化的具体步骤为:

父类非静态成员初始化语句(包括代码块,按照在类定义中的顺序执行)->父类构造函数->子类非静态成员初始化语句(包括代码块,按照在类定义中的顺序执行)->子类构造方法()

注意哦!
如果这个类有父类不光是先实例化父类。整体流程如下:
1. 加载父类
1.1 为静态属性分配存储空间并赋初始值
1.2 执行静态初始化块和静态初始化语句(从上至下)
2. 加载子类
2.1 为静态属性分配存储空间
2.2 执行静态初始化块和静态初始化语句(从上至下)
3. 加载父类构造器
3.1 为实例属性分配存数空间并赋初始值
3.2 执行实例初始化块和实例初始化语句
3.3 执行构造器内容
4. 加载子类构造器
4.1 为实例属性分配存数空间并赋初始值
4.2 执行实例初始化块和实例初始化语句
4.3 执行构造器内容

实例化的内存模型

到这里,我们就非常的清楚为什么在静态方法中不能直接调用非静态的变量,因为此时的非静态变量并没有被赋值。

以前我在学习的时候,new一个对象出来大家总是在说,我们初始化了这个对象,然后balabala。。。

导致我对于初始化和实例化里的静态变量和非静态变量何时被赋值一直有点模糊。new一个对象出来准确的来说是进行了初始化和实例化两个步骤,这样应该就会清晰了很多。

初始化完成以后,类被存放在方法区,注意哦,此时并没有存放在堆内存中。

只有当对象实例化进入堆内存中以后才会对非静态变量进行初始化赋值。

总结

这下总算吧一个类的初始化和实例化的细节搞明白了,关于文中的方法区,堆内存等内容,下一节再具体分析。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java基础教程之基本类型数据类型、包装类及自动拆装箱

    前言 我们知道基本数据类型包括byte, short, int, long, float, double, char, boolean,对应的包装类分别是Byte, Short, Integer, Long, Float, Double, Character, Boolean.关于基本数据类型的介绍可参考Java基础(一) 八大基本数据类型 那么为什么需要包装类? JAVA是面向对象的语言,很多类和方法中的参数都需使用对象,但基本数据类型却不是面向对象的,这就造成了很多不便. 如:List<in

  • java中List集合及其实现类的方法详解

    List集合_List接口介绍 特点 1).有序的: 2).可以存储重复元素: 3).可以通过索引访问: List<String> list = new ArrayList<>(); list.add("张无忌"); list.add("张三丰"); list.add("章子怡"); list.add("章子怡");//OK的,可以添加 for(String s : list){ System.out.

  • 一文读懂Jvm类加载机制

    前言 一个月没更新了,这个月发生了太多的事情,导致更新的频率大大降低,不管怎样收拾心情,技术的研究不能落下! jvm作为每个java程序猿必须了解的知识,博主推荐一本书<深入理解Java虚拟机>,以前博主在学校的时候看过几遍,每一次看都有新的理解.加上工作了也有一年多的时间了,有必要好好总结一番~ 什么是jvm 平常我们编写代码都是编写的.java文件,怎么部署到机器上运行呢?通过打jar包或者war包,然后部署运行. 如果看过jar包的内容那么就能知道,我们写的.java文件全部被编译成了.

  • Java实体类中Set按照对象的某个字段对set排序

    背景: User实体类 有个属性是 Set<PositionChange> 职位变更字段 如下: PositionChange实体类 有个属性是positionStartDate 什么时候开始任职此职务的字段 现在有一个需求,想在查询出 User这个对象的时候 ,可以获取到 Set<PositionChange>中 用户最新任职的一条岗位记录,也就是展示当前用户所处的岗位信息. 但是,Set始终的无序的,想要取出Set中PositionChange的positionStartDat

  • java中File类的构造函数及其方法

    1.IO流(Input Output) IO流技术主要的作用是解决设备与设备之间的数据传输问题,比如:硬盘的数据--读取到-->内存中 内存的数据--读取到-->硬盘中 键盘上的数据--读取到-->内存中 2.IO流技术的运用场景 导出报表.上传大头照.下载.解析xml文件.....等等 (数据保存到硬盘,该数据可以做到永久性保存.数据一般以文件的形式保存到硬盘上.sun使用一个File类来描述文件或者文件夹) 3.File类的构造函数(方法) File(String pathname)

  • Java中List add添加不同类型元素的讲解

    问题: 今天看java的list ,list后面的<> 里面可以填多种类型,但是如果不填写类型那就默认为 Object 类型. 所有我门 add 到 list 里的 数据都会被转换成 Object 类型. 而当我门再从list 中取出该数据时,就会发现数据类型已经改变. 解答 java集合中 能添加不同类型的元素其实不同类型的元素,只是地一定层次是不同元素,根本上都继承于Object类,本质上还是同一类型的元素. List<Object> list = new ArrayList&

  • 简单了解java中静态初始化块的执行顺序

    这篇文章主要介绍了简单了解java中静态初始化块的执行顺序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在java中,其应该是先于所有的方法执行. 下面是测试代码: public class Test1 { static{ System.out.println("执行静态初始化块test1..."); } { System.out.println("执行初始化块test1"); } public Test1(){

  • 简单了解java类的初始化以及类的实例化

    前言 上一篇我们知道了一个类的生命周期是:加载->验证->准备->解析->初始化->使用->卸载. 当初始化完成以后,一个类所有的类变量(被static修饰的变量)都被赋值.但是未被static修饰的成员变量又是何时被赋值的呢? 一个类何时会被初始化 一个类何时被初始化可以分为以下几类: 1.创建类的实例(new). 2.访问某个类或接口的静态变量,或者对该静态变量赋值. 3.调用类的静态方法. 4.通过反射方式执行以上三种行为. 5.初始化子类的时候,会触发父类的初始

  • 简单分析Java线程编程中ThreadLocal类的使用

    一.概述   ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为ThreadLocalVar更加合适.线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突.   从线程的角度看,每个线程都保持一个对

  • 简单了解Java类成员初始化顺序

    这篇文章主要介绍了简单了解Java类成员初始化顺序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 类中包含7中成员: 1.静态变量 static 2.final静态常量 final static 3.静态代码块 static{} //多个代码块顺序执行 4.普通变量 5.普通代码块 {} //多个代码块顺序执行 6.构造方法 7.普通方法 类中成员初始化方式(排出7): 非继承类中: 首先执行1/2/3,执行顺序为顺序执行(谁在前先执行谁).

  • 详解Java的构造方法及类的初始化

    目录 一. 利用构造方法给对象初始化 1. 构造方法的概念 2. 构造方法的特性 3. 子类构造方法 4. 避免在构造方法中调用重写的方法 二. 对象的默认初始化 三. 就地初始化对象 四. 类的初始化顺序 1. 普通类(没有继承关系) 2. 派生类( 有继承关系) 一. 利用构造方法给对象初始化 1. 构造方法的概念 构造方法(也称为构造器)是一个特殊的成员方法,其名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次. 构造方法的作用就是给对象中的成员进行初

  • Java类的初始化实践分析

    本文实例讲述了Java类的初始化.分享给大家供大家参考,具体如下: 一 点睛 1 下面6种方式,系统会初始化该类或接口. 创建类的实例.为某个类创建实例的方式包括使用new操作符来创建实例,通过反射来创建实例,通过反序列化的方式来创建实例. 调用某个类的静态方法. 访问某个类或接口的静态属性,或为该静态属性赋值. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象.例如代码:Class.forName("Person"). 初始化某个类的子类,当初始化某个类的子

  • 简单了解java获取类的3种方式

    这篇文章主要介绍了java获取类的3种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.Class.forName("全类名") 将字节吗文件加载进内存,返回Class对象,多用于配指文件,将类名定义在配置文件中,便于利用java的反射机制生成类对象,加载类. //加载一个用户实体类UserBean Class c1 = Class.forName("com.test.UserBean"): 2.类名.c

  • Java类的初始化顺序知识点总结

    对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器. 初始化顺序图示: 我们也可以通过下面的测试代码来验证这一点: package com.trs.oop; /** * 类的初始化顺序 * 静态变量->静态初始化块->变量->初始化块->构造器 * @author xiayunan * @date 2018年7月5日 * */ public class InitialOrderTest { /

  • 简单谈谈Java类与类之间的关系

    类与类之间最常见的关系主要有三种:依赖(uses-a).聚合(has-a)和继承(is-a). 下面以在线书店订单系统为例,来详细的讲述这三种关系的概念. 在线书店订单系统的主要功能是:注册用户可以登录到网上书店选购图书,在线填写订单,并支付购书款.书店确认已经收到购书款时,按用户留下的地址邮寄图书.可以在这个系统中建立几个类,有图书(book).账户(account).订单(order).地址(address)等,如下图所示: 依赖(uses-a) 依赖关系是类中最常见的关系,例如订单类(or

  • Java 中的 Unsafe 魔法类的作用大全

    Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别.不安全操作的方法,如直接访问系统内存资源.自主管理内存资源等,这些方法在提升Java运行效率.增强Java语言底层资源操作能力方面起到了很大的作用. 但是,这个类的作者不希望我们使用它,因为我们虽然我们获取到了对底层的控制权,但是也增大了风险,安全性正是Java相对于C++/C的优势.因为该类在sun.misc包下,默认是被BootstrapClassLoader加载的.如果我们在程序中去调用这个类的话,我们使用的类加载

随机推荐