成员初始化

  Java尽力保证:所有变量在使用前都能得到恰当的初始化。

  对于方法的局部变量,Java会以编译时报错的形式贯彻这种保证,比如:

  1. void f()
  2. {
  3. int i; //这里编译时就会报错,未初始化
  4. }

  但是如果是类的数据成员,情况会有所不同。类的每个基本类型数据成员会保证一个默认初始值,通常为0,布尔型就是false,引用类型会为null。

  指定初始化

    (1 直接在类里定义时写变量等于多少(这样在C++中是不允许的)如, 

  1. public class initialV
  2. {
  3. int a=1;
  4. char c = 'c';
  5. //...等等
  6. }

构造器初始化

  可以用构造器进行初始化。但应注意:无法阻止自动初始化的进行,它将在构造器之前发生。

  1. public class Counter
  2. {
  3. int i;
  4. Counter()
  5. {
  6. i=7;
  7. }
  8. }

这里,i首先会被置0,然后变成7.对于所以基本类型和对象引用,包括在定义时已经指定初值的变量。这种情况都是成立的。

初始化顺序

  在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。如下例子

  1. class Window {
  2. Window(int marker) { print("Window(" + marker + ")"); }
  3. }
  4.  
  5. class House {
  6. Window w1 = new Window(1); // Before constructor
  7. House() {
  8. // Show that we're in the constructor:
  9. print("House()");
  10. w3 = new Window(33); // Reinitialize w3
  11. }
  12. Window w2 = new Window(2); // After constructor
  13. void f() { print("f()"); }
  14. Window w3 = new Window(3); // At end
  15. }
  16.  
  17. public class OrderOfInitialization {
  18. public static void main(String[] args) {
  19. House h = new House();
  20. h.f(); // Shows that construction is done
  21. }
  22. } /* 输出:
  23. Window(1)
  24. Window(2)
  25. Window(3)
  26. House()
  27. Window(33)
  28. f()
  29. *///:~

静态数据的初始化

   类的静态成员 属于 类 而不是类 的实例。所以 ,无论你创建多少个对象,静态成员指占用一份存储区域。static关键字不能应用于局部变量,因此只能作用于域。初始化方式和非静态一样。

   给看一个挺长的例子,看不懂直接调后面的解析。

  1. import static net.mindview.util.Print.*;
  2.  
  3. class Bowl {
  4. Bowl(int marker) {
  5. print("Bowl(" + marker + ")");
  6. }
  7. void f1(int marker) {
  8. print("f1(" + marker + ")");
  9. }
  10. }
  11.  
  12. class Table {
  13. static Bowl bowl1 = new Bowl(1);
  14. Table() {
  15. print("Table()");
  16. bowl2.f1(1);
  17. }
  18. void f2(int marker) {
  19. print("f2(" + marker + ")");
  20. }
  21. static Bowl bowl2 = new Bowl(2);
  22. }
  23.  
  24. class Cupboard {
  25. Bowl bowl3 = new Bowl(3);
  26. static Bowl bowl4 = new Bowl(4);
  27. Cupboard() {
  28. print("Cupboard()");
  29. bowl4.f1(2);
  30. }
  31. void f3(int marker) {
  32. print("f3(" + marker + ")");
  33. }
  34. static Bowl bowl5 = new Bowl(5);
  35. }
  36.  
  37. public class StaticInitialization {
  38. public static void main(String[] args) {
  39. print("Creating new Cupboard() in main");
  40. new Cupboard();
  41. print("Creating new Cupboard() in main");
  42. new Cupboard();
  43. table.f2(1);
  44. cupboard.f3(1);
  45. }
  46. static Table table = new Table();
  47. static Cupboard cupboard = new Cupboard();
  48. } /* 输出:
  49. Bowl(1)
  50. Bowl(2)
  51. Table()
  52. f1(1)
  53. Bowl(4)
  54. Bowl(5)
  55. Bowl(3)
  56. Cupboard()
  57. f1(2)
  58. Creating new Cupboard() in main
  59. Bowl(3)
  60. Cupboard()
  61. f1(2)
  62. Creating new Cupboard() in main
  63. Bowl(3)
  64. Cupboard()
  65. f1(2)
  66. f2(1)
  67. f3(1)
  68. *///:~

  解析下这个Demo:要执行main()(静态方法) ,必须加载StaticInitialization 类,然后其静态域table和cupboard被初始化,这将导致他们对应的类页被加载,并且由于他们也都包含静态的Bowl对象,因此Bow随后也被加载了。(恍然大悟)

  理论得出:静态初始化只有在必要时刻才会进行。如果不创建Table对象,也不引用Table.b1或Table.b2,name静态的Bowl b1和b2永远都不会被创建。只有在第一个Table对象被创建(或其第一次被访问了静态数据)的时候,它们才会被初始化。此后,静态对象不会再次被初始化

显式的静态初始化

  Java允许将多个静态初始化动作组织成一个特殊的“静态字句”(也称 “静态块”),如下。

  1. public class Spoon {
  2. static int i;
  3. static {
  4. i = 47;
  5. }
  6. } ///:~

  尽管上面的代码看起来像个方法,但它实际只是一段跟在static关键字后面的代码。与其他静态初始化动作一样,这段代码只执行一次:同样的时间,当第一次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时(即便从未生成过那个类)。

非静态实例初始化

  用来初始化每一个对象的非静态变量。如下

  1. class Mug {
  2. Mug(int marker) {
  3. print("Mug(" + marker + ")");
  4. }
  5. void f(int marker) {
  6. print("f(" + marker + ")");
  7. }
  8. }
  9.  
  10. public class Mugs {
  11. Mug mug1;
  12. Mug mug2;
  13. {
  14. mug1 = new Mug(1);
  15. mug2 = new Mug(2);
  16. print("mug1 & mug2 initialized");
  17. }
  18. Mugs() {
  19. print("Mugs()");
  20. }
  21. Mugs(int i) {
  22. print("Mugs(int)");
  23. }
  24. public static void main(String[] args) {
  25. print("Inside main()");
  26. new Mugs();
  27. print("new Mugs() completed");
  28. new Mugs(1);
  29. print("new Mugs(1) completed");
  30. }
  31. } /* 输出:
  32. Inside main()
  33. Mug(1)
  34. Mug(2)
  35. mug1 & mug2 initialized
  36. Mugs()
  37. new Mugs() completed
  38. Mug(1)
  39. Mug(2)
  40. mug1 & mug2 initialized
  41. Mugs(int)
  42. new Mugs(1) completed
  43. *///:~

这是无论调用了哪个显式构造器,某些操作都会发生。从输出中 可以看到实例化字句 是在构造器之前执行的。

《java编程思想》读书笔记(二)第五章(2)的更多相关文章

  1. 《Java编程思想》笔记 第十五章 泛型

    1 泛型 “泛型”意思就是适用于许多类型. 使用泛型的目的之一: 指定容器持有什么类型,让编译器确保正确性,而不是在运行期发现错误. 这个容器可以看成是有其他类型对象作为成员的类,而不单单只是JDK中 ...

  2. Java编程思想读书笔记_第7章

    final关键字类似const: import java.util.*; public class FinalData { static Random rand = new Random(47); f ...

  3. Java编程思想读书笔记_第6章

    如何创建一个包: 比如创建一个包名为com.huawei 则在一个目录下如(d:\java)创建目录com/huawei 然后在huawei目录下创建一个文件Assist.java package c ...

  4. Java编程思想读书笔记_第三章

    本章提到的关于==的部分,一个完整的实验如下: class Test { public static void main(String[] args) { Integer i = new Intege ...

  5. Java编程思想读书笔记_第8章

    覆盖私有方法 class Father { private void f() { System.out.println("Father::f()"); } public stati ...

  6. Java编程思想读书笔记_第6章(访问权限)

    四种访问权限: public private 包访问权限 protected 如果没有明确指定package,则属于默认包 package access.dessert; public class C ...

  7. JAVA编程思想读书笔记(五)--多线程

    接上篇JAVA编程思想读书笔记(四)--对象的克隆 No1: daemon Thread(守护线程) 参考http://blog.csdn.net/pony_maggie/article/detail ...

  8. JAVA编程思想读书笔记(二)--容器

    接上篇JAVA编程思想读书笔记(一) 第八章.对象的容纳 No1: java提供了四种类型的集合类:Vector(矢量).BitSet(位集).Stack(堆栈).Hashtable(散列表) No2 ...

  9. JAVA编程思想读书笔记(三)--RTTI

    接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...

  10. JAVA编程思想读书笔记(四)--对象的克隆

    接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ...

随机推荐

  1. spark应用程序常见问题整理

    1.executor lost /java oom 通常是由于单个task内存占用过多,可以观察是哪个阶段挂的,如果类似groupbykey,可以看看是否有数据倾斜现象 如果不是,可以repartit ...

  2. 2014优秀的好用的20款免费jQuery插件推荐

    2013 年最好的 20 款免费 jQuery 插件,世界买家网 www.buyerinfo.biz在这里分享给大家 这些插件对设计者和开发者都有很大的帮助,希望大家能够喜欢:) 现 今互联网市场上提 ...

  3. [DNS-BIND]网络初始化

    1.创建ns_g_socketmgr: 首先,套接字管理器是全局唯一的,与有多少个网络接口无关,全局变量定义在/bin/named/include/named/globals.h: EXTERN is ...

  4. css cursor 的可选值(鼠标的各种样式)

    crosshair; 十字准心 The cursor render as a crosshair游标表现为十字准线 cursor: pointer; cursor: hand;写两个是为了照顾IE5, ...

  5. php复习第一章—1.1php 简介

    php语言是构建互联网应用的后端最佳选择 跨平台 性能优越,稳定性强 语法简单,易于上手 丰富完善的技术扩展 LAMP平台成熟稳定,低成本构建 回顾 web 网页本质是一个文本文件,由浏览器解释文件内 ...

  6. Spark源码学习1.2——TaskSchedulerImpl.scala

    许久没有写博客了,没有太多时间,最近陆续将Spark源码的一些阅读笔记传上,接下来要修改Spark源码了. 这个类继承于TaskScheduler类,重载了TaskScheduler中的大部分方法,是 ...

  7. FFMpeg的码率控制

    mediaxyz是一位研究ffmpeg有三年的高人了,这几天一直在折腾ffmpeg中的x264,就是不知道该如何控制码率,主要是参数太多,也不知道该如何设置,在google上search了一下,这方面 ...

  8. Appium学习笔记(一)--安装与配置

    移动自动化测试常用工具有两个:Appium和Robotium.正好最近自己开始负责客户端的工作,初来乍到需要熟悉下环境,正好学习新的东西. 移动自动化相对web来说,原理与操作过程是一样的,通过自动化 ...

  9. 【转】IP协议详解之子网寻址、子网掩码、构造超网

    子网寻址 1. 从两级IP地址到三级IP地址 <1>. IP地址利用率有时很低. <2>. 给每一个物理网络分配一个网络号会使路由表变得太大而使网络性能变坏. <3> ...

  10. 将string转换成char* (转)

    原文:http://blog.sina.com.cn/s/blog_786ce14d01014lpr.html string 是c++标准库里面其中一个,封装了对字符串的操作把string转换为cha ...