Java

类的访问权限控制

1、类的访问权限

类型 无修饰(default) public
同一包中的类
不同包中的类

2、类成员的访问权限

  • 公有(public):可以被其他任何方法访问(前提是对类成员所属的类有访问权限)
  • 保护(protected):只可被同一类及其子类的方法访问
  • 私有(private):只可被同一类的方法访问
  • 默认(default):仅允许同一个包内的访问,又被称为“包(package)访问权限”

下表展示了类成员在不同范围的访问权限:

类型 private 无修饰(default) protected public
同一类
同一包中的子类
同一包中的非子类
不同包中的子类
不同包中的非子类
  • 如果要允许其它没有权限访问的类访问一些实例变量的值,需要在类中声明相应的公有方法。
  • 通常有两类典型的方法用于访问属性值,get方法及set方法。
    • get方法:功能是取得属性变量的值,名以 get 开头,后面是实例变量的名字。
    • set方法:功能是改变属性变量的值,名以 set 开头,后面是实例变量的名字。
    • this关键字:如果方法内的局部变量(包括形参)名与实例变量名相同,则方法体内访问实例变量时需要this关键字,即 this.实例变量

对象初始化

  • 对象初始化:系统在生成对象时,会为对象分配内存空间,并自动调用构造方法对实例变量进行初始化

  • 对象回收:对象不再使用时,系统会调用垃圾回收程序将其占用的内存回收

1、构造方法

用来初始化对象,每个类都需要有构造方法。

  • 方法名与类名相同;
  • 不定义返回类型
  • 通常被声明为公有的(public);
  • 可以有任意多个参数;
  • 主要作用是完成对象的初始化工作;
  • 不能在程序中显式的调用;
  • 在生成一个对象时,会自动调用该类的构造方法为新对象初始化;
  • 若未显式声明构造方法,编译器隐含生成默认的构造方法

默认构造方法

  • 没有参数(内部类除外),方法体为空;
  • 使用默认的构造方法初始化对象时,如果在类声明中没有给实例变量赋初值,则对象的属性值为零或空

自定义构造方法与方法重载

  • 在生成对象时给构造方法传送初始值(参数表),为对象进行初始化。

  • 构造方法可以被重载

    一个类中有两个及以上同名的方法,但参数表不同,这种情况就被称为方法重载。

    在方法调用时,可以通过参数列表的不同来辨别应调用哪一个方法。

  • 只要显式声明了构造方法,编译器就不再生成默认的构造方法。

  • 也可以显式声明无参数的构造方法,方法体中可以定义默认初始化方式

声明构造方法时使用this关键字

  • 可以使用this关键字在一个构造方法中调用另外的构造方法
  • 代码更简洁,维护起来也更容易;
  • 通常用参数个数比较少的构造方法调用参数个数最多的构造方法。

2、final变量的初始化

  • 实例变量和类变量都可被声明为final:一经初始化就不能再改变;
  • final实例变量可以在类中定义时给出初始值,或者在每个构造方法结束之前完成初始化;
  • final类变量必须在声明的同时初始化。

内存回收

当一个对象在程序中不再被使用时,就成为一个无用对象,将在必要时被自动回收。

1、对象的自动回收

  • 无用对象
    • 离开了作用域的对象;
    • 无引用指向对象。
  • Java运行时系统通过垃圾收集器周期性地释放无用对象所使用的内存。
  • Java运行时系统会在对对象进行自动垃圾回收前,自动调用对象的finalize() 方法。

2、垃圾收集器

  • 自动扫描对象的动态内存区,对不再使用的对象做上标记以进行垃圾回收;
  • 作为一个后台线程运行,通常在系统空闲时异步地执行;
  • 在对象被回收之前的最后时刻,会自动调用名为finalize的方法;
  • 可以在这个方法中释放资源

3、finalize()方法

  • 在类java.lang.Object中声明,因此Java中的每一个类都有该方法:

    1
    protected void finalize() throws Throwable
  • 用于释放资源。

  • 类可以覆盖(重写)finalize()方法。

  • finalize() 方法有可能在任何时机以任何次序执行,所以在 finalize() 方法中释放资源不能有严格的次序关系——finalize() 方法在什么时候执行不会影响程序的正确性。

枚举类

对象的可取值为可列举的特定的值时,可以使用枚举类型。

1、声明枚举类

1
2
3
4
5
6
7
[public] enum 枚举类型名称 [implements 接口名称列表] {
枚举值1 (实参表),
枚举值2 (实参表),
……;
变量成员声明及初始化;
方法声明及方法体;
}

注:枚举类中也可以声明构造方法和其他用于操作枚举对象的方法。

因为枚举值是常量,因此枚举类型的枚举值的名称应该以大写字母表示。

2、枚举类的特点

  • 枚举定义实际上是定义了一个类;
  • 所有枚举类型都隐含继承(扩展)自 java.lang.Enum,因此枚举类型不能再继承其他任何类
  • 枚举类型的类体中可以包括方法和变量;
  • 枚举类型的构造方法必须是包内私有(default)或者私有(private)的。定义在枚举开头的常量会被自动创建,在创建时会根据提供的参数自动地调用枚举类的构造方法。不能自己调用枚举类构造函数来创建对象。

3、枚举类型的默认方法

  • 静态的 values() 方法用于获得枚举类型的枚举值的数组,此方法通常与 for-each 构造(增强的for循环)结合使用,以迭代枚举类型的值;
  • toString 方法返回枚举值的字符串描述;
  • valueOf 方法将以字符串形式表示的枚举值转化为枚举类型的对象;
  • Ordinal 方法获得对象在枚举类型中的位置索引。

4、举例

该程序引自oracle Java文档:Enum Types

下面是一个示例程序,它获取您在地球上的重量(任何单位),计算并输出您在所有行星上的重量(同一单位):Planet

Here is a sample program that takes your weight on earth (in any unit) and calculates and prints your weight on all of the planets (in the same unit):Planet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);

private final double mass; // in kilograms
private final double radius; // in meters
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() { return mass; }
private double radius() { return radius; }

// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;

double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}

public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Planet <earth_weight>");
System.exit(-1);
}
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight/EARTH.surfaceGravity();
for (Planet p : Planet.values())
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}

如果提供175作为命令行参数运行,则会得到下面的结果:Planet.class

If you run from the command line with an argument of 175, you get this output:Planet.class

1
2
3
4
5
6
7
8
9
$ java Planet 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
Your weight on EARTH is 175.000000
Your weight on MARS is 66.279007
Your weight on JUPITER is 442.847567
Your weight on SATURN is 186.552719
Your weight on URANUS is 158.397260
Your weight on NEPTUNE is 199.207413