初始化和清理

初始化与清理

用构造器确保初始化,构造器

编程的安全问题是我们越来越关注的问题,如果没有及时清理不用的对象,回收内存资源,就容易出现内存溢出问题

  1. 因为每个对象的出现都需要初始化, 只有初始化后, 才能再内存中分配合适的资源,而Java中提供构造方法进行初始化。 调用构造器是编译器的责任。
  2. 构造器的名字问题很是困扰, 因为不能和成员的名称相冲突, 于是Java就默认用类名字为构造器取名字
  3. 关于构造器,只要知道无参构造方法和有参构造方法, 构造器前面说了是为了 创建对象, 再内存空间中分配大小的时候用的。现在要说的是代码中的关系: 再代码中, 无参构造, 是成员变量被赋予默认值, 如果我们再创建对象的时候增加参数, 再有参构造中进行赋值初始化成员变量, 这样就很省事,对于代码而言。
  4. 但我们如果只有有参构造方法, 就指能再创建对象的时候使用带有参数的, 比如:
  5. new Demo(a , b)这样的化, 有哪位你没有设置无参构造, 所以再创建对象的时候不能用 new Demo(). 不过构造方法可以重载。
  6. 还有如果没有写构造方法,系统默认使用无参构造, 但如果i你写了一个有参构造, 那么系统就不会默认给你赋予无参构造。

方法重载

  • 关于重载, 不用可以这么记:之前提到过的方法签名的概念, 是指参数和方法名字构成一个独一无二的签名, 所以再调用的时候可以通过签名去调用, 所以只要你们签名, 也就是参数和方法名字不同时冲突就不会调用错, 这样的概念叫做方法的重载。
  • 基本类型的重载, 传入的参数比重载类型的参数来得大就自动转型, 比如方法中参数类型为long 而我们的调用的方法,给的参数类型为int , 那么Java将会自动类型转换。
  • 一个有返回值的方法, 一个没返回值的方法,参数相同, 可这两个方法区别也很大, 但是这种方式,再调用的时候,会使阅读代码的人难以判断, 于是就把返回值问题,丢给命名上面去入手。

    为了副作用而调用: 调用没有返回值, 也就是没有返回数据的方法, 但是这个方法中会产生我们想要的影响, 这种影响也被业内称为副作用。

this关键字

  • this 关键字的用法:

    是为了处理变量名不好取, 容易冲突的问题, 然后用this进行代替, 另外调用本方法内的方法的时候不需要加类型,直接调用方法名即可, 所以不用this进行修饰。

    再构造器中调用构造器, this(参数), 参数怎么加取决于你调用的是哪个构造方法。

    static特点: 里面必须全部都是静态的,所以所以里面不能有通过new 这种动态创建对象, 所以也就不能用this了

    清理:终结处理和垃圾回收

    • finalize, 一般垃圾回收器会自动回收垃圾, 可是有一些垃圾不会被自动回收, 所以我们需要主动去回收它,finalize方法。

      不会被自动回收的垃圾, 就是指不是用new进行再堆内存生成的对象,是说java可以通过调用本地方法进行调用非Java代码,调用c或者c++,但是c和c++可以调用其他代码, 所以 实际上可以调用任何代码,而c中是用malloc() 来分配空间,用free进行释放资源

    • 里面对于主动回收, 其实是用finalize进行标记垃圾, 到时候垃圾回收器, 开始清理的时-候就会将其一起清理掉,也就是说如果没有面临着内存耗尽的情况就不会被回收。

      c中有局部对象的概念, 局部对象是创建堆栈上面的, 而Java对象是创建再堆上的所以说, Java中是抛弃了局部对象的, 不允许出现局部变量。 在右花括号前面进行析构操作, 而Java是没有的, 所以可能出现有时候能没回收垃圾的情况,所以垃圾回收不能完全代替析构函数。

    • 所以说,不论是终结,还是垃圾回收,都是不能保证一定会发生,

    关于finalize的用途

    • 虽然话是这么说, 但是finalize可以拿去验证终结的条件, 比如一个例子: 书本都要进行签入, 如果签入则用false表示, 所以在finalize方法中, 加入判断语句, 如果代表签入状态的属性表示为未签入, 那这个跟我们的需求不相符, 所以我们要进行回收, 而finalize, 再进行通知垃圾回收器。 另外, 可以在主函数末尾调用 System.gc()的方法, 这样的话, 可以直接进行垃圾回收。

      对象可能不被垃圾回收

      垃圾回收不等于c++中的析构。

    • 垃圾回收器是如何工作的:

      在说回收器是如何工作的时候我们得先了解一下,c的堆栈可以比喻成一个院子, 而Java的堆,可以比喻成一个传送带, 一个传送带比院子来得小, 但是传送带是傻瓜式的分配空余的空间, 一步一步地向前分配, 而院子也就c中,得我们手动进行分配。 于是, Java的效率在这里扳回一成, Java运行起来也就显得快了。

    • 还有一件事: Java的堆并不完全像传送带,因为传送带频繁的调度,会让内存资源耗尽, 然而回收器会对对象重新排列成一个高速的可,有无限空间进行分配的堆模型
    • 计数回收机制:当有引用连接对象的时候,引用计数加1,当引用离开作用域,或者为null的时候引用计数减1, 当引用计数为0的时候, 该对象就会被垃圾回收器回收。

      以上是常被Java文档说的回收技术, 可是,没有一款的jvm虚拟机是用这技术进行回收, 嗯~ o( ̄▽ ̄)o 因为不够高大上。

    • 遍历对象的所有层次的方式, 意思是说, 便利所有引用指向的对象, 排除掉指向引用的引用, 留下真正的对象。 应用这种方式记录对象的回收机制有一个叫做: 复制式的回收机制: 创建另外一个堆, 然后在本堆中,用遍历对象的所有层次的方式筛选出所有的对象, 然后进行复制到新的堆上面, 本堆中剩下的自然是垃圾, 于是再进行删除操作。
    • 复制回收机制,很强大,这样剩下的垃圾肯定很少, 可是再于, 复制一个堆, 这样的操作很占内存, 然后我们在清理了很多垃圾,只剩很少垃圾的时候, 仅仅要做的是检查然后删除少量的垃圾, 这样再用复制回收就显得杀鸡用牛刀的感觉,所以Java采用的是自适应的机制, 再垃圾剩的很少的时候, 它会采用标志-清理, 原理是:会从堆栈和静态存储区出发,遍历所有引用,然后找出存活的对象, 然后给对象添加标志,再添加标志完成的时候, 就会开始清理未带有标志额对象。
    • 关于停止-复制, 垃圾回收动作发生的同时,程序会被暂停,而进行清理操作。
    • Java虚拟机是以块为分配的基本单位
    • Just-In-Time JIT 编译器,这种技术是把程序的全部代码或者部分代码编译成机器码, Java虚拟机本来的工作就是这个, 当加载某个类,创建第一个对象的时候, 编译器会找到.class文件然后将对象的字节码文件用JIT编译,可以,如果全部拿去编译,会因为程序代码过于散落,而导致编译的时候会增加可执行代码的长度,且花费更多的时间, 于是可以采用有必要的时候进行编译的方式, 就是说不用执行的代码是i不会被编译的。
    • Java程序最初是仅仅通过解释器解释执行的,即对字节码逐条解释执行,这种方式的执行速度相对会比较慢,尤其当某个方法或代码块运行的特别频繁时,这种方式的执行效率就显得很低。于是后来在虚拟机中引入了JIT编译器(即时编译器),当虚拟机发现某个方法或代码块运行特别频繁时,就会把这些代码认定为“Hot Spot Code”(热点代码),为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各层次的优化,完成这项任务的正是JIT编译器,JIT编译器位于虚拟机当中和解释器一起存在。

    成员初始化

    Java为什么没给局部变量进行添加初始化操作, 因为读者觉得,局部变量没有初始化,可能是程序员的疏忽,如果我们帮它进行初始化操作, 那么程序员可能拿不到所想要的值, 也就会造成了一点, 逻辑上的错误。

    构造器初始化

    • 关于构造器的初始化操作, 得知道, 成员变量的初始化会先于构造器的初始化,比如说,成员变量 Int a ; 会先被赋值为0, 然后再构造器中再进行赋值操作。
    • 初始化顺序: 即使成员变量散落再方法定义的之间, 但它仍然会比任何方法之前初始化。变量定义的先后顺序将会决定变量的初始化顺序。
    • 静态成员变量会再成员变量初始化之前进行初始化操作, 但是他们只会初始化操作一次。
    • 即使构造函数没有显示地使用static关键字,实际上也是静态方法,虚拟机加载字节码文件,得以运行,所以dog类被加载时候必须在加载静态变量,且只会加载一次。
    • 加载时候, 会将存储区域清零操作,就是说进行成员变量地初始化操作, 比如int类型编程0,然后再进行我们定义地初始化操作,
    • 然后我们地构造器初始化地操作
    • 代码块地初始化操作也会优先于构造器地初始化。

    数组初始化

    • 数组只是相同类型地对象序列用标识符封装再一起。
    • Java会处理下标越界地问题, 而c语言只会默默地接受
    • 可变参数列表,没什么好说地。。 object... xx,表示的是数组,这个只是形式不一样而已。然后里面还带有自动包装的机制,举例:如果是Integer... xxx传入的参数类型为int, 可以自动转化为原本Integer.

    枚举类型

    • 枚举类型,基本不用。知道有这个东西就够了:
public enum Spiciness{
    NOT, MILD, MEDIUM, HOT, FLAMING
    //上面是具名值,要用大写来代替
}

public class EnumOrder{
    public static void main(String[] args){
        for(Spiciness s: Spiciness.values())
            System.out.println(s + ", ordinal "+s.ordinal())
     }
}

另外,为什么一定要初始化呢, 因为如果不初始化的话, c语言中的变量默认是随机数。嗯~ o( ̄▽ ̄)o具体来说,变量是再栈上面进行分配的, 栈使用的是Ram, 掉电内容丢失, 内容丢失是指,内容会出现不稳定,随机变一个数,随机的数一般来说就是0,但有几率是其他数,所以这是一个不确定的数。

时间: 2024-10-09 18:25:29

初始化和清理的相关文章

对象的初始化与清理

随着计算机革命的发展,"不安全"的编程方式已经逐渐成为了编程代价高昂的主因之一. 正确的初始化和清理过程对于程序的安全性和性能至关重要,不同的编程语言对此具有不同的处理机制.C++中利用构造器完成初始化,当对象不再被使用时调用析构函数完成销毁,程序员需要手动完成内存释放管理过程:Java也采用了构造器完成初始化,同时提供了垃圾会收器对不再使用的内存资源进行自动管理,减轻了程序员管理手动管理内存的编程负担. 1 重载 Java(和C++)中,构造器是强制重载方法名的原因之一.因为构造器常

Win32中GDI+应用(二)--初始化与清理

GDI+提供了GdiplusStartup和 GdiplusShutdown 函数来进行初始化和完成清理工作.你必须在调用其他的GDI+函数之前,调用GdiplusStartup函数,在完成GDI+工作后调用GdiplusShutdown .具体的可以看下面的MSDN上的例子: #include <windows.h> #include <gdiplus.h> #include <stdio.h> using namespace Gdiplus; int main()

Chapter5_初始化与清理_用构造器初始化

接下来进入第五章,java中初始化和清理的问题,这是两个涉及安全的重要命题.初始化的功能主要是为库中的构件(或者说类中的域)初始化一些值,清理的功能主要是清除程序中不再被需要的元素,防止资源过分被垃圾占用的出现,为解决这些问题,java中提供了对构造器和垃圾清理器的支持,首先讨论构造器的问题. 为了保证程序的安全性,java中采用了构造器的机制来保证初始化.第一个问题就是命名的问题,java中的构造器规定名称必须和类名相同.这主要是出于如下的考虑,第一如果让编程者自行命名,则可能会产生于其他任何

图解 & 深入浅出Java初始化与清理:构造器必知必会

Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆         瓣:BYSocket FaceBook:BYSocket Twitter    :BYSocket 在面向对象编程中,编程人员应该在意"资源".比如 ? 1 <font color="#000000">String hello = "hello": </font> 在代码中,我们很在意在内存中Stri

Java 编程思想 第五章 ----初始化与清理(1)

从今天开始每天一小时的java 编程思想的阅读和编码,其实就是把书上的代码抄下来. 5.5 清理:终结处理和垃圾回收 初始化和清理工作同等重要,但是清理工作却被常常忘记,但是在使用对象之后,对对象弃之不顾的做法并不是很安全.Java有自己的垃圾回收器负责回收无用的对象占据的内存资源.但也有特殊情况:假定你的内存区域不是用new获得的,这是无法用垃圾回收器释放所以java中允许在类中定义一个名为 finalize()的方法.       工作原理: 一旦垃圾回收器准备好释放对象占用的存储空间,将首

[THINKING IN JAVA]初始化和清理

4.5初始化和清理 5.1 构造器初始化 无参:如果一个类没有构造器,那么会有一个默认的无参构造器,并且只能通过无参构造器初始化对象: 带参:传入参数初始化成员变量或者其它初始化操作需要的参数,如果类重质油带参构造器,那不能通过无参构造器初始化对象. 5.2 方法重载 具有相同的方法名称.不同的返回值或者参数列表(个数.类型.顺序) 基本类型重载:基本类型存在自动向上转型的情况 5.3 垃圾回收 finalize():在对象被销毁时调用 如何回收:引用计数.停止-复制.标记-清扫.分代.JIT

Thinking In Java笔记(第五章 初始化与清理(三))

第五章 初始化与清理 5.6 成员初始化 Java尽力保证:所有变量在使用前都能得到恰当的初始化.对于方法的局部变量,Java以编译错误的形式来保证.如下: void f() { int i; i++; //Error:i not initialized } 会得到一条错误的消息,提示i可能没有初始化.编译器可以给i赋初值,但是并没有这么做,因为没有初始化是程序员的疏忽,为了保证程序的稳定性,能帮助程序员找出程序的缺陷所在. 但如果是类的数据成员是基本类型,类的每个基本类型成员变量都会保证有一个

Java编程思想:第5章 初始化与清理

随着计算机革命的发展,“不安全”的编程方式已经逐渐成为编程代价高昂的主因之一. 初始化和清理,正是涉及安全的俩个问题. 5.1 用构造器确保初始化 构造器名与类名相同,没有返回值 5.2 方法重载 构造器的重载与方法重载 5.2.1 区分重载的方法 参数列表的不同(不同顺序也是重载,但不建议这么做) 5.2.2 涉及基本类型的重载 void print(char c){System.out.println("The character is "+c); }    void print(

Java - Thinking in Java 第5章 初始化与清理

初始化和清理(cleanup)是涉及安全的两个问题. 构造器确保类的初始化, 采用与类名相同的名称, 初始化期间自动调用构造器. 默认构造器就是不接受任何参数的构造器. 重载方法的函数名相同, 参数列表唯一. 如果传入的实际数据类型小于方法声明的形式参数类型, 实际数据类型就会提示. char类型可以匹配int类型, 作为参数传入. 函数没有构造器时, 编译器会自动创建一个默认构造器; 如果定义了一个构造器, 编译器就不会创建默认构造器. 版权声明:本文为博主原创文章,未经博主允许不得转载.

Java编程思想(二) —— 初始化与清理

(一)操作符一章的int类型数据溢出的问题在Java7的版本中仍然存在,而且溢出的结果千奇百怪. public class Hello { public static void main(String[] args) { int i = Integer.MAX_VALUE; System.out.println(i); System.out.println(i*4); System.out.println(i*5); } } 结果分别为2147483647,-4,2147483643. 当应用中