《Java 编程思想》整理——第一个Java程序-初始化

写到一半的文章没了。。。还要重新再来

第一个 Java 程序

对于每一个 Java 程序,都会有一个 java.lang 的包被自动导入,比如我们常用的 System.out 就是这个包里对象。

Java 源文件通过编译生成 class 字节码文件,因此文件名和类名必须相同,并且此类名必须是 public 的(否则会编译出错)。static 方法可以在不创建对象的情况下进行调用,因此 main 必须是 static 的。

Javadoc 使用“文档标签”和“嵌入 HTML”的方式,可以自动生成文档。(这部分没有仔细阅读)

编码风格:约定类名首字母必须是大写;如果类名由几个单词构成,那么把它们并在一起,其中每个内部单词的首字母都采用大写形式

静态导入:通过静态导入,可以在调用对象方法的时候不需要添加导入对象名;但是如果有多个对象包含同样的方法名,则会出现冲突问题。

初始化

当初学习 C 语言时候,所有的初始化都是手工操作的,于是各种 memset。。。C++中的类对象,使用了构造函数和析构函数,在对象创建和删除的时候实现初始化和内存清理。Java 中也使用构造器,不过清理是使用垃圾回收器(GC),将不再使用的内存资源进行回收。

this 关键字

编译器会暗自把“所操作对象的引用”作为第一个参数传递给方法。this关键词只能在方法内部使用,表示对“调用方法的那个对象”的引用。this的用法和其他对象引用并无不同,它就是一个对象引用,特殊的是这个对象是它自己本身。以下有几天需要注意的:

  • 区分同名变量:this关键字是类内部当中对自己的一个引用,可以方便类中方法访问自己的属性。成员变量与方法内部的变量重名时,希望在方法内部调用成员变量,如this.a = a
  • 如果在方法内部调用同一类的另一个方法,不必使用this,直接调用即可。当方法需要返回当前对象的引用时才需要明确使用this,如需要返回当前对象时。
  • 如果要将当前对象传递给外部的方法,可以 return this 来返回当前对象的引用。
  • 可能为一个类写了多个构造器,想在一个构造其中调用另一个构造器,以避免重复代码。this关键字可以做到这一点。
  • 尽管可以用this调用一个构造器,但不能调用两个。此外,必须将构造器置于最起始处,否则编译器会报错。
  • 不能在构造方法以外的任何方法内调用构造方法。
  • static方法是属于类的,所以里面不能用this关键字。

初始化顺序

Java尽力保证:所有变量在使用前都能得到恰当的初始化。类的每个基本类型数据成员保证都会有一个初始值。在类里定义一个对象引用时,如果不将其初始化,此引用就会获得一个特殊值null。无法阻止自动初始化的进行,它将在构造器被调用之前发生。

  • 变量定义的先后顺序决定了初始化的顺序
  • 但是不论变量定义在什么位置,都会在任何方法(包括构造器)被调用之前得到初始化
  • 静态初始化只有在必要的时刻才会进行。只有在第一个对象被创建(或者第一次访问静态成员,其实构造器可以看成是静态方法)的时候,它们才会被初始化。此后,静态对象不会再次被初始化。
  • 初始化的顺序是,先静态对象(如果他们尚未初始化,类加载过程中被初始化),而后是非静态对象(类实例化时被初始化)。

Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(有时也叫做“静态块”)。此外还有实例初始化子句,这在匿名内部类初始化中是必须的(因为匿名内部类没有构造器)。static块可以访问、修改在它之前的static 字段,只能修改出现在它后面的static字段。

对于继承中子类的初始化:

  1. 加载类的基类,如果基类还有基类,则继续加载,如此类推。其它任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。
  2. 根基类中的static初始化(static域和static块初始化),然后下个导出类,以此类推。
  3. 根基类初始化:非static显示初始化,调用构造器。
  4. 导出类初始化,流程与基类类似。

AlexYoung 的 blog 中,有更为仔细的一些分析。

数组的初始化

在书的第16章中,有详细讲解数组的一些内容。这里主要讨论数组初始化的部分。

关于数组的一些特点:

  • 数组也是一种数据类型,本身就是一种引用类型,我们从它的初始化方法,通过关键字new去完成定义及初始化就可以知道。
  • 数组的长度是不变的,一旦数组完成初始化后,它的长度就固定下来了。
  • 数组里边存放的数据类型要一致,可以基本数据类型(保存值),也可以是引用数据类型(即对象)。在Java中,类与类是支持继承关系的,所以就可能造成数组里面可以存在多中数据类型的假象(因为向上转型的存在,多个类型转型为同一父类即可存在同一个数组里)

定义数组:

第一种方法可以更为直观的表示这是一个 type 类型的数组。

初始化数组:

可变参数表

第一次接触到可变参数表是在学习 Python 的时候,通过*args 和**args 可以使用变量和列表的可变参数表。在 Java5 中也加入了这一新特性。可以主要到,在常用的 main 方法中:

使用数组的方式,实现了可变参数表的功能。但是不方便的是,如果我们传递的时候多个参数,而不是一个数组,则需要在调用的时候,将多个参数封装到一个数组中进行传递:

Java5中新加入的特性,可以使用三个点来实现可变参数表:

需要注意的是,可变参数表的使用也有一些限制:

  • 一个方法只能有一个可变长参数,并且这个可变长参数必须是该方法的最后一个参数
  • 如果使用,应当在方法的最后一个重载版本上使用。

这里有一个英文 blog 的讲解。

关于清理的讲解,似乎是在面试中经常考察的部分,我会在认真阅读一些相关资料后,在下篇 blog 中进行记录。应该会包括 JVM 垃圾回收机制的一些介绍(但愿我能看到什么各种回收机制。。)

发表评论

电子邮件地址不会被公开。 必填项已用*标注