第九章:构造器与垃圾收集器-对象的前世今生

2023-11-03

该系列文章系个人读书笔记及总结性内容,任何组织和个人不得转载进行商业活动!

第九章:构造器与垃圾收集器-对象的前世今生

对象有生有死:

    必须对对象的生命周期负责;
    何时创建、何时销毁(不是消灭、只是放弃),由垃圾收集器(GC)将它蒸发掉,回收所占空间;
本节述及堆、栈、范围、构造器、超级构造器、空引用等内容;

Java中重要的两种内存区域:

    对象的生存空间堆(heap);
    方法调用及变量的生存空间(stack);
当JVM启动时,他会从底层的操作系统取得一块内存,并以此区段来执行Java程序;
 
所有的对象都存活在可垃圾回收的堆上;
局部变量又叫栈变量;

实例变量和局部变量:

    实例变量是被声明在类而不是方法里面;代表每个独立对象的’字段’;
    实例变量存在于所属的对象中;
    
    局部变量和方法的参数都是被声明在方法中;他们是暂时的,且生命周期只限于方法被放在栈上的这段期间;
调用方法是一个压栈的过程,方法执行完之后,弹出栈;
    实际压栈的是堆栈块,它带有方法的状态,包括执行到哪一行程序以及所有的局部变量;
非primitive的局部变量只是保存对象的引用而已,存在栈上;对象本身存在堆上;
认识堆栈,对理解变量的有效范围(scope)、对象的建立、内存管理、线程(thread)和异常处理很有用;

要点:

1.我们关系栈和堆两种内存空间;
2.实例变量声明在类中方法之外的地方;
3.局部变量声明在方法或方法的参数上;
4.所有的局部变量都存在栈上相对应的堆栈块中;
5.对象引用和primitive主数据类型的局部变量都是放在栈上的;
6.不管是实例变量还是局部变量,对象本身都会在堆上;

实例变量存在于对象所属的堆空间上:

    primitive主数据类型的实例变量,Java会依据其大小留下空间;
    对于引用类型的实例变量,Java会留下引用所需的空间;
    
实例变量所需的空间是在对象上;
若实例变量引用类型只声明未赋值,则存对象的堆空间中只会留下引用变量的空间;直到被赋值,该引用变量所指向的内存中在会被赋值的对象占用;

构造对象的过程:

    new Dog();
其实是在调用Dog的构造函数:
    构造函数像方法,但不是方法;
    它带有new的时候会执行的程序代码;(初始化时会执行)
   
唯一能够调用构造函数的办法就是新建一个类;(严格说来,是唯一在构造函数之外能够调用构造函数的方式)
当没有自己写构造函数时,编译器会帮你写一个;

构造函数:

    没有返回类型;
    函数名与类名同;
构造Dog:
    构造函数的一项关键特征是它会在对象能够被赋值给引用之前就执行,这代表你可以有机会在对象被使用之前介入;
新建Dog状态的初始化:
    大部分人都使用构造函数来初始化对象的状态,即给对象的实例变量赋值;
    使用构造函数来初始化Dog状态,最好方式是:把初始化的程序代码放在构造函数中,并把构造函数设置成需要参数的;
构造函数不会被继承!
有了需要参数的构造函数,还要注意——最好要有不需要参数的构造函数(但也确实存在没有无参数的构造函数的类);
    编译器会在你没有设定构造函数时帮你写出一个没有参数的构造函数;
如果一个类有一个以上的构造函数,这代表他们是重载的,他们的参数也一定不一样(和方法重载是相同的);

要点:

1)实例变量保存在所属的对象中,位于堆上;
2)如果实例变量是一个对对象的引用,则引用和对象都是在堆上的;
3)构造函数会在新建对象的时候执行程序代码;
4)构造函数必须与类名同名且没有返回类型;
5)你可以用构造函数来初始化被创建对象的状态;
6)若没写出构造函数,编译器会帮你创建一个;
7)默认的构造函数是没有参数的;
8)如果你写了构造函数,编译器就不会调用;
9)最好有无参数的构造函数让人可以选择使用默认值;
10)重载的构造函数是指多个构造函数之间的关系;
11)两个构造函数的参数必须不同;
构造函数可以是共有的、不指定的、私有的;
    私有的构造函数不是不能存取,它代表该类以外不能存取;

父类的构造函数:

    在创建新对象时,所有继承下来的构造函数都会执行;
    new的时候,会启动构造函数连锁反应——构造函数链(Construction Chaining);(就算是抽象类也有构造函数,虽然抽象类不能new,但会在子类创建出实例时执行)
    使用super可以调用父类的构造函数;
构造函数执行的时候,第一件事就是去执行父类的构造函数;这回连锁反映到Object这个类为止;
构造函数连反应的过程和方法调用类似,也是一个不断压栈、退栈的过程;
示例:(Code-AnimalDrive.java)
public class Animal{
    private String name;
    private int age;
    
    public void setName(String aName){
        name = aName;
    }
    public String getName(){
        return name;
    }
    public void setAge(int aAge){
        age = aAge;
    }
    public int getAge(){
        return age;
    }
    public Animal(){
        name = "def";
        age = 1;
        System.out.println("initial animal");

    }
    public Animal(String aName,int aAge){
        name = aName;
        age = aAge;
        System.out.println("initial animal with paras");
    }
}
public class Dog extends Animal{
    public Dog(){
        super("haha",5);
        System.out.println("initial dog");
    }
    public void eat(){
        System.out.println("dog eat");
    }
}
public class AnimalDrive{
    public static void main(String[] args){
        Animal ani = new Animal();
        
        Dog dog = new Dog();
        dog.eat();
        
        System.out.println(dog.getName());
        System.out.println(dog.getAge());
    }
}
这个实例也展示了如何调用父类的构造函数;

调用父类构造函数的唯一方法就是调用super();

    在你的构造函数中调用super()会把父类的构造函数放在堆栈的最上方;
    如果我们没有调用super(),编译器会帮我们加上super()的调用;(这个可以修改示例代码验证下)
    这里需要注意的是,编译器帮忙加的一定是没有参数的版本,假如父类有多个重载版本的构造函数,也只有无参数的这个版本会被调用到;
    如果没有这个版本,那么就需要主动调用下其他版本,这也是建议提供无参数构造函数的原因;
每个子类的构造函数会立即调用父类的构造函数;对super()的调用必须是构造函数的第一个语句;
super(para)可以接收参数,对应父类有参数的构造函数的调用;(仔细看先上边的示例,展示了子类如何通过super(name,age)来设置父类的私有变量)

从某个构造函数调用重载版的另一个构造函数:

    需要使用this,它表示对对象本身的引用;
    this()只能用在构造函数中,且必须是第一行语句;
    每个构造函数可以选择调用super()或this(),但不能同时使用;
即:
1)使用this()来从某个构造函数调用同一个类的另外一个构造函数;
2)this()只能用在构造函数中,且必须是第一行语句;
3)super()与this()不能兼得;
对象会存活多久——对象生命周期要看引用变量的生命周期而定,那变量到底会活多久?
1)局部变量只会存活在声明该变量的方法中;
2)实例变量的寿命和对象相同;

life和scope:

    lift:只要变量的堆栈块还在堆栈上,局部变量就还活着;
    scope:局部变量的范围只限于声明它的方法之内;(方法中再调用其他方法,变量还活着,但范围会变化到新的方法中,知道新的方法完毕,范围再跟着回来)
       
也就是说:局部变量只能在声明它的方法执行中才能被使用;
当对象最后一个引用消失时就会变成可回收的;

有三种方式可以释放对象的引用:

1)引用永久性的离开范围;
    void go(){ Dog dog = new Dog(); }
2)引用被赋值到其他的对象上;
3)直接将引用设定为null;

null的真相:

    null是代表“空”的字节组合(只有JVM才知道是什么);
    不能对null引用进行操作(方法调用等);对null引用使用圆点运算符会在执行器遇到NullPointerException这样的错误;
    当变量被置为null时,就只好等着被垃圾回收,原来的地方也会让出来给别人用;
    

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第九章:构造器与垃圾收集器-对象的前世今生 的相关文章

  • 无法访问类型的封闭实例。 [复制]

    这个问题在这里已经有答案了 整个代码是 public class ThreadLocalTest ThreadLocal
  • 何时/为何使用/定义接口[重复]

    这个问题在这里已经有答案了 可能的重复 何时最好使用 java 中的接口 https stackoverflow com questions 2586389 when best to use an interface in java Hi
  • 多线程环境下如何更好的使用ExecutorService?

    我需要创建一个库 其中包含同步和异步方法 executeSynchronous 等待直到有结果 返回结果 executeAsynchronous 立即返回一个 Future 如果需要 可以在其他事情完成后进行处理 我的图书馆的核心逻辑 客户
  • JavaFX Platform.runLater 的使用以及从不同线程访问 UI

    我有几个问题Platform runLater 我有一个 JavaFX 应用程序类 在这个类中 我运行一个线程 该线程从网络套接字读取数据 现在当我创建一个新的Stage在线程内部 系统抛出异常 JavaFX 事件调度程序线程和我的网络读取
  • 设置 SWT Shell 的默认字体

    有没有办法为整个 Shell 设置默认字体 以便任何新控件都将使用相同的字体 看来现在我必须为我创建的每个控件设置字体 这导致了太多的冗余 默认使用的字体由平台选择 请参阅中的其他信息 类字体 SWT 标准小部件工具包 http book
  • 实现与扩展:何时使用?有什么不同?

    请用易于理解的语言进行解释或提供某些文章的链接 extends is for 延伸一类 implements is for 实施一个接口 接口和常规类之间的区别在于 在接口中您不能实现任何声明的方法 只有 实现 接口的类才能实现方法 C 中
  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • 初级 Java 计数器代码

    我的教授希望我这样做 使用下面的 Counter 接口写入多个可互换计数器 public interface Counter Current value of this counter int value Increment this co
  • 在 TestNG 中运行多个类

    我正在尝试自动化一个场景 其中我想登录一次应用程序 然后进行操作而无需再次重新登录 考虑一下 我有在特定类的 BeforeSuite 方法中登录应用程序的代码 public class TestNGClass1 public static
  • Java Spring 应用程序存在内存泄漏。系统非堆内存不断增加

    我已使用 yourkit 分析器监视我的 Web 应用程序 保留最大大小的主要对象是 SessionFactoryImpl webappclassloader 和 CGlib 对象显示 spring crone调度程序会导致内存泄漏吗 我尝
  • 是否可以从另一个方法传递 args[] 来调用 main 方法?

    我试图从另一个传递参数的方法调用类的主要方法 就像从命令行运行该类时一样 有没有办法做到这一点 您可以致电main方法就像您调用任何其他 静态 方法一样 MyClass main new String arg1 arg2 arg3 Exam
  • 如何在 Struts 2 OGNL 中将参数传递给方法调用

    我想使用属性作为对象方法的参数
  • 如何使用 Guava 连接字符串?

    我写了一些代码来连接字符串 String inputFile for String inputLine list inputFile inputLine trim 但我不能使用 连接 所以我决定使用 Guava 所以我需要使用Joiner
  • HTTP PUT 在 Java 中上传文件

    Edit 我想我已经弄清楚如何执行二进制数据部分 仔细检查代码 但我很确定我做对了 现在 当我尝试按照中所述完成上传时遇到新错误Vimeo API 文档 http vimeo com api docs upload streaming Ed
  • Java ConcurrentModificationException [重复]

    这个问题在这里已经有答案了 当删除倒数第二个元素时 没有 ConcurrentModificationException List
  • 是否可以为 azure blob 存储中的给定目录生成具有写入权限的 SAS(共享访问签名)

    我们的 blob 存储帐户结构 容器名称 simple 在这个容器内我们有 blob aa one zip aa two zip bb ss zip bb dd zip 是否可以生成对aa 目录 有写权限 但对bb 目录 没有访问权限的SA
  • 在Java中多次读取System.in会导致IOException?

    我正在尝试创建一个小命令行游戏来强化我在过去几个月中在 Java 中学到的一些东西 我正在尝试创建一个名为 readInput 的方法 它返回一个我可以一次又一次调用的字符串 第一次它工作正常 但第二次它会导致 IO Exception 如
  • 找不到符号assertEquals

    我正在尝试为计算器编写第一个单元测试 但 NetBeans 说它找不到该符号assertEquals和注释 Test 我应该包括一些东西吗 我正在使用 NetBeans 7 3 1 和 W7 package calculator impor
  • 将带有 webapp 的 WAR 部署到 Maven 中央存储库是否有意义?

    这样做有意义吗 如果是 我在哪里可以找到使用简单的 Web Hello World 执行此操作的示例 当人们从 Maven 执行 Web 应用程序时 他们会使用 Jetty 来运行它吗 我想 tomcat 太重了 任何帮助将不胜感激 谢谢
  • JMockit - 初始化问题

    当我使用以下测试时 我收到警告 警告 JMockit 是按需初始化的 这可能会导致某些测试失败 请检查文档以获取更好的初始化方法 这是我的测试实现 package test import static mockit Mockit impor

随机推荐

  • 把字符串转换成整数(最详细解答)

    题目要求 分析 把一个一个字符以整数的形式来进行输出 需要考虑相互转化的问题 不能使用库函数 首尾会有空格 进行去空格操作 可以减少不必要的判断 区分正负正数 结果可能会越界 题目给的是Integer类型 当超过最大范围或者小于最小范围 有
  • hihoCoder #1000: A+B

    时间限制 1000ms 单点时限 1000ms 内存限制 256MB 描述 求两个整数A B的和 输入 输入包含多组数据 每组数据包含两个整数A 1 A 100 和B 1 A 100 输出 对于每组数据输出A B的和 样例输入 1 2 3
  • 单元测试(二)—— Jest结合Vue-test-utils入门实战

    文章目录 前言 介绍 语法实战 Shallow Rendering DOM结构 测试Props 总结 前言 公共组件 在我们编写测试用例之前 首先需要确认我们的目标组件到底是什么 我的理解为 在我们的项目中通常会分为两种类型的组件 一种为业
  • JAVA学习路线,面试复习方向指引

    前言 好久没有沉下心学习一波了 总结了一份简单的java学习内容 包含java开发大概的技术栈 后续每个部分寻找一些面试题专项学习 本篇先写一个大概的知识概括 后面逐渐加内容 慢慢丰满 有一起学习的朋友欢迎交流 共同进步 学问须学 不学则殆
  • 二、Xshell如何连接虚拟机

    Xshell如何连接虚拟机 安装Vmware时 会自动在windows安装虚拟网卡 在Vmware中设定虚拟交换机网段 圈定主机能使用的ip地址 虚拟网卡会自动获取一个ip地址 创建linux服务器时 选定网络模式为NAT ip地址为该网段
  • 05JWT实现微服务鉴权

    05 JWT 实现微服务鉴权 5 1 什么是微服务鉴权 我们之前已经搭建过了网关 使用网关在系统中比较适合进行权限校验 那么我们可以采用JWT的方式来实现鉴权校验 5 2 JWT JSON Web Token JWT 是一个非常轻巧的规范
  • STM32 USB AUDIO教程——导读

    STM32 USB AUDIO教程 基于正点原子的STM32F407探索者开发板 通过CUBEMX 移植等方式实现USB音频播放speaker和USB音频录制mic等功能 资料篇 主要是X CUBE USB AUDIO资料的概述和翻译 基础
  • 阿里云赵明山:详解灵活可插拔的渐进式发布框架OpenKruise Rollout

    嘉宾 赵明山 随着K8s及云原生理念的普及 尤其是在持续部署流水线出现后 渐进式交付为互联网应用提供了基础设施和实现方法 2022年7月27日 在由开放原子开源基金会主办的 2022开放原子全球开源峰会 上 阿里云技术专家 OpenKrui
  • 基于ISO13400(DoIP)实现车辆刷写,你知多少?

    近年来 基于以太网实现车辆高带宽通讯无疑是整车研发中人们热议的话题 无论是车内基于车载以太网减少线束成本 实现ADAS 信息娱乐系统等技术 还是基于新的电子电气架构以及远程诊断需求 为实现以太网诊断 DoIP 各家OEM都投入大量人力 物力
  • 【100天精通python】Day35:GUI界面编程_一文掌握Tkinter基本操作

    目录 专栏导读 1 GUI 编程概述 1 1 为什么需要GUI 1 2 常见的GUI编程工具和库 1 3 GUI应用程序的组成和架构 2 使用Tkinter 库 进行GUI编程 2 1 使用Tkinter库进行GUI编程的基本流程 2 2
  • 虚拟机网络适配器的三种模式详解及其配置

    VMWare中网络适配器的三种模式详解 关于虚拟机下Linux下ping www baidu com 出现 ping unknown host www baidu com问题的解决 有可能是因为网络适配器未正常配置 本文参照文章 https
  • Linux应用编程(系统信息与系统资源)

    在应用程序当中 有时往往需要去获取到一些系统相关的信息 譬如时间 日期 以及其它一些系统相关信息 本章将向大家介绍如何通过 Linux 系统调用或 C 库函数获取系统信息 譬如获取系统时间 日期以及设置系统时间 日期等 除此之外 还会向大家
  • Nacos介绍以及使用

    目录 一 概述 1 1 Nacos是什么 能干嘛 1 2 去哪下载 1 3 各个注册中心比较 二 Nacos作为服务注册中心 2 1 基于Nacos的服务提供者 2 2 基于Nacos的服务消费者 三 Nacos作为服务配置中心 3 1 N
  • 基于深度学习的海上雷达数据质量管控自动化技术

    文章作者Rune Gangeskar任职于Miros公司 目标是设计一套Wavex传感器系统 如何精准测量波浪 洋流 以及对水航速 并使用深度学习网络来自动辨识测量下取得的雷达数据 进一步提升Wavex系统的表现与可靠度 一 总体简介 对海
  • Java实现不规则软件版本号比较大小

    背景 最近由于需要比较两个版本号 从网上寻找的例子出现了问题 因此单独写一个不规则的版本号比较方法 代码 如果version1大于等于version2就返回true 可以根据自己需要进行调整 public static boolean co
  • 使用 Simulink 进行 STM32 编程

    目录 介绍 所需材料 步骤 1 在MATLAB中设置STM32 MAT软件路径 步骤 2 在STM32CubeMX中创建一个项目 步骤 3 配置时钟和 GPIO 引脚 步骤 4 项目经理并生成代码 步骤 5 在 Simulink 中创建模型
  • Java多线程——线程同步

    1 不安全的买票 不安全的买票 线程不安全 有负数或者多人买到同一张票 public class UnsafeBuyTicket public static void main String args BuyTicket buyTicket
  • $ 与 $$(*) 是什么?

    前言 今天在阅读一篇文章 小伙伴遇到这个问题说不想干前端了 一次Chrome翻译造成的玄学bug 主要内容是说翻译插件引发页面的react报错 文章中用 去获取报错页面所有的dom标签和正常无报错页面的dom标签 再进行对比来定位问题 具体
  • webform jquery ajax,ajax - Asp.net webform, jquery - Stack Overflow

    I m working on a project of estimation for my office I m using Ajax Autocomplete in Visual Studio 2017 The following cod
  • 第九章:构造器与垃圾收集器-对象的前世今生

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 第九章 构造器与垃圾收集器 对象的前世今生 对象有生有死 必须对对象的生命周期负责 何时创建 何时销毁 不是消灭 只是放弃 由垃圾收集器 GC 将它蒸发掉 回收所占空