java 类
java 类的 数据域 初始化顺序:
- 所有数据域被初始化为默认值(数值类型值为 0, 布尔类型值为 false, 对象引用值为 null);
- 按照在类声明中出现的次序, 依次执行所有域的初始化语句和初始化块;
- 如果构造器第一行(也只能是第一行)调用了第二个构造器(包括父类构造器), 则执行第二个构造器主体;
- 执行这个构造器的主体;
class BaseClass {
BaseClass() {
System.out.println("BaseClass constructor");
}
}
class DerivedClass extends BaseClass {
private static final int VALUE = 10; // 在声明中赋值
private int value;
// 初始化块
{
value = 1;
}
DerivedClass() {
this("name");
System.out.println(this.getClass().getName() + " constructor: no arg");
}
DerivedClass(String name) {
super();
System.out.println(this.getClass().getName() + " constructor: have arg");
}
}
public class constructor {
public static void main(String[] args) {
DerivedClass derivedClass = new DerivedClass();
}
}
类设计技巧:
1. 一定要保证数据私有
绝对不能破坏封装性. 很多惨痛的经验告诉我们, 数据的表示形式很可能会改变, 但它们的使用方式却不会经常发生变化. 当数据保持私有时, 它们的表示形式的变化不会对类的使用者产生影响.
2. 一定要对数据初始化
java 会对对象的实例域进行初始化, 但不会对局部变量进行初始化.
最好不要依赖于系统的默认值, 而是应该显式地初始化所有数据. 推荐使用提供默认值的初始化方式.
3. 不要再类中使用过多的基本类型
将多个相关的基本类型的数据组装成一个新类, 这样会使类更加易于理解和易于修改.
4. 不是所有的域都需要独立的域访问器和域修改器
可能有部分实例域禁止被获得或修改.
5. 将职责过多的类进行分解
6. 类名和方法名要能够体现它们的职责
命名类名的良好习惯是采用一个名词(Order
), 或者是前面有形容词修饰的名词(RushOrder
),
或者动名词(有 -ing 后缀)修饰名词(BillingAddress
).
对于方法来说, 习惯是访问器为 getXXX
, 更改其为 setXXX
.
7. 优先使用不可变的类
LocalDate
类和 java.time
包中的其它类时不可变的, 没有方法能修改对象的状态,
可以安全的在多个线程间共享其对象.
继承的设计技巧
1. 将公告操作和域放在超类
2. 不要使用被包含的域
protected
的缺点:
- 可以任意派生子类并访问
protected
的实例域, 破坏封装性; - 同一个包内所有类都可以访问
protected
域, 即使其不是这个类的子类.
protected
的场景应该是定义只能在子类中使用的方法时才用.
3. 使用继承实现 is-a 关系
4. 除非所有继承的方法都有意思, 否则不要使用继承
5. 在覆盖方法时, 不要改变预期的行为
6. 使用多态, 而非类型信息
对与如下代码, 如果 action1
和 action2
表示相同的概念, 就应为其定义在两个类的超类或接口中:
if (x is of type1)
action1(x);
else if (x if of type2)
action2
7. 不要过多使用反射
只能在运行时才能发现错误并导致异常.