java 初始化与清理

来源:互联网 发布:治疗近视知乎 编辑:程序博客网 时间:2024/04/30 10:41
随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一。
初始化和清理正是涉及安全的两个问题。
1.用构造器确保初始化
默认构造器(无参构造器):不接受任何参数的构造器
2.方法重载
1.区分重载方法
每个重载的方法都必须有一个独一无二的参数类型列表。
参数顺序的不同也足以区分两个方法。不过,一般情况下,别这么做,因为这会使代码难以维护。
2.涉及基本类型的重载
基本类型能从一个“较小”的类型自动提升至一个“较大”的类型,此过程一旦牵涉到重载,可能会造成一些混淆。
如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际数据就会被提升。char型略有不同,
     如果无法找到恰好接受char参数的方法,就会把char直接提升至int型。
如果传入的实际参数较大,就得通过类型转换来执行窄化转换。如果不这样做,编译器就会报错。
3.以返回值区分重载方法
有时调用方法而忽略其返回值,所以根据返回值区分重载方法是行不通的。、
3.默认构造器
如果类中没有构造器,则编译器会自动帮你创建一个默认构造器。但是,如果已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器。
4.this关键字
this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。
1.在构造器中调用构造器
在构造器中,如果为this添加了参数列表,那么就有了不同的含义。这将产生对符合此参数列表的某个构造器的明确调用。
尽管可以用this调用一个构造器,但却不能调用两个。此外,必须将构造器调用置于最起始处,否则编译器会报错。
2.static的含义
static方法(静态方法)就是没有this的方法。可以在没有创建任何对象的前提下,通过类本身调用static方法。具有全局函数的语义。
在static方法的内部不能调用非静态方法,但是在非静态方法中可以调用static方法。
5.清理:终结处理和垃圾回收
Java有垃圾回收器负责回收无用对象占据的内存资源。但也有特殊的情况:假定你的对象(并非使用new)获得了一块“特殊”的内存区域,由于垃圾
回收器只知道释放那些经由new分配的内存,所以它不知道该如何释放该对象的这块“特殊”内存。为了应对这种情况,Java允许在类中定义一个名为finalize()的方法。
它的工作原理“假定”是这样的:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生
时,才会真正回收对象占用的内存。所以要是你打算用finalize(),就能在垃圾回收时刻做一些重要的清理工作。
注意:finalize()与C++中的析构函数不同:在C++中,对象一定会被销毁(如果程序中没有缺陷的话),而Java里的对象却并非总是被垃圾回收。
换句话说:1.对象可能不被垃圾回收  2.垃圾回收并不等于“析构”
只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。如果程序执行结束,并且垃圾回收器一直都没有释放你创建的任何
对象的存储空间,则随着程序的退出,那些资源也会全部交还给操作系统。这个策略是恰当的,因为垃圾回收本身也有开销,要是不使用它,那就不用
支付这部分开销了。
1.finalize()的用途何在
垃圾回收只与内存有关。使用垃圾回收器的唯一原因是为了回收程序不再使用的内存。所以对于与垃圾回收有关的任何行为来说(尤其是finalize()方法),
它们也必须同内存及其回收有关。
    finalize()作用:释放那些通过某种创建对象以外的方式为对象分配的存储空间。
之所以要有finalize(),是由于在分配内存时可能采用了类似C语言中的做法,而非Java中通常做法。这种情况主要发生在使用“本地方法”的情况下,本地
方法是一种在Java中调用非Java代码的方式。本地方法目前只支持C和C++,但C和C++可以调用其他语言写的代码,所以实际上可以调用任何代码。
2.你必须实施清理
要清理一个对象,用户必须在需要清理的时刻调用执行清理动作的方法。
垃圾回收器的存在并不能完全代替析构函数(而且绝对不能直接调用finalize()),如果希望进行除释放存储空间之外的清理工作,还是得明确调用某个
恰当的方法。
   记住:无论是“垃圾回收”还是“finalize()”,都不保证一定会发生。如果Java虚拟机(JVM)并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收
以恢复内存的。
3.终结条件
通常,不能指望finalize(),必须创建其他的“清理”方法,并且明确的调用它们。
但是可以用finalize()验证终结条件。在垃圾回收之前,只要对象存在没有被适当的清理的部分,finalize()可以最终发现这种情况。
System.gc()用于强制进行终结动作。
4.垃圾回收器是如何工作的
在以前所用过的程序语言中,在堆上分配对象是非常昂贵的,你可能会觉得Java中所有对象都在堆上分配的方式也非常昂贵。然而垃圾回收器对于
提高对象的创建的速度,却有非常明显的效果。Java从堆上分配空间的速度,可以和其他语言从堆栈上分配空间的速度相媲美。
在某些Java虚拟机中,堆就像一个传送带,每分配一个新对象,它就往前移动一格,对象存储空间的分配速度非常快。但Java中堆未必完全像传送带
那样工作,要是那样的话,势必导致频繁的内存页面调度。然而垃圾回收器的介入,当它工作时,将一面回收空间,一面使堆中的对象紧凑排列。
其他系统中的垃圾回收机制:引用计数是一种简单但速度很慢的垃圾回收技术。(当对象被引用时,引用计数加1,当离开或被置空时,引用计数减1,
当某个对象的引用计数为0时,就释放其占用的空间)
在一些更快的模式中,垃圾回收器并不基于引用计数技术。它们依靠的思想是:对任何“活”的对象,一定能最终追溯到其存活在堆栈或静态存储区中的
引用。因此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有“活”的对象。,没有找到的对象就被自动回收。
Java虚拟机采用一种只适应的垃圾回收技术。
“停止-复制”:先暂停程序的运行,然后将所有活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。当对象被复制到新堆时,它们是一个挨一个的,
所以新堆保持紧凑排列。“复制式回收器”效率会降低。原因:1.需要两个分离的堆,维护比实际多一倍的空间。2。复制问题,程序进入稳定状态后,可能只会产生
少量的垃圾,甚至没有垃圾。复制式回收器仍然会将所有内存自一处复制到另一处,这很浪费。为了避免这种情况,一些Java虚拟机会进行检查:要是没有新垃圾
产生就转换到另一种工作模式--“标记-清扫”。
“标记-清扫”:思路是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象,然后设一个标记,全部标记工作完成,开始清理没有标记的对象。
不会发生任何复制动作,所以剩下的堆空间是不连续的,垃圾回收器要是希望得到连续的空间,就得重新整理剩下的对象。
垃圾回收器根据不同的情况,调用不同的垃圾回收模式,这将是“自适应”技术。“自适应的、分代的、停止-复制、标记-清扫”式垃圾回收器。
6.成员初始化
Java尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,Java以编译时错误的形式来贯彻这种保证。
如果类的数据成员是基本类型,都会有一个默认的初始值。
1.指定初始化
如果想给某个变量赋初值,就直接的方法是,在定义时直接赋值。
也可以调用某个方法来提供初始值。
7.构造器初始化
可以用构造器来进行初始化,但是:无法阻止自动初始化的进行,它将在构造器被调用之前发生。
1.初始化顺序
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
2.静态数据的初始化
无论创建多少个对象,静态数据都只占用一份存储区域。
静态初始化只有在必要的时刻才会进行。
3.显式的静态初始化
Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(静态块)
static int i;
static
{
i=45;
}
4.非静态实例初始化
int a;
int b;
{
a = 1;
b = 2;
}
与静态初始化子句一模一样,只不过少了static关键字。
8.数组的初始化
数组只是相同类型的,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。
数组是通过方括号下标操作符[]来定义和使用的。
int[] arrInt = {1,2,3,4,5}; 或 int arrInt[];
arrInt.length:获得数组内包含了多少个元素
Arrays.toString():属于java.util标准库,它将产生一维数组的可打印版本。
1.可变参数列表
public void printArray(Object[] args);
public void method(int... arrInt);
9.枚举类型
enum关键字,它使得我们在需要群组并使用枚举类型集时,可以方便地处理。
public enum Spiciness
{
NOT,MILD,MEDIUM,HOT,FLAMING
}
Spiciness howHot = Spiciness.Hot;
在创建enum时,编译器会自动添加一些有用的特性:
1.toString()方法
2.ordinal()方法:用来显示某个特定enum常量的声明顺序
3.static values()方法:用来按照enum常量的声明顺序,产生由这些常量值构成的数组。
enum有一个特别实用的特性,即它可以在switch语句内实用
Spiciness degree;
switch(degree)
{
case NOT:
 break;
case MILD:
break;
case MEDIUM:
break;
case HOT:
break;
case FLAMING:
break;
default: 
break;
}
原创粉丝点击