随着计算机革命的发展,"不安全"的编程方式已经逐渐称为编程代价高昂的主因之一。

初始化和清理正是涉及安全的两个问题。

5.1 用构造器确保初始化

通过提供构造器,类的设计者可确保每个对象都会得到初始化。

考虑到初始化期间编译器要自动调用构造器,构造器采用和类相同的名称。

在创建对象时,将会为对象分配存储空间,并调用相应的构造器。

构造器是一种特殊类型的方法,因为它没有返回值(void是空返回,任然有返回值)。

5.2 方法重载

方法名相同而形式参数不同的方法。

5.2.1 区分重载方法

每个重载方法都必须有一个独一无二的参数类型列表。参数顺序不同有足够区别两个方法。

5.2.2 涉及基本类型的重载

如果传入的实际参数类型小于方法中声明的形式参数类型,实际数据类型会被提升。

如果传入的实际参数类型大于方法中声明的形式参数类型,就要通过类型转换执行窄化转换。

5.3 默认构造器

默认构造器是没有形式参数的——它的作用是创建一个"默认对象"。

5.4 this关键字

先看看下面的代码:

Banana a=new Banana();
Banana b=new Banana();
a.peel(1);
b.peel(2);

对于上面的代码,发送消息给对象,编译器做了一些背后的工作。它暗自把所操作的对象作为第一个参数传递给peel()。

Banana.peel(a,1);
Banana.peel(b,1);

this关键字只能在方法内部使用,表示对"调用方法的那个对象"引用。

this。关键字对于将当前对象传递给其他方法也很有用。

5.4.1 在构造器中调用构造器

想在一个构造器调用另一个构造器,使用this就可以做到这一点。

this可以调用一个构造器,但不能调用两个。

5.4.2 static的含义

在static方法的内部不能调用非静态方法,反之可以。

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

Java有垃圾回收器负责回收无用对象占据的内存资源。但也有特殊情况:假定你的对象(并非使用new)获得一块内存区域,由于垃圾回收器只知道释放那些由new分配的内存,所有它不知道该如何释放该对象的这块特殊内存。

为了应对这种情况,Java允许在类中定义一个名为finalize()的方法:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用finalize()的方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。但要注意finalize()不等于析构函数。

在C++中,对象一定会被销毁,而Java中对象却并非总是被垃圾回收:

  • 对象可能不被垃圾回收
  • 垃圾回收并不等于"析构"
5.5.1 finalize()用途何在

垃圾回收只与内存有关。

使用垃圾回收器唯一的原因是为了回收程序中不在使用的内存。

无论对象怎么创建,垃圾回收器都会负责释放对象占据的所有内存。

5.5.2 你必须实施清理

如果Java虚拟机并没有面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。

5.5.3 终结条件

当对某个对象不再感兴趣——也就是它可以被清理了,这个对象应该处于某种状态,使它占用的内存可以被安全的释放。

5.5.4 垃圾回收器如何工作

再堆上分配对象的代价十分高昂,然而,垃圾回收器对于提高对象创建速度,却具有明显的效果。

在某些Java虚拟机中,堆的实现:它更像一个传送带,没分配一个新对象,它就往前移动一格。

垃圾回收当它工作时,将一面收回空间,一面使堆中的对象紧凑排列,这样堆指针就可以很容易移动到更靠近传送带的开始处,也可以尽量避免页面错误。通过垃圾回收器对对象重新排列,实现了一种高速的,有无线空间可供分配的堆模型。

其他系统中的垃圾回收机制:引用技术法,一种简单但速度慢的的垃圾回收技术。每个对象都有一个计数器,当有引用连接至对象时,引用计数加1。当引用离开作用域或被置为null时,引用计数减1。

一种更快的模式:对任何活的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。

Java虚拟机采用一种自适应的垃圾回收技术。

有一种做法叫做停止——复制。先暂停程序运行,然后将所有存活对象从当前堆复制到另一个堆,没有被复制的就都是垃圾。当对象被复制到新堆时,在新堆中保持紧凑排列。

在程序进入稳定状态下,这样复制太浪费。一些Java虚拟机会进行检查:要是没有产生新垃圾,就会转换到另一种工作模式,标记——清扫:从堆栈和静态存储区出发,遍历所有引用,进而找出所有存活对象,每当它找到一个存活对象,就会给对象一个标记,这个过程中不会回收任何对象。只有标记全部完成的时候,清理动作才会开始。在清理过程中,没有标记的对象将被释放,不会发送任何复制动作。

5.6 成员初始化

Java尽力保证:所有遍历在使用前都能恰当的初始化。对于方法的局部变量,Java以编译时错误的形式来贯彻。

在类里定义一个对象引用时,如果不将其初始化,此引用就会获得一个特殊的null值。

5.6.1 定义成员变量的地方为其赋值。

5.7 构造器初始化

在运行时刻,可以调用方法或执行某些动作来确定初值。但牢记:无法阻止自动初始化的进行,它将在构造器中被调用。

5.7.1 初始化顺序

在类的内部,变量的先后顺序决定了初始化的顺序。变量定义散步于方法定义之间,他们仍旧会在任何方法被调用前初始化。

5.7.2 静态数据初始化

无论创建多少对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值。如果它是一个对象引用,那么它的默认初始值就是null。



public class StaticInitialization {
static Table table =new Table();
static Cupboard cupboard=new Cupboard();
public static void main(String[] args){
System.out.println("in main");
new Cupboard();
new Cupboard();
table.f2(1);
cupboard.f3(3);
}
} class Bowl{
Bowl(int marker){
System.out.println("Bowl("+marker+")");
}
void f1(int marker){
System.out.println("f1("+marker+")");
}
} class Table{
static Bowl bow1=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);
}

初始化的顺序是先静态对象,而后是"非静态"对象。

对象创建过程,假设有个名为Dog的类:

  • 1.即使没有显示地使用static关键字,构造器实际上也是静态方法。
  • 2.载入new Dog()创建对象的时候,有关静态化初始化的所有动作都会执行,并且只会在第一次执行。
  • 3.当用new Dog()创建对象的时候,首先会先为Dog对象分配足够的存储空间。
  • 4.这块存储空间会被清零,这就自动的将Dog对象中的所有基本类型数据都设置成默认值,而引用则被设置成了null。
  • 5.执行所有出现于字段定义出的初始化动作。
  • 6.执行构造器。
5.7.3 显式的静态初始化

Java允许将多个静态初始化动作组织成一个特殊的"静态子句"。

public class Spon{
static int i;
static{
i=47;
}
}
5.7.4 非静态实例初始化

Java中也有被称为实例化的类似语法,用来初始化每一个对象的非静态变量。

5.8 数组初始化

数组只是相同类型的,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。数组是通过方括号下标操作符[]来定义和使用的。

数组的使用和C#一致。

5.8.1 可变参数列表

所有的类都直接或间接继承于Object类,所以可以创建以Object数组为参数的方法。

public class VarArgs {

    public static void main(String[] args){
// printArray1(15,13,16,34,"wer",new Integer[]{1,2,3,4});
printArray1(new Integer[]{1,2,3,4});
} static void printArray1(Object[] args){
for (Object obj:args) {
System.out.println(obj);
}
}
}

Java SE5新加可变参数语法。在可变参数中,可以使用任何类型的参数,包括基本类型。

 static void printArray(Object... args){
for (Object obj:args) {
System.out.println(obj);
}
} public static void main(String[] args){
printArray(15,13,16,34,"wer",new Integer[]{1,2,3,4});
printArray(new Integer[]{1,2,3,4});
}

将0个参数传递给可变参数也是可行的。

public class VarArgs {
static void printArray(Object... args){
for (Object obj:args) {
System.out.println(obj);
}
} public static void main(String[] args){
// printArray1(15,13,16,34,"wer",new Integer[]{1,2,3,4});
// printArray1(new Integer[]{1,2,3,4});
printArray();
} // static void printArray1(Object[] args){
// for (Object obj:args) {
// System.out.println(obj);
// }
// }
//printArray1(15,13,16,34,"wer",new Integer[]{1,2,3,4});
}

5.9 枚举

public class SimpleEnumUse {
public static void main(String[] args){
Spiciness howHot=Spiciness.MEDIUM;
for (Spiciness spic:Spiciness.values()) {
System.out.println(spic+":"+spic.ordinal());
} }
}
enum Spiciness{
NOT,MILD,RT,MEDIUM,HOT,FLAMING
}

Java编程思想之五初始化与清理的更多相关文章

  1. 《Java编程思想》——初始化与清理(一)读书笔记

    第一次写这个,这一章都用word写的,结果复制过来没图片....只能上传word文档了.以后改用markdown比较好 word文档地址:<Java编程思想>--初始化与清理(一)读书笔记

  2. 《java编程思想》 初始化与清理

    1.初始化与清理的重要性: 1.许多C程序的错误都源于程序员忘记初始化变量,特别是使用程序库时,如果不知道如何初始化库的构件更容易出错 2.当使用完一个元素时,这个元素就不会有什么影响了,所以很容易就 ...

  3. (六)《Java编程思想》——初始化及类的加载顺序

    package chapter7; /** * 初始化及类的加载顺序:顺序如下 * 1.基类的static变量 * 2.导出类的static变量 * 3.基类的变量 * 4.基类的构造函数 * 5.导 ...

  4. Java编程思想——初始化与清理

    PS:最近一直忙于项目开发..所以一直没有写博客..趁着空闲期间来一发.. 学习内容: 1.初始化 2.清理 1.初始化   虽然自己的Java基础还是比较良好的..但是在解读编程思想的时候还是发现了 ...

  5. 《 Java 编程思想》CH05 初始化与清理

    < Java 编程思想>CH05 初始化与清理 用构造器确保初始化 在 Java 中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.Java 会保证初始化的进行.构造器采用与类相 ...

  6. 《java编程思想》读书笔记(一)开篇&第五章(1)

    2017 ---新篇章  今天终于找到阅读<java编程思想>这本书方法了,表示打开了一个新世界. 第一章:对象导论 内容不多但也有20页,主要是对整本书的一个概括.因为已经有过完整JAV ...

  7. Java编程思想(11~17)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...

  8. Java编程思想 (1~10)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象2.程序就是对象的集合3.每个对象都是由其它对象所构成 ...

  9. Java编程思想(前十章)

    Java编程思想 有C++编程基础的条件下, 前10章可以快速过一下,都是基本语法,不需要花太多时间. 着重中后段的一些章节,类型信息.泛型.容器.IO.并发等. 中文翻译版 阅读地址 对于一个架构师 ...

随机推荐

  1. Vulnhub靶场题解

    Vulnhub简介 Vulnhub是一个提供各种漏洞环境的靶场平台,供安全爱好者学习渗透使用,大部分环境是做好的虚拟机镜像文件,镜像预先设计了多种漏洞,需要使用VMware或者VirtualBox运行 ...

  2. 解决bootstrap模态框居中问题

    完美解决办法: 在bootstrap.js或bootstrap.min.js文件中找到Modal.prototype.show方法. 在that.$element.addClass('in').att ...

  3. nginx 常用的location rewrite proxy_pass

    location 以 = 开头,表示精确匹配:如只匹配根目录结尾的请求,后面不能带任何字符串. 以^~ 开头,表示uri以某个常规字符串开头,如果匹配到,则不继续往下匹配.不是正则匹配 以~ 开头,表 ...

  4. ML-对偶(Duality)问题初识

    Primal vs Dual 为什么要把原始问题(primal) 转为 对偶问题(dual), 主要原因在于, 求解方便吧大概. 对偶问题 原始问题和其对偶问题, 都是对看待同一个问题的,从不同角度, ...

  5. LNMP搭建后html访问正常php报404错误解决办法

    环境:CentOS7.7.3.10.0-1062.el7.x86_64.nginx1.16.1 .php7.3.10 问题:nginx能解析静态文件但是不能解析php动态文件,返回404文件未发现错误 ...

  6. Linux系统的时间比北京时间慢12个小时的处理方案(将EDT时区改为CST)

    今天查看Linux操作系统的时间,发现比正常时间慢12个小时整,感觉很奇怪,后来使用ntp服务器校对时间发现也是不管用的,还是慢12个小时.之前遇到过是慢8个小时,但是我知道是因为使用的是UTC时间, ...

  7. Example-based Machine Learning是什么?

    参考:https://christophm.github.io/interpretable-ml-book/proto.html EML简介 Example-based Machine Learnin ...

  8. MoveIt简单编程

    目的:使用一些简单代码使机器人运动到指定位置.讲解代码怎么实现机器人的运动. 参考文献: 第一个博客需要下载<Mastering ROS for robotics Programming> ...

  9. ECHO命令输出空行的11种方法和效率

    标题: 批处理技术内幕:ECHO命令作者: Demon链接: http://demon.tw/reverse/cmd-internal-echo.html版权: 本博客的所有文章,都遵守“署名-非商业 ...

  10. server 2012/2016上,任务管理器性能页面增加磁盘监控

    1.用管理员身份启动命令行 2.命令行中输入:diskperf -y 3.关闭之前打开的任务管理,重新打开,发现可爱的磁盘监视器出现了.