初始化与清理
2016-12-02 15:28
134 查看
# 初始化和清理
这是个涉及安全的两个问题,许多c程序的错误都源于程序员忘记初始化变量,c++中引入了构造器,java也采用了构造器,并额外提供垃圾回收器,对不再使用的内存资源,垃圾回收器自动将其释放掉.
如果你的类里不写构造函数,java默认加上无参的构造函数.如果你写了构造函数,java就不会给你自动加了.构造函数无返回值.
练习2:一个在定义时就被初始化的String,以及另一个通过构造函数初始化的String,有什么差异?
1.构造函数灵活,可以根据需要赋值,而定义时的一直是那个值.
2.定义时初始化先于构造函数初始化.
基本类型的重载:较小的会自动提升成一个”较大”的类型,比如int->double或float,char->int;如果传入的类型”较大”,必须强制窄化处理了.
区分重载函数:
1. 规则很简单,每个重载的方法都必须有一个独一无二的参数类型列表.甚至参数的顺序不同也可以!一般别这样,很难维护.
2. 不能通过返回值来重载方法,比如代码:
有时候我并不关心返回值是什么,我只是想要方法调用的过程效果,使用f();编译器无法分辨我想要哪个方法.
在参数和数据成员名称重复时候也可以使用this关键字.
除了构造函数之外,编译器禁止在其他任何方法中调用构造函数.
垃圾回收并不等于”析构”
垃圾回收只与内存有关
甚至可以肤浅的认为,正是由于垃圾回收器的存在,使得java没有析构函数,随着学习的深入,你会明白垃圾回收器并不能完全代替析构函数.
如果JVM并未面临内存耗尽的情况,它是不会浪费时间去执行垃圾回收以恢复内存的.
System.gc()用于强制进行终结动作.
在它工作时,一面回收空间,一面使堆中的对象紧凑排列,这样堆指针就可以很容易地移动到更靠近传送带的开始处,避免了页面错误,通过对对象的重新排列,实现了一种高速的,有无限空间可分配的堆模型.
在一些更快的模式中,并非基于引用计数,从堆栈和静态存储区开始,遍历所有的引用,找到所有活的对象,然后是此对象包含的所有引用,直到全部被访问完为止,你所访问的对象必须是活动的,这就解决了交互自引用的对象组.
java虚拟机采用一种自适应的垃圾回收技术,如何处理活动的对象,每个虚拟机做法不同,有一种叫stop-and-copy,显然这意味这先暂停,(它不属于后台回收模式),将所有活动的对象从当前堆复制到另一个堆,没被复制的都是垃圾,到了新堆,就是一个挨着一个,保持紧凑.
这种方式需要更新引用指向,位于堆或者静态存储区的可以直接修正,但其他指向对象的引用,在遍历时候才能被找到(可以想象成有个表格,将旧地址映射至新地址).
复制式回收器,效率降低,首先要有两个堆,然后在两个堆来回倒腾,维护比实际多一倍的空间.某些虚拟机处理方式是,按需从堆中分配几块较大的内存,复制动作发生在这些大块内存之间.
然后是复制的问题,程序稳定后,垃圾很少,甚至没有,尽管这样,回收器仍然会将内存从一处复制到另一处,这很浪费;为了避免,一些虚拟机会检查,要是没垃圾产生,转换到另一种模式(自适应),标记-清扫.sun公司早期版本的java虚拟机使用这种技术.
标记-清扫的思路是从堆栈和静态存储区出发,遍历所有的引用,每次找到一个对象设置标记,全部标记完成后,没有标记的释放,所以剩下的堆是不连续的,回收器要是希望得到连续空间的话,就得重新整理剩下的对象.也是程序暂停执行.
垃圾回收器根据情况进行切换技术,stop-and-copy和mark-and-sweep.
类的数据成员是基本类型,都会有默认值.
类的数据成员是对象引用,不初始化就会得到null;
但是引用顺序要正确,比如下面的就不对了:
你会得到非法向前引用的编译错误!
静态成员初始化在必要时刻才会被执行,如果不创建该类的对象,或者引用对象静态成员,静态对象不会被创建,在第一个Table对象或者第一次访问静态成员时候,它们会被初始化,此后都不会再被初始化.
初始化顺序是先静态对象(第一次”访问”),然后是非静态成员变量,最后是构造函数.在Class对象首次加载的时候进行一次.
static代码块也是相同与静态变量.假如不带static修饰,那就和普通成员变量一样执行.
可变参数是Java SE5引进的,原理上好像和第一种差不多,但是省去写数组的麻烦,而且第一种不支持无参.可变参数列表可以是任意类型.
这是个涉及安全的两个问题,许多c程序的错误都源于程序员忘记初始化变量,c++中引入了构造器,java也采用了构造器,并额外提供垃圾回收器,对不再使用的内存资源,垃圾回收器自动将其释放掉.
用构造器确保初始化
构造器的命名,第一,不能和成员名称冲突;第二,调用构造器是编译器的责任.所以采用与类名相同的名称.延用c++的.如果你的类里不写构造函数,java默认加上无参的构造函数.如果你写了构造函数,java就不会给你自动加了.构造函数无返回值.
练习2:一个在定义时就被初始化的String,以及另一个通过构造函数初始化的String,有什么差异?
1.构造函数灵活,可以根据需要赋值,而定义时的一直是那个值.
2.定义时初始化先于构造函数初始化.
方法的重载
构造器的名字确定,那如果想要使用多种方法创建一个对象,那只能通过方法的重载了.基本类型的重载:较小的会自动提升成一个”较大”的类型,比如int->double或float,char->int;如果传入的类型”较大”,必须强制窄化处理了.
区分重载函数:
1. 规则很简单,每个重载的方法都必须有一个独一无二的参数类型列表.甚至参数的顺序不同也可以!一般别这样,很难维护.
2. 不能通过返回值来重载方法,比如代码:
void f(){} int f(){return 1;}
有时候我并不关心返回值是什么,我只是想要方法调用的过程效果,使用f();编译器无法分辨我想要哪个方法.
this关键字
在构造函数里可以调用另一个构造函数,比如class Dog{ private int age; private String name; Dog(int age){ this.age = age; } Dog(int age,String name){ Dog(age); this.name = name; } }
在参数和数据成员名称重复时候也可以使用this关键字.
除了构造函数之外,编译器禁止在其他任何方法中调用构造函数.
终结处理和垃圾回收
对象可能不被垃圾回收垃圾回收并不等于”析构”
垃圾回收只与内存有关
甚至可以肤浅的认为,正是由于垃圾回收器的存在,使得java没有析构函数,随着学习的深入,你会明白垃圾回收器并不能完全代替析构函数.
如果JVM并未面临内存耗尽的情况,它是不会浪费时间去执行垃圾回收以恢复内存的.
System.gc()用于强制进行终结动作.
垃圾回收器如何工作
以前的语言中,在堆上分配对象代价很大,但是java所有对象(除了基本类型)都是在堆上分配的方式也非常高昂,然而,垃圾回收器对于提高对象的创建速度,却有着明显的效果,存储空间的释放竟然影响存储空间的分配,但这确实是java虚拟机的工作方式.在它工作时,一面回收空间,一面使堆中的对象紧凑排列,这样堆指针就可以很容易地移动到更靠近传送带的开始处,避免了页面错误,通过对对象的重新排列,实现了一种高速的,有无限空间可分配的堆模型.
引用计数模式
这是一种简单但速度很慢的垃圾回收技术,但引用离开作用域或被置为null时,引用计数减1,有引用连接对象时,引用加1,虽然管理计数开销不大,但是在整个程序的生命周期中都持续发生,垃圾回收器会在含有全部对象的列表上遍历,发现某个对象的引用计数为0时候.就释放(通常是立即释放).但是如果对象之间存在循环引用,可能出现’对象应该被回收,但是引用计数却不为零’,对垃圾回收器而言,定位对象组工作量大.所有它经常被用来说明垃圾收集的工作方式,但似乎未被应用于任何一种java虚拟机中.在一些更快的模式中,并非基于引用计数,从堆栈和静态存储区开始,遍历所有的引用,找到所有活的对象,然后是此对象包含的所有引用,直到全部被访问完为止,你所访问的对象必须是活动的,这就解决了交互自引用的对象组.
java虚拟机采用一种自适应的垃圾回收技术,如何处理活动的对象,每个虚拟机做法不同,有一种叫stop-and-copy,显然这意味这先暂停,(它不属于后台回收模式),将所有活动的对象从当前堆复制到另一个堆,没被复制的都是垃圾,到了新堆,就是一个挨着一个,保持紧凑.
这种方式需要更新引用指向,位于堆或者静态存储区的可以直接修正,但其他指向对象的引用,在遍历时候才能被找到(可以想象成有个表格,将旧地址映射至新地址).
复制式回收器,效率降低,首先要有两个堆,然后在两个堆来回倒腾,维护比实际多一倍的空间.某些虚拟机处理方式是,按需从堆中分配几块较大的内存,复制动作发生在这些大块内存之间.
然后是复制的问题,程序稳定后,垃圾很少,甚至没有,尽管这样,回收器仍然会将内存从一处复制到另一处,这很浪费;为了避免,一些虚拟机会检查,要是没垃圾产生,转换到另一种模式(自适应),标记-清扫.sun公司早期版本的java虚拟机使用这种技术.
标记-清扫的思路是从堆栈和静态存储区出发,遍历所有的引用,每次找到一个对象设置标记,全部标记完成后,没有标记的释放,所以剩下的堆是不连续的,回收器要是希望得到连续空间的话,就得重新整理剩下的对象.也是程序暂停执行.
垃圾回收器根据情况进行切换技术,stop-and-copy和mark-and-sweep.
成员初始化
方法的局部变量,会在编译时得到错误消息.类的数据成员是基本类型,都会有默认值.
类的数据成员是对象引用,不初始化就会得到null;
指定初始化
类的数据成员是基本类型,直接赋值就行.但是引用顺序要正确,比如下面的就不对了:
int j = g(i); int i = f(); int f(){return 1;} int g(int n){return n*10;}
你会得到非法向前引用的编译错误!
初始化的顺序
变量定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义之间,它们仍旧会在任何方法被调用之前初始化!静态成员的初始化
先看代码示例:/** * Created by samp on 16-12-2. */ import static java.lang.System.out; class Bowl { Bowl(int m) { out.println("bowl 4000 :" + m); } void f1(int m) { out.println("f1 " + m); } } class Table{ Bowl bowl3 = new Bowl(3); static Bowl bowl1 = new Bowl(1); Table(){ out.println("table"); bowl2.f1(1); } void f2(int m){ out.println("f2 " + m); } static Bowl bowl2 = new Bowl(2); } public class StaticInitialization { public static void main(String[] args) { out.println("creating new table"); new Table(); } static Table table = new Table(); } /* bowl:1 bowl:2 bowl:3 table f1 1 creating new table bowl:3 table f1 1 */
静态成员初始化在必要时刻才会被执行,如果不创建该类的对象,或者引用对象静态成员,静态对象不会被创建,在第一个Table对象或者第一次访问静态成员时候,它们会被初始化,此后都不会再被初始化.
初始化顺序是先静态对象(第一次”访问”),然后是非静态成员变量,最后是构造函数.在Class对象首次加载的时候进行一次.
static代码块也是相同与静态变量.假如不带static修饰,那就和普通成员变量一样执行.
static Bowl bowl4; static { bowl4 = new Bowl(4); } ``` ## 可变参数列表 看代码示例: ```java public class Varargs { static void printArray(Object[] args) { for (Object obj : args) { System.out.print(obj + " "); } System.out.println(); } static void printArray2(Object... args) { for (Object obj : args) { System.out.print(obj + " "); } System.out.println(); } public static void main(String[] args) { printArray(new Object[]{new Integer(12), new String("a"), new Float(0.5)}); printArray2(new Integer(12), new String("sad"), null); printArray2(); } } /* 12 a 0.5 12 sad null //注意这里是空行,就是无参的那个输出的,第一种方式不支持无参 */
可变参数是Java SE5引进的,原理上好像和第一种差不多,但是省去写数组的麻烦,而且第一种不支持无参.可变参数列表可以是任意类型.
相关文章推荐
- moon 初始化 和清理 编程思想第5章
- 初始化与清理之一 (初始化)
- 五.初始化与清理——Java编程思想第4版学习笔记
- 1-2.对象初始化与清理和字符串
- thinking in Java ---03-06操作符&流程&初始化清理&权限访问
- java语言中的初始化和垃圾清理
- Thinking In Java笔记(第五章 初始化与清理(二))
- CSS清理表格边框,图片边框,初始化表单等
- linux动态库的初始化和清理
- JAVA编程思想笔记——初始化和清理(1)
- 【Java】《Java编程思想》笔记-第五章 初始化与清理
- Think in Java第5章 初始化与清理 (笔记)
- Java 初始化与清理
- 初始化与清理
- Think in Java(二):初始化与清理
- 《java编程思想》第五章:初始化和清理
- thinking in Java:5.1初始化与清理
- 《Java编程思想》笔记 第五章 初始化与清理
- 初始化与清理之二(清理)
- linux动态库的初始化和清理