第六章 初始化和清理

利用构造器保证初始化

在 Java 中,类的设计者通过构造器保证每个对象的初始化。

构造器名称与类名相同。

在 Java 中,对象的创建与初始化是统一的概念,二者不可分割。

方法重载

区分重载方法

Java 中以参数列表区分重载方法。

重载与基本类型

基本类型可以自动从较小的类型转型为较大的类型。

如果传入的参数类型大于方法期望接收的参数类型,你必须首先做下转换,如果你不做的话,编译器就会报错。

自动转换顺序:

char,byte,short,int,long,float,double

char不会转byte和short,而是直接转int。

无参构造器

如果你创建一个类,类中没有构造器,那么编译器就会自动为你创建一个无参构造器。

但是,一旦你显式地定义了构造器(无论有参还是无参),编译器就不会自动为你创建无参构造器。

this关键字

this 关键字只能在非静态方法内部使用。

当你调用一个对象的方法时,this 生成了一个对象引用。你可以像对待其他引用一样对待这个引用。如果你在一个类的方法里调用其他该类中的方法,不要使用 this,直接调用即可,this 自动地应用于其他方法上了。

this 关键字只用在一些必须显式使用当前对象引用的特殊场合。

    // 方法定义
Leaf increment() {
i++;
return this;
} // 调用
Leaf x = new Leaf();
x.increment().increment().increment();

this 关键字在向其他方法传递当前对象时也很有用:

Peeler.peel(this);

在构造器中调用构造器

在一个构造器中,当你给 this 一个参数列表时,它是另一层意思。它通过最直接的方式显式地调用匹配参数列表的构造器。

能通过 this 调用一次构造器。另外,必须在方法的第一行使用 this 关键字调用构造器,否则编译器会报错。

参数列表中的变量名 s 和成员变量名 s 相同,会引起混淆。你可以通过 this.s 表明你指的是成员变量 s,从而避免重复。

编译器不允许在一个构造器之外的方法里调用构造器。

static 的含义

static 方法中不会存在 this。你不能在静态方法中调用非静态方法(反之可以)。静态方法是为类而创建的,不需要任何对象。一个类中的静态方法可以被其他的静态方法和静态属性访问。

垃圾回收器

finalize() 方法的工作原理"假定"是这样的:当垃圾回收器准备回收对象的内存时,首先会调用其 finalize() 方法,并在下一轮的垃圾回收动作发生时,才会真正回收对象占用的内存。

finalize() 是一个潜在的编程陷阱。

在 Java 中,对象并非总是被垃圾回收

  1. 对象可能不被垃圾回收。
  2. 垃圾回收不等同于析构。
  3. 垃圾回收只与内存有关。

将对 finalize() 的需求限制到一种特殊情况,即通过某种创建对象方式之外的方式为对象分配了存储空间。

看起来之所以有 finalize() 方法,是因为在分配内存时可能采用了类似 C 语言中的做法,而非 Java 中的通常做法。这种情况主要发生在使用"本地方法"的情况下,本地方法是一种用 Java 语言调用非 Java 语言代码的形式。

本地方法目前只支持 C 和 C++,但是它们可以调用其他语言写的代码,所以实际上可以调用任何代码。在非 Java 代码中,也许会调用 C 的 malloc() 函数系列来分配存储空间,而且除非调用 free() 函数,不然存储空间永远得不到释放,造成内存泄露。但是,free() 是 C 和 C++ 中的函数,所以你需要在 finalize() 方法里用本地方法调用它。

绝对不能直接调用 finalize()方法。

在不需要类似析构器行为的时候,Java 的垃圾回收器极大地简化了编程,并加强了内存管理上的安全性。一些垃圾回收器甚至能清理其他资源,如图形和文件句柄。然而,垃圾回收器确实增加了运行时开销,由于 Java 解释器从一开始就很慢,所以这种开销到底造成多大的影响很难看出来。随着时间的推移,Java 在性能方面提升了很多,但是速度问题仍然是它涉足某些特定编程领域的障碍。

构造器初始化

自动初始化的进行,会在构造器被调用之前发生。

编译器不会强制你一定要在构造器的某个地方或在使用它们之前初始化元素——初始化早已得到了保证。

初始化的顺序

在类中变量定义的顺序决定了它们初始化的顺序。即使变量定义散布在方法定义之间,它们仍会在任何方法(包括构造器)被调用之前得到初始化。

静态数据的初始化

初始化的顺序先是静态对象(如果它们之前没有被初始化的话),然后是非静态对象。

初始化顺序:

  1. 静态初始化
  2. 对象中的所有基本类型数据设置为默认值,数字会被置为 0,布尔型和字符型也相同),引用被置为 null
  3. 字段定义处的初始化动作
  4. 构造器初始化

显式的静态初始化

    static {
i = 47;
}

静态初始化只会执行一次,在构造器之前调用。

非静态实例初始化

    {
mug1 = new Mug(1);
mug2 = new Mug(2);
System.out.println("mug1 & mug2 initialized");
}

多次初始化,在构造器之前调用,对于支持"匿名内部类"的初始化是必须的。

数组初始化

// 三种创建数组的方式
int[] a = {1, 2, 3, 4, 5};
int[] a = new int[rand.nextInt(20)];
int[] a = new int{1, 2, 3, 4, 5};

对于数组,初始化动作可以出现在代码的任何地方,但是第一种使用一种特殊的初始化表达式,它必须在创建数组的地方出现

可变参数列表

    // 定义
void printArray(Object... args) {
for (Object obj: args) {
System.out.print(obj + " ");
}
System.out.println();
} // 调用
printArray(47, (float) 3.14, 11.11);
printArray((Object[]) new Integer[] {1, 2, 3, 4});
printArray(); // Empty list is OK

可变参数实质上是一个数组。

如果你有一组事物,可以把它们当作列表传递,而如果你已经有了一个数组,该方法会把它们当作可变参数列表来接受。

可变参数的个数可以为 0。

可变参数列表使得方法重载更加复杂了,尽管乍看之下似乎足够安全。

    static void f(float i, Character... args) {
System.out.println("first");
} static void f(Character... args) {
System.out.println("second");
} public static void main(String[] args) {
f(1, 'a');
f('a', 'b'); // 会报错
}

可能需要通过在某个方法中增加一个非可变参数解决这个问题。

    static void f(float i, Character... args) {
System.out.println("first");
} static void f(char c, Character... args) {
System.out.println("second");
}

应该总是在重载方法的一个版本上使用可变参数列表,或者压根不用它。

枚举类型

Java 5 中添加了特性 enum 关键字。

由于枚举类型的实例是常量,因此按照命名惯例,都用大写字母表示(如果名称中含有多个单词,使用下划线分隔)。

在你创建 enum 时,编译器会自动添加一些有用的特性。例如,它会创建 toString() 方法,以便你方便地显示某个 enum 实例的名称,这从上面例子中的输出可以看出。编译器还会创建 ordinal() 方法表示某个特定 enum 常量的声明顺序,static values() 方法按照 enum 常量的声明顺序,生成这些常量值构成的数组。

由于 switch 是在有限的可能值集合中选择,因此它与 enum 是绝佳的组合

        switch(degree) {
case NOT:
System.out.println("not spicy at all.");
break;
case MILD:
case MEDIUM:
System.out.println("a little hot.");
break;
case HOT:
case FLAMING:
default:
System.out.println("maybe too hot");
}

20190816 On Java8 第六章 初始化和清理的更多相关文章

  1. 初读"Thinking in Java"读书笔记之第五章 --- 初始化与清理

    用构造器确保初始化 构造器可以确保每个对象都会得到初始化,Java毁在创建对象时自动调用构造器. 构造器采用与类名相同的名称,因此并不适合"每个方法首字母小写的风格". 构造器默认 ...

  2. 《Java编程思想》笔记 第五章 初始化与清理

    1.构造器 因为创建一个类的对象构造器就会自动执行,故初始化某些东西特好 2.方法重载 方法名相同,参数列表不同. 2.1 区分重载方法 方法重载后区别不同方法的就是方法签名 -->参数类型和个 ...

  3. java编程思想第五章初始化与清理

    5.1使用构造器确保初始化: 构造器与一般方法一样,但是没有返回值,且其方法名与类名完全相同. 不接受任何参数的构造器成为默认构造器,也叫无参构造器. 5.2 方法重载: 为什么会有方法重载? 构造器 ...

  4. 20190902 On Java8 第十六章 代码校验

    第十六章 代码校验 你永远不能保证你的代码是正确的,你只能证明它是错的. 测试 测试覆盖率的幻觉 测试覆盖率,同样也称为代码覆盖率,度量代码的测试百分比.百分比越高,测试的覆盖率越大. 当分析一个未知 ...

  5. [Effective Java]第六章 枚举和注解

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  6. 【windows核心编程】 第六章 线程基础

    Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ①    一个是线程的内核 ...

  7. Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧

    第六章 Android绘图机制与处理技巧 1.屏幕尺寸信息屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DP ...

  8. 第六章SignalR的服务器广播

    第六章SignalR的服务器广播 1.概述: VS可以通过 Microsoft.AspNet.SignalR.Sample NuGet包来安装一个简单的模拟股票行情应用.在本教程的第一部分,您将从头开 ...

  9. ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性

    原文:ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性 深入讲解控件的属性持久化(一) 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开 ...

随机推荐

  1. 音频视频的播放的进度调整(以.net为例)

    Background:对于音视频在线播放,一些小应用是靠nginx处理访问视频.音频文件的请求,对外应用的一般会托管至各种云上使用相关的服务.前者存在巨大的安全隐患,后者会有一定的成本.有的时候还是需 ...

  2. C# 同步调用 异步调用 异步回调 多线程的作用

    同步调用   : 委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. 异步调用  :同步调用会阻塞线程,如果是要调用一项繁重的 ...

  3. 在Linux上下载和安装AAC音频编码器FAAC

    Linux上FAAC的安装 安装 下载 http://downloads.sourceforge.net/faac/faac-1.28.tar.gz 解压 tar zxvf faac-1.28.tar ...

  4. JDK 8 中Stream流中的去重的方法

    JDK 8 中Stream流中去重的方法 1.简单的去重,可以使用distinct()方法去重,该方法是通过比较equals和hashcode值去去重, 2.复杂的去重, 例如,在一个JavaBean ...

  5. 如何同步发送put或者delete请求

    1.必须把前端发送方式改为post . 2.在web.xml中配置一个filter:HiddenHttpMethodFilter过滤器 3.必须携带一个键值对,key=_method,  value= ...

  6. Linux性能优化从入门到实战:13 内存篇:内存指标/工具总结、问题定位和调优

    内存性能指标 系统内存指标 已用内存和剩余内存很容易理解,就是已经使用和还未使用的内存. 共享内存是通过 tmpfs 实现的,所以它的大小也就是 tmpfs 使用的内存大小.tmpfs 其实也是一种特 ...

  7. pandas.Series函数用法

    class pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False) e.g., ...

  8. JavaScript用在哪里

    <script> 标签 在HTML,JavaScript代码必须插入<script> 和 </script>之间的. document.getElementById ...

  9. php中ajax的使用实例讲解

    一.总结 1.多复习:代码都挺简单的,就是需要复习,要多看 2.ajax原理:ajax就是部分更新页面,其实还在的html页面监听到事件后,然后传给服务器进行操作,这里用的是get方式来传值到服务器, ...

  10. Oracle DB 查看预警日志

    “Database(数据库)”主页>“Related Links相关链接)”区域> “Alert Log Content (预警日志内容)” 查看预警日志每个数据库都有一个alert_&l ...