第五章 初始化与清理(下)

2023-11-02

                              第五章 初始化与清理
         现在总结的东西很多都需要用代码来帮助理解了,所以会有大量的测试代码,不过这中方式非常有用,如果认真敲过一遍之后,并且将这些代码弄清楚了,我相信你一定会对书中描述的内容有一个更清楚的认识。我是在eclipse工具上进行测试的,这里边的代码可以之间粘贴运行,不过对于程序员来说还是自己敲一遍吧,效果会更好。
5.5  清理 : 终结处理和垃圾回收
      程序员都了解初始化的重要性,但常常会忘记同样也重要的清理工作。Java有垃圾回收器负责回收无用对象占据的内存资源。但是,垃圾回收器只知道释放那些经过new分配的内存,如果你的对象(并非使用new)获得了一块“特殊”的内存区域,则垃圾回收器就不知道该如何释放这块“特殊”内存。为了应对这种情况,Java允许在类中定义一个名为finalize()的方法。这个方法的工作原理:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是你打算用finalize(),就能在垃圾回收时刻做一些重要的清理工作。
      注意:在Java中   
               1、对象可能不被垃圾回收。
               2、垃圾回收并不等于“析构”。(析构是在c++里出现的一个概念,就是在c++中要销毁对象必须使用析构函数)
5.5.1 finalize()的用途何在
        这里需要记住第三点:
        3、垃圾回收只与内存有关
          也就是说,使用垃圾回收器的唯一原因是为了回收程序不再使用的内存。所以对于与垃圾回收相关的任何行为来说(尤其是finalize()方法),它们也必须同内存及其回收有关。
5.5.2  你必须实施清理
        要清理一个对象,用户必须在需要清理的时刻调用执行清理动作的方法。无论是“垃圾回收”还是“终结”,都不保证一定会发生。如果Java虚拟机(JVM)并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。
5.5.3  终结条件
        通常,不能指望finalize(),必须创建其他的“清理”方法,并且明确地调用他们。
     class Book{
     boolean checkedOut = false;
     Book(boolean checkOut){
          checkedOut=checkOut;
     }
     void checkIn(){
          checkedOut=false;
     }
     protected void finalize(){
          if(checkedOut){
               System.out.println("error : checked out");
               try {
                    super.finalize();
               } catch (Throwable e) {
                    System.out.println("Throwable");
                    e.printStackTrace();
               }
          }
     }
}
public class TerminationCondition {
     public static void main(String[] args) {

          Book novel = new Book(true);
          novel.checkIn();
          new Book(true);
          System.gc();
     }

}
运行结果:error : checked out
因为在main()方法中,由于程序员错误,有一本书未被签入。要是没有finalize()来验证终结条件,将很难发现这种缺陷。
5.5.4  垃圾回收器如何工作
5.6  成员初始化
     Java尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,Java以编译时错误的形式来贯彻这种保证。
     例如:我们定义成员变量的时候并没有给它们赋值,但是编译器会给它们初始化默认值,比如 int i;在编译的时候初始值就是0。但是在方法中就不行了:  void f(){
             int i;
             i++;     //错误,i没有被初始化
}
5.6.1  指定初始化
       如果想为某个变量赋初值,在基本数据类型中可以直接赋值。例如:int i=1;  char ch='x' ; boolean bool=true; 
       如果是其他类型的对象则可以创建一个对象来初始化:Depth d=new Depth();
       当然也可以通过调用方法来初始化:int i=f();
5.7  构造器初始化
      public class Counter {
     int i;
     public Counter() {
          i=7;
     }
该程序中i首先会被置零,然后变成7。
5.7.1  初始化顺序
      在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散步与方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
5.7.2  静态数据的初始化
       无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值;如果它是一个对象的引用,那么它的默认初始化值就是null。
class Bowl{
     Bowl(int marker){
          System.out.println("Bow1("+marker+")");
     }
     void f1(int marker){
          System.out.println("f1("+marker+")");
     }
}
class Table{
     static Bowl bowl1= new Bowl(1);
     Table(){
          System.out.println("Table()");
          bowl2.f1(1);
     }
     void f2(int marker){
          System.out.println("f2("+marker+")");
     }
     static Bowl bowl2=new Bowl(2);
}
class Cupboard{
     Bowl bowl3=new Bowl(3);
     static Bowl bowl4=new Bowl(4);
     Cupboard(){
          System.out.println("Cupboard");
          bowl4.f1(2);
     }
     void f3(int marker){
          System.out.println("f3("+marker+")");
     }
     static Bowl bowl5=new Bowl(5);
}
public class StaticInitialization {

     public static void main(String[] args) {
          System.out.println("createing new cupboard in main");
          new Cupboard();
          System.out.println("createing new cupboard in main");
          new Cupboard();
          table.f2(1);
          cupboard.f3(1);
     }
     static Table table=new Table();
     static Cupboard cupboard=new Cupboard();

}
运行结果:
Bow1(1)
Bow1(2)
Table()
f1(1)
Bow1(4)
Bow1(5)
Bow1(3)
Cupboard
f1(2)
createing new cupboard in main
Bow1(3)
Cupboard
f1(2)
createing new cupboard in main
Bow1(3)
Cupboard
f1(2)
f2(1)
f3(1)
由运行结果可以发现:初始化的顺序是先对静态对象(前提是得有对象被初始化时才会进行,就是说静态初始化只有在必要时刻才会进行),而后是“非静态”对象,然后才是构造器。
5.7.3  显式的静态初始化
       Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(有时也叫做“静态块”)。
     class Cup{
     Cup(int marker){
          System.out.println("cup("+marker+")");
     }
     void f(int marker){
          System.out.println("f("+marker+")");
     }
}
class Cups{
     static Cup cup1;
     static Cup cup2;
     static{
          cup1=new Cup(1);
          cup2=new Cup(2);
     }
     Cups(){
          System.out.println("cups ()");
     }
}
public class Explicitstatic {

     public static void main(String[] args) {
          System.out.println("inside main");
          Cups.cup1.f(99);
     }
//     static Cups cups1=new Cups();
}
运行结果:
inside main
cup(1)
cup(2)
f(99)
      静态块跟静态初始化一样也只执行一次,当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员(即便从未生成过那个类的对象)。就会被执行。
5.7.4  非静态实例初始化
      Java中也有被称为实例初始化的类似语法,用来初始化每一个对象的非静态变量。例如:
      class Mug{
     Mug(int marker){
          System.out.println("Mug("+marker+")");
     }
     void f(int marker){
          System.out.println("f("+marker+")");
     }
}
public class Mugs {
     Mug mug1;
     Mug mug2;
     {
          mug1=new Mug(1);
          mug2=new Mug(2);
          System.out.println("mug1 & mug2 initialized");
     }
     Mugs(){
          System.out.println("Mugs()");
     }
     Mugs(int i){
          System.out.println("Mugs(int)");
     }

     public static void main(String[] args) {
          System.out.println("inside main()");
          new Mugs();
          System.out.println("new Mugs() completed");
          new Mugs(1);
          System.out.println("new Mugs(1) completed");

     }

}
运行结果:
inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed
从以上代码可以看出少了static关键字,所以会重复执行。
5.8  数组的初始化
     数组的初始化有几种方法:
     第一种:int [] a={a,b,c}   这种方式是你明确知道要初始化多少个数据,这种形式很有用,但缺点也很明显,就是更加受限。
     第二种 : int [] a = new a [n]   这种形式可以解决你不知道具体要多少数据的难题,使用时可以根据情况而定。
      
5.9  枚举类型
      在Java SE5中添加了一个看似很小的特性,即enum关键字,它使得我们在需要群组并使用枚举类型集时,可以很方便的处理。在很大程度上,可以将enum当作其他任何类来处理,事实上enum确实是类,并且具有自己的方法。enum有一个特别实用的特性,即ta3可以在switch语句内使用;
     enum Spiciness{
     NOT, MILD, MEDIUM, HOT, FLAMING
}
public class Burrito {
     Spiciness degree;
     public Burrito(Spiciness degree){
          this.degree=degree;
     }
     public void describe(){
          System.out.print("this burrito is ");
          switch (degree) {
          case NOT:
               System.out.println("not spicy at all");
               break;
          case MILD:
          case MEDIUM:
               System.out.println("A little hot");
               break;
          case HOT:
          case FLAMING:
          default:
               System.out.println("maybe too hot");
               break;
          }
     }
     public static void main(String[] args) {
          Burrito
          plain = new Burrito(Spiciness.NOT),
          greenChile=new Burrito(Spiciness.MEDIUM),
          jalapeno=new Burrito(Spiciness.HOT);
         
          plain.describe();
          greenChile.describe();
          jalapeno.describe();
          
     }

}
运行结果:
this burrito is not spicy at all
this burrito is A little hot
this burrito is maybe too hot
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第五章 初始化与清理(下) 的相关文章

  • sql server学习笔记——批处理语句、存储过程

    目录 批处理语句 1 批处理语句简介 示例一 示例二 存储过程 一 什么是存储过程 1 存储过程的简介 2 存储过程包含的内容 3 存储过程的优点 4 存储过程的分类 系统存储过程 用户定义存储过程 5 常用的系统储存过程 1 一般常用的存
  • 专访帝国软件的创造者:仍然在路上的80后

    全球的网站数量已经超过了一亿 并且还在以惊人的速度继续增长 CMS作为一种位于Web前端 Web 服务器 和后端办公系统或流程 内容创作 编辑 之间的软件系统为互联网应用的丰富和发展起到了至关重要的作用 最近我们注意到有一款口碑很好的CMS
  • Yii2 选择布局的方式

    方案1 控制器内成员变量 public layout false 不使用布局 public layout main 设置使用的布局文件 方案2 控制器成员方法内 this gt layout false 不使用布局 this gt layo
  • EMC 电磁兼容知识简易解析

    EMC基础知识 电磁兼容性 EMC Electromagnetic Compatibility 设备在共同的电磁环境中能一起执行各自功能的共存状态 即该设备不会由于受到处于同一电磁环境中其他设备的电磁发射导致不允许的降级 也不会使同一电磁环
  • iphone或安卓配置Charles抓包

    4个步骤完成iPhone配置Charles抓包步骤 Charles官网下载地址 Download a Free Trial of Charles Charles Web Debugging Proxy 1 连接到wifi 并设置代理地址 可
  • React传递参数的多种方式

    最常见的就是父子组件之间传递参数 父组件往子组件传值 直接用this props就可以实现 在父组件中 给需要传递数据的子组件添加一个自定义属性 在子组件中通过this props就可以获取到父组件传递过去的数据 父组件 render re
  • K-means算法的参数详解

    参数名称 默认值及输入类型 参数解释 algorithm 默认 Auto 有auto full和elkan三种选择 algorithm 优化算法的选择 有auto full和elkan三种选择 full就是一般意义上的K Means算法 e

随机推荐

  • java.security.InvalidKeyException: Illegal key size错误

    新使用了AES的256位密钥加解密 项目上线后发现生产在加密的时候报java security InvalidKeyException Illegal key size错误 而本地和测试环境都是没问题的 产生错误原因 为了数据代码在传输过程
  • 求生之路显示服务器指令大全手机,求生之路2指令大全 求生之路2指令怎么用? (7) _地图指令_游侠网...

    地图指令 c1m1 hotel 1 死亡中心1旅馆 c1m2 streets 1 死亡中心2街道 c1m3 mall 1 死亡中心3购物中心 c1m4 atrium 1 死亡中心4中厅 c2m1 highway 1 黑色狂欢节1高速公路 c
  • 正则校验-我需要的正则表达式知识

    正则校验 我需要的正则表达式知识 正则表达式由正则表达式引擎提供支持 不同编程环境有不同的正则表达式引擎 在实际使用正则表达式的过程中会有一些差别 什么是正则表达式 正则表达式是用于描述匹配复杂字符串规则的工具 一个正则表达式对应着一个文本
  • python glob通配符方式单/多层搜索文件/文件夹

    import os import glob 可以利用通配符进行文件的搜索获取 goal dir r D demo 遍历指定文件夹下所有文件或文件夹 for file in glob glob goal dir print file 遍历指定
  • 两种方式判断移动运营商(移动,联通,电信)[原创]

    author Stay 判断移动运营商 public class NetworkOperater extends Activity private static final String TAG MainActivity Called wh
  • 1.安全传输加密算法

    一 何为安全传输 安全传输就是 即使人家从网络监听到我们发送的数据包 也无法破译我们的信息 或者破译的机会十分渺茫 那么这是如何实现的呢 毕竟 我们想要传输加密信息 接收者解密的话则需要密钥 而密钥也是需要通过网络传输的啊 1 非对称加密
  • 国产嵌入式操作系统发展思考

    国产嵌入式操作系统发展思考 偶然翻到了这篇老文章 出自何小庆 嵌入式操作系统风云录 历史演进与物联网未来 作者 写的很好 汇总了当下国产 OS 的状态 遂分享出来 本文源自微博 麦克泰技术 物联网学前班公众号经授权转载分享 嵌入式操作系统历
  • Linux 添加Match User 重启sshd出现job for ssh.service failed

    最近在做一个sftp的需求 需要添加一个sftp用户来传输文件到linux的指定路径 通过网络学习 需要新增一个ftp账户 需要在 etc ssh sshd config中新增几条命令 Subsystem sftp internal sft
  • 信息网络向价值网络演进过程中产品形态的思考

    随着Facebook品牌更名Meta 持续火爆了一年多的元宇宙概念迎来了互联网巨头的正名 全球互联网生态产品将迎来怎样的新一轮大跃进 本文整理自Contentbox VP Castbox亚洲地区负责人杨霄在量江湖 拍乐云主办的 社交产品如何
  • java 加解密实例(对称——非对称)

    加密算法有很多种 这里只大约列举几例 1 消息摘要 数字指纹 既对一个任意长度的一个数据块进行计算 产生一个唯一指纹 MD5 SHA1 发送给其他人你的信息和摘要 其他人用相同的加密方法得到摘要 最后进行比较摘要是否相同 2 单匙密码体制
  • git本地仓库基本操作--查看提交历史和版本回退前进

    1
  • 版本问题导致 导入vue报错:Uncaught TypeError: Vue is not a constructor

    版本问题导致 导入vue报错 Uncaught TypeError Vue is not a constructor 浏览器控制台错误信息 问题代码 某博客带来的启发 解决方案 附录 vue2生产环境部分代码 vue3生产环境部分代码 浏览
  • window7 配置telnet 服务

    第一步 点击开始 选择控制面板 第二步 选择 程序 选择打开或关闭windows 功能 在选择对话框中勾选Telnet客户端和Telnet服务端 第三步 点击 计算机 管理 属性 修改Telnet服务的启动方式 第四步 判断Telnet服务
  • [LeetCode] Reverse Linked List I II - 链表翻转问题

    题目概述 Reverse a singly linked list 翻转一个单链表 如 1 gt 2 输出 2 gt 1 1 gt 2 gt 3 输出3 gt 2 gt 1 题目解析 本人真的比较笨啊 首先想到的方法就是通过判断链尾是否存在
  • MySQL中的正斜杠和反斜杠

    目录 问题背景 问题提出 1 为什么书上的这种方法得不到正确的数据呢 2 是因为DBMS的问题嘛 3 如何在MySQL上得到正确的数据呢 问题总结 问题背景 今天数据库老师留了一道实验题 如下 14 查询 A C 课程的课程号和学分 如果没
  • 初识C++Primer plus

    写在前面 从事c 编程转眼也快一年了 一直从事工厂数据采集工作 然而就与硬件交互效率来说 无疑c c 与硬件更加契合 就很任性的买了一本c Primer plus 第六版 希望自己在博客里能坚持下去 将自己所悟所感写在这里与大家分享 分割线
  • 飞驰的高铁-第15届蓝桥杯第一次STEMA测评Scratch真题精选

    导读 超平老师的 Scratch蓝桥杯真题解析100讲 已经全部完成 后续会不定期解读蓝桥杯真题 这是Scratch蓝桥杯真题解析第150讲 飞驰的高铁 本题是2023年8月20日举行的第15届蓝桥杯STEMA测评Scratch编程中级组编
  • 源码大杀器:怎样查看源码

    一 以SpringBoot来分析下 首先获取到源码 二 点击GitHub获取源码 三 下载源码 SpringSpace 11 24 24 ls emptydemo springdemo gs accessing data jpa maste
  • 【Python网络爬虫与信息提取】Scrapy爬虫框架

    1 理论知识 pip install scrapy i http pypi douban com simple trusted host pypi douban com scrapy h scrapy startproject python
  • 第五章 初始化与清理(下)

    第五章 初始化与清理 现在总结的东西很多都需要用代码来帮助理解了 所以会有大量的测试代码 不过这中方式非常有用 如果认真敲过一遍之后 并且将这些代码弄清楚了 我相信你一定会对书中描述的内容有一个更清楚的认识 我是在eclipse工具上进行测