import java.util.Iterator; import java.util.NoSuchElementException; public class InitOrder { public static void main(String[] args) { //错误的初始化 new RoundGlyph(5); for (Iterator<Character> i = AbstractIterator.test("OPS"); i.hasNext();) { System.out.print(i.next()); } //正确的设计CorrectAbstractIterator System.out.println(); for (Iterator<Character> i = CorrectAbstractIterator.test("OPS"); i.hasNext();) { System.out.print(i.next()); } } } abstract class Glyph { abstract void draw(); Glyph() { System.out.println("Glyph() before draw()"); draw(); System.out.println("Glyph() after draw()"); } } class RoundGlyph extends Glyph { int radius = 1; RoundGlyph(int r) { radius = r; System.out.println( "RoundGlyph.RoundGlyph(), radius = " + radius); } void draw() { System.out.println( "RoundGlyph.draw(), radius = " + radius); } } abstract class AbstractIterator<T> implements Iterator<T> { T next = nextElement(); public boolean hasNext() { return next != null; } public T next() { if (next == null) { throw new NoSuchElementException(); } T result = next; next = nextElement(); return result; } public void remove() { throw new UnsupportedOperationException(); } protected abstract T nextElement(); public static Iterator<Character> test(final String s) { return new AbstractIterator<Character>() { private int cursor = 0; protected Character nextElement() { return cursor == s.length() ? null : s.charAt(cursor++); } }; } } //正确的设计 abstract class CorrectAbstractIterator<T> implements Iterator<T> { public abstract boolean hasNext(); public T next() { if (!hasNext()) { throw new NoSuchElementException(); } return nextElement(); } public void remove() { throw new UnsupportedOperationException(); } protected abstract T nextElement(); public static Iterator<Character> test(final String s) { return new CorrectAbstractIterator<Character>() { private int cursor = 0; @Override protected Character nextElement() { return cursor == s.length() ? null : s.charAt(cursor++); } @Override public boolean hasNext() { return cursor < s.length(); } }; } }
输出为:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
OOPS
OPS
* 初始化的实际过程是这样的:
(1) 在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零。
(2) 就象前面叙述的那样,调用基础类构建器。此时,被覆盖的draw()方法会得到调用, 此时会发现
radius 的值为0,这是由于步骤(1)造成的。
(3) 按照原先声明的顺序调用成员初始化代码。
(4) 调用衍生类构建器的主体。
* 设计构建器时一个特别有效的规则是:用尽可能简单的方法使对象进入就绪状态;如果可能,避免调用
任何方法。在构建器内唯一能够安全调用的是在基础类中具有final 属性的那些方法 (也适用于private方
法,它们自动具有final 属性)。
相关推荐
在面试中,面试官可能会通过这种类型的题目来评估应聘者对Java内存模型的理解,以及他们在编写代码时是否能考虑到这些初始化规则,从而避免潜在的陷阱。因此,掌握类的初始化顺序是每个Java开发者必备的知识点。
首先,需要了解Java类初始化的基本规则,即在类的静态变量、静态初始化块、变量、初始化块、构造器这五个部分中,它们的初始化顺序依次是:静态变量、静态初始化块、变量、初始化块、构造器。这个顺序在单个类中是...
了解静态变量的初始化顺序对于理解和避免潜在的编程陷阱至关重要。 ### 静态变量初始化的基本规则: 1. **默认初始化**:当类被加载时,静态变量首先会被赋予其数据类型的默认值。例如,`int`类型的静态变量会被...
然而,构造器是用于初始化新对象的,它没有返回值且不能被继承。 4. **线程启动**:如果一个类没有重写`Thread`类的`run()`方法,那么创建并启动该类的线程将不会有任何效果。正确的做法是实现`Runnable`接口或直接...
`final`修饰的变量一旦初始化后就不能再次赋值。所以,`++x`操作是不允许的,因为`x`是`final`的。正确代码如下: ```java public class Something { public int addOne(int x) { return x + 1; // 不可以使用 +...
遵循正确的构造顺序不仅有助于避免常见的编程陷阱,还能确保类和对象的正确初始化,从而提升程序的稳定性和性能。通过以上步骤的分析,我们可以更加深刻地认识到Java语言设计的严谨性和灵活性,同时也提醒我们在实际...
在Java编程语言中,对象初始化是一个至关重要的概念,特别是对于初学者来说,理解这一过程能够帮助他们更好地构建和管理程序中的实例。这个压缩包“Java-objects-initial.rar_objects”包含了关于Java对象初始化顺序...
",来讨论Java初始化相关的知识点。 1. 初始化(Initialization): Java中的初始化通常涉及变量的赋值和对象的创建。在Java中,初始化可以通过声明时赋值、构造函数、初始化块(实例初始化块和静态初始化块)以及...
这段代码定义了一个名为`Something`的类,其中包含一个未初始化的实例变量`i`和一个方法`doSomething`。在`doSomething`方法中,直接打印变量`i`的值。由于`i`是一个`int`类型的实例变量,因此它的默认值为`0`。 **...
在Java中,一个类可能包含静态变量、静态初始化块、成员变量、实例初始化块和构造函数。当创建一个对象时,这些元素的加载顺序遵循特定的规则: 1. 静态成员和静态初始化块:在任何实例被创建之前,首先是父类的...
- 了解类的生命周期(加载、验证、准备、解析、初始化、使用、卸载)。 5. **设计模式**: - 掌握常见的设计模式,如单例、工厂、建造者、装饰者、适配器、代理、观察者、策略、模板方法等。 - 能够在实际问题中...
基本的`for`循环由三个部分组成:初始化、条件判断和迭代。它的语法结构如下: ```java for (初始化; 条件; 迭代) { // 循环体 } ``` 例如,打印1到10的数字: ```java for (int i = 1; i ; i++) { System...
- Static Nested Class(静态嵌套类)不持有对外部类的引用,可以独立存在,可被静态初始化,可以有自己的静态成员。 - Inner Class(内部类)持有对外部类的隐式引用,只能在外部类实例化后使用,不能有静态成员...
- 初始化多维数组时,需要逐层初始化。 24. **字符串比较**: - `equals`方法用于比较字符串的内容是否相等。 - `compareTo`方法用于比较字符串的字典顺序。 以上知识点涵盖了Java编程的基础概念和技术要点,...
在Java并发编程中,双检锁(Double-Checked...在实际应用中,我们应优先考虑使用其他更简单、更安全的替代方案,如早期初始化、按需初始化或枚举单例。这些方法不仅减少了代码的复杂性,还提供了更好的性能和可维护性。
在Java中,变量使用前必须遵循一定的规则:先定义,并且初始化之后才能使用。对于基本类型变量来说,这很好理解,例如你不能定义一个`int`类型的变量`a`而不给它赋值就尝试打印其值。同样的规则也适用于引用类型变量...
例如,一个经典的Java Puzzler是关于变量初始化的。在Java中,局部变量必须先初始化后才能使用,但有时候编译器可能会做出一些你意想不到的优化。如果在函数内部声明并初始化一个变量,然后在后续的代码块中再次初始...
否则,编译器会报错,因为未初始化的变量可能包含不确定的值。 - 同样,变量在使用前必须声明其类型,并且只能定义一次。一旦定义了类型,就不能改变。 3. **类型兼容性**: - 数据类型之间的转换有一定的规则。...