Java解惑学习有感(五)---类之谜

谜题46:令人混淆的构造器案例

如果你确实进行了重载,那么请确保所有的重载版本所接受的参数类型都互不兼容,这样,任何两个重载版本都不会同时是可应用的。如果做不到这一点,那么就请确保所有可应用的重载版本都具有相同的行为

谜题47:啊呀!我的猫变成狗了

静态域由声明它的类及其所有子类所共享。如果你需要让每一个子类都具有某个域的单独拷贝,那么你必须在每一个子类中声明一个单独的静态域。如果每一个实例都需要一个单独的拷贝,那么你可以在基类中声明一个非静态域。还有就是,要优选组合而不是继承,除非导出类真的需要被当作是某一种基类来看待。

谜题48:我所得到的都是静态的

1、当你调用了一个静态方法时,通常都是用一个类而不是表达式来标识它

2、要用类名来修饰静态方法的调用,或者当你在静态方法所属的类中去调用它们时,压根不去修饰这些方法,但是千万不要用一个表达式去修饰它们。还有就是要避免隐藏静态方法。所有这些原则合起来就可以帮助我们去消除那些容易令人误解的覆写,这些覆写需要对静态方法进行动态分派

谜题49:比生命更大

要当心类初始化循环。最简单的循环只涉及到一个单一的类,但是它们也可能涉及多个类。类初始化循环也并非总是坏事,但是它们可能会导致在静态域被初始化之前就调用构造器。静态域,甚至是 final 类型的静态域,可能会在它们被初始化之前,被读走其缺省值。

谜题50:不是你的类型

1、 instanceof 操作符被定义为在其左操作数为 null 时返回 false。

2、 instanceof 操作符有这样的要求:如果两个操作数的类型都是类,其中一个必须是另一个的子类型,不然会编译报错

以下代码:

public class Type3 {
public static void main(String args[]) {
Type3 t3 = (Type3) new Object();
}
}

将会编译通过,但会运行失败抛出异常ClassCastException 异常

以下代码:

public class Type3 {
public static void main(String args[]) {
Object c = new Type3();
Type3 type3 = (Type3) c;
System.out.println(type3);
}
}

将会编译通过,也能运行通过!

谜题51:那个点是什么

在任何情况下,你都务必要记住:不要在构造器中调用可覆写的方法。在实例初始化中产生的循环将是致命的。

谜题52:合计数的微笑

请考虑类初始化的顺序,特别是当初始化显得很重要时更是如此。请你执行测试,以确保类初始化序列的简洁。请使用积极初始化,除非你有某种很好的理由要使用惰性初始化,例如性能方面的因素,或者需要打破初始化循环

谜题53:按您的意愿行事

有这样的类:
public class Thing {
public Thing(int i) { ... }
...
}

如何通过子类来调用父类的构造方法呢?

需要这样来做:

ublic class MyThing extends Thing {
private final int arg;
public MyThing() {
this(SomeOtherClass.func());
}
private MyThing(int i) {
super(i);

arg = i;
}
}

这个解决方案使用了交替构造器调用机制(alternate constructor invocation)。这个特征允许一个类中的某个构造器链接调用同一个类中的另一个构造器。在本例中,MyThing()链接调用了私有构造器 MyThing(int),它执行了所需的实例初始化。在这个私有构造器中,表达式SomeOtherClass.func()的值已经被捕获到了变量 i 中,并且它可以在超类构造器返回之后存储到 final类型的域 param 中。

谜题54:Null与Void

有以下代码:

public class Null {
public static void greet() {
System.out.println("Hello world!");
}
public static void main(String[] args) {
((Null) null).greet();
}
}

代码将会输出:Hello world!

总结:要么用某种类型来限定静态方法调用,要么就压根不要限定它们。对语言设计者来说,应该不允许用表达式来污染静态方法调用的可能性存在,因为它们只会产生混乱

谜题55:特创论

1、一个本地变量声明不能被用作 for、while 或 do 循环中的重复执行语句,它作为一条语句只能出现在一个语句块中。(一个语句块是由一对花括号以及包含在这对花括展中的语句和声明构成的。)

所以以下代码是不被允许的:
for (int i = 0; i < 100; i++)
Creature creature = new Creature();

2、在使用一个变量来对实例的创建进行计数时,要使用 long 类型而不是 int 类型的变量,以防止溢出。

3、如果你打算在多线程中创建实例,要么将对实例计数器的访问进行同步,要么使用一个 AtomicLong 类型的计数器。


如果有疑问或者对该博文有何看法或建议或有问题的,欢迎评论,恳请指正!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值