热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java初始化与清理的案例分析

小编给大家分享一下Java初始化与清理的案例分析,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!大家都知道,Java是站在巨人的

小编给大家分享一下Java初始化与清理的案例分析,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!

  大家都知道,Java是站在巨人的肩上成功的,它是在C&C++的基础上进一步的开发,投入面向对象开发的怀抱。Java吸取了很多以前的教训,加入自己很多独创的方式。在程序语言发展初期,许多C程序员经常忘记初始化变量,在程序结束后也经常忘记对创建的数据类型进行释放内存,造成内存泄漏。这些"不安全"的编程方式当然需要程序员有良好的编程习惯,但如果编程语言能够加入自动清理与初始化的工作,这回大大降低开发成本。随着技术的发展,C++语言引入了构造器(constructor),即在创建对象自动调用的初识方法,Java语言采用这一方法,并加入垃圾回收器,负责自动回收用户创建的内存,进一步降低程序员的开发成本。

Java的初始化与构造器

  创建Java的对象最普遍发的方法是使用new方法,如下所示。而创建对象必须使用构造器,构造器实际就是Java对象初始化的方法,用户可以在该方法中添加自定义初始化行为。

 Object obj = new Object(); // 左侧为声明对象,右侧为实际创建一个对象

  构造器它是一个隐含为静态的无返回值的方法,名称与类名相同,编译期会自动调用该方法。如果用户没有创建构造器,编译期会为你自动生成一个默认构造器。总之,构造器个数至少有一个。构造器可以有多个,它可以用户自己选择如何初始化对象,这里是使用重载(Overload)的方法。如下所示:

package com.thinkinjava.initialization;
import static com.thinkinjava.util.Print.*;

class Tree {
 int height;
 Tree() {
 print("Planting a seedling");
 height = 0;
 }
 Tree(int initialHeight) {
 height = initialHeight;
 print("Creating new Tree that is " +
  height + " feet tall");
 } 
 void info() {
 print("Tree is " + height + " feet tall");
 }
 void info(String s) {
 print(s + ": Tree is " + height + " feet tall");
 }
}

public class Overloading {
 public static void main(String[] args) {
 for(int i = 0; i <5; i++) {
  Tree t = new Tree(i);
  t.info();
  t.info("overloaded method");
 }
 // Overloaded constructor:
 new Tree();
 } 
}

Java的初始化顺序

  既然讲到Java初始化,那肯定要关注Java的初始化顺序,这涉及到一些继承的知识,首先看一个实例:

package com.thinkinjava.multiplex;

import static com.thinkinjava.util.Print.print;

/**
 * 初始化顺序
 *
 */

// 形状
class Insect {
  private int i = 9;
  protected int j;
  private int k = priInit("Insect.k initialized");

  Insect() {
    print("i = " + i + ",j = " + j);
    j = 39;
  }

  private static int x1 = priInit("static Insect.x1 initialized");

  static int priInit(String s) {
    print(s);
    return 47;
  }
}

class InitOrder extends Insect {
  private int i = 10;
  private int k = priInit("InitOrder.k initialized");

  public InitOrder() {
    print(" k = " + k);
    print(" j = " + j);
  }

  private static int x2 = priInit("static InitOrder.x2 initialized");

  public static void main(String[] args) {
    print("InitOrder constructor");
    InitOrder x = new InitOrder();
  }
}

Output:

static Insect.x1 initialized
static InitOrder.x2 initialized
InitOrder constructor
Insect.k initialized
i = 9,j = 0
InitOrder.k initialized
 k = 47
 j = 39

  如上所示,当运行该Java程序时,首先访问程序入口,即InitOrder.main()方法,于是类加载器加载InitOrder.class类文件,而对它的加载过程中,通过extends关键字可知该类有个父类,于是加载该父类,如果该父类还有它自身的父类,继续加载,然后执行最高一层类的static初始化,然后是其子类,依次执行,最后所有的类的已加载完成,开始执行main方法:在main方法中开始创建对象,对象被创建之后,虚拟机会为其分配内存,主要用来存放对象的实例变量及其从父类继承过来的实例变量(即使这些从父类继承过来的实例变量有可能被隐藏也会被分配空间)。在为这些实例变量分配内存的同时,这些实例变量也会被赋予默认值。在内存中创建对象后,开始调用父类的构造器,父类的构造器能够使用super调用或被编译期自动调用,父类在执行构造器语句之前,会对父类实例变量按照次序进行初始化。父类完成父类子对象的初始化后,子类开始的顺序执行,先实例变量初始化,然后执行构造器语句。最后整个对象构造完成。

Java的对象与清理

  Java的显著优点就是Java有良好的垃圾清理机制,C++中创建对象,使用对象后,需要使用delete操作符删除对象,就会调用对应的析构函数。而Java中没有析构函数,Java的finalize()并不是类似C++的析构函数,Java的finalize()只是用来回收本地方法(c/c++)占用的内存(调用本地方法类似free)。通常意义上来讲,Java程序员只需创建对象,而不需我们自己去销毁对象,因为垃圾回收机制会帮我们回收对象,虽然不知道什么时候回收,是否会被回收。

  然后可能会出现这种情况,类可能要在生命周期内执行一些必需的清理活动,这就需要程序员自己书写清理方法,在清理方法中必须注意清理顺序,即其顺序与初始化顺序相反,为防止出现异常,可以将清理动作放入finally中。如实例所示:

import static com.thinkinjava.util.Print.print;

/**
 * 确保正确清理
 * */

// 形状
class Shape {
 Shape(int i) {
 print("Shape constructor");
 }

 // 处理
 void dispose() {
 print("Shape dispose");
 }
}

class Circle extends Shape {
 Circle(int i) {
 super(i);
 print("Circle constructor");
 }

 void dispose() {
 print("Circle dispose");
 super.dispose();
 }
}

// 三角形
class Triangle extends Shape {
 Triangle(int i) {
 super(i);
 print("Triangle constructor");
 }

 void dispose() {
 print("Triangle dispose");
 super.dispose();
 }
}

class Line extends Shape {
 private int start, end;

 Line(int start, int end) {
 super(start);
 this.start = start;
 this.end = end;
 print("Drawing Line: " + start + ", " + end);
 }

 void dispose() {
 // 擦除线条
 print("Erasing Line: " + start + ", " + end);
 super.dispose();
 }
}

public class CADSystem extends Shape {
 private Circle c;
 private Triangle t;
 private Line[] lines = new Line[3];

 public CADSystem(int i) {
 super(i + 1);
 for (int j = 0; j = 0; i--) {
  lines[i].dispose();
 }
 super.dispose();
 }

 public static void main(String[] args) {
 CADSystem x = new CADSystem(47);
 try {
  // 程序编码与异常处理
 } finally {
  x.dispose();
 }
 }

Output:

Shape constructor
Shape constructor
Drawing Line: 0, 0
Shape constructor
Drawing Line: 1, 1
Shape constructor
Drawing Line: 2, 4
Shape constructor
Circle constructor
Shape constructor
Triangle constructor
Combined constructor
CADSystem.dispose()
Triangle dispose
Shape dispose
Circle dispose
Shape dispose
Erasing Line: 2, 4
Shape dispose
Erasing Line: 1, 1
Shape dispose
Erasing Line: 0, 0
Shape dispose
Shape dispose*/

看完了这篇文章,相信你对Java初始化与清理的案例分析有了一定的了解,想了解更多相关知识,欢迎关注编程笔记行业资讯频道,感谢各位的阅读!


推荐阅读
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
author-avatar
肉斯情-
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有