Java核心技术卷1笔记-2

第四章笔记

对象

  • 三大基本特征:封装、继承、多态。
  • 对象的构造使用构造器new Date()。构造器的名称与类名相同。
  • 区别对象变量与对象:对象变量引用一个对象。
  • 在使用类方法时,实际上还有一个隐式参数,即对象。
  • 对于同一个类,一个对象的私有域可以被另一个对象访问。

final修饰符

参考:浅析Java中的final关键字

三个特性:(1)构建类时必须初始化;(2)初始化后不能修改;(3)一般用于基本类型或者不可变类。

可以用于修饰类、方法、变量。

修饰类

表示该类不允许被继承,且类内方法被隐式声明为final方法。

修饰方法

final可以将方法锁定,即防止继承类修改其含义。因此,如果这个方法不想在子类中被覆盖的话,就设置为final。(private方法会隐式指定为final方法)

将类或方法修饰为final,可以防止其在子类中被修改。

修饰变量

对于一个final变量,如果是基本数据类型变量,那么初始化之后就不能再修改;如果是引用类型变量,那么初始化之后就能指向另一个对象。

静态域

  • 一个类的所有实例都共享一个静态域

  • 类中静态常量用处较多,比如Math.PISystem.out

静态方法

静态方法是一种不能操作对象的方法。也就是说,静态方法中不能使用类的实例域,但是可以方法类的静态域。因此以下两种情况可以用静态方法:(1)不需要访问对象状态;(2)只需要访问静态域。

调用时直接类名就行,比如Math.pow(x, a);

下文【其他】中提到的静态工厂方法也是。

main方法

每一个类都可以有自己的main方法,就用来做单元测试。

方法参数

Java采用按值调用(而不是按引用调用)。按值调用,即方法接受的是参数的拷贝

这里有一个比较绕的点,如果参数时引用变量,函数会接受一个引用变量的拷贝。对于拷贝所指的对象进行修改,也可以改变其值,即可以改变对象参数引用的对象的状态。但是,无法改变对象参数引用的对象。

对象构造

构造器的多种写法。

重载(overload)

简单来说,就是方法名称相同,但参数不同。编译器会进行重载解析(为具体执行挑选特定的方法)。

描述一个方法,通过方法的签名,方法签名指的是方法名称与参数类型(不包括返回类型,因此不允许存在名称和参数相同,返回类型却不同的两种方法)(不允许这种情况也好理解,我感觉是编译器解析的时候管不到返回类型这么远的东西)

无参数的构造器

如果类中没有写构造器,此时会有一个默认的无参数构造器,构造器为实例域都设置为默认值(如对象是null,数值为0,布尔型为false)。

注意,如果只写了一个带参数的构造器,这个时候在new对象的时候用无参数构造器,是会报错的。

显式域初始化

在声明数据域的时候,直接赋值了。这个操作是在调用构造器之前执行的。

调用另一个构造器

在一个构造器中调用另一个构造器,要放在第一句,如此一来使得不同构造器之间公共的部分只需要写一次。

例子:

1
2
3
4
5
public Employee(int id)
{
this(id, "Employee #" + nextId); // 看这里~
nextId ++;
}

初始化块

不常见,通常都是会放到构造器中。就是在数据域声明之后放一个花括号括起来的代码块,来初始化值。

同样的,静态域除了直接赋值,也可以这样初始化,当类第一次加载的时候就会进行初始化。

1
2
3
4
5
6
7
private static int example = 1;  // 直接赋值

private static int nextId;
static{
Random random = new Random();
nextId = random.nextInt(1000);
}

对象析构

C++中有析构器,来清理与释放内存。但Java有垃圾回收机制,因此不需要人工回收,也不支持析构器。

但是如果有对象使用了内存之外的资源,需要回收再利用的时候,可以引入finalize方法,但用起来要当心,因为不知道啥时候才会调用这个方法。(有关闭钩方法)

另外,如果有资源需要在用完了之后马上关闭,那就需要人工管理,用close。

包(package)

如果要访问某个包中的类,有两种方式。第一,指名道姓地给出完整路径;第二,导入该类或该类所在的包。

1
2
LocalDate today = LocalDate.now();
java.time.LocalDate today = java.time.LocalDate.now();
  • 如果有重复名称的类同时出现在程序里,那么就要指名道姓给出路径了。

  • 在包中定位是编译器的事情。

静态导入

这样可以直接使用某个类中的静态和静态方法,比如Math包:

1
2
3
import static java.lang.Math.*;
...
sqrt(2); // 不用写Math.sqrt(2);

java.lang.*是默认导入的,因此不需要导入就可以使用Math类的函数。

创建自己的包

在源代码开头写package myjava.com.test;,然后把这个文件放到myjava/com/test文件夹下面

其他

静态工厂方法(static factory method)

简单来说,就是代替构造器,来提供类实例的方法。在《Effective Java》中提出“用静态工厂方法代替构造器”

写法

1
public static ClassName getInstance()

参考:关于 Java 的静态工厂方法,看这一篇就够了

public与private

public表示可以被任意类使用,private表示只能被定义它的类使用,啥也不加表示的是package,也就是只能被同一个包内的类使用。类、变量和方法都是如此。

定义private类,只能在一个外部类(顶级类,top class)中定义。且一个top class中不能用private修饰(参考这篇Stack Overflow)。

  • 注意,变量要显式指出private,否则破坏了类的封装性。

JAR

jar中可以压缩存放多个类和子目录,更节省空间。在使用时需要设置类路径。

类路径的设置也就是环境变量里的CLASSPATH

文档注释

主要是javadoc的用法。javadoc可以根据源代码中的注释自动生成文档。

提取信息的有:

  1. 公有类与接口
  2. 公有的和受保护的构造器及方法
  3. 公有的和受保护的域

在源代码中添加注释:

对公有类添加注释需要在import后,声明前。

1
2
3
4
5
6
7
8
9
import java.util.Random;
/**
* This is an {@code Employee} object.
* @author lwq
* @version 1.0
*/
public class Employee {
...
}

对公有域注释一般是对静态常量注释。

对包添加注释:

同目录下新建文件。

(PS,要用的时候知道有这个工具就行)