在Java设计模式中,模板方法是很常用的一种模式,它的宗旨就是把子类相同的部分提取到父类,不同的部分通过声明抽象方法在父类中调用,在子类中实现。
但是如果在抽象方法中访问实例变量,可能会有一个让你意外的陷阱:
public class Test {
public static void main(String[] args) {
new ChildClass();
}
}
abstract class SuperClass {
private int i = 0;
SuperClass() {
foo();
}
abstract void foo();
}
class ChildClass extends SuperClass {
private int i = 5;
void foo() {
System.out.println("i = " + i);
}
}
父类中的foo()方法调用的确实是子类中实现的foo方法。
在子类中,我们期望变量i象我们初始化的那样,值为5,但是实际上它的值不是子类中赋予的5,而是父类中赋予的0。
实际上子类的初始化过程如下:
1)初始化父类的实例变量
2)调用父类的构造器
3)调用子类的foo()方法
4)初始化子类的实例变量
5)调用子类的构造器
因此,如果我们在父类的构造器中调用抽象函数,而该函数又要访问实例变量的值的时候,就要特别注意到这种情况。
分享到:
相关推荐
- **实例变量(Instance Variable):** 实例变量是在类中声明但不是在方法中声明的变量。每个对象都有自己的实例变量副本。 - **默认值:**实例变量具有默认值。对于基本类型,默认值取决于类型(如`int`的默认值为`...
在Java面试中,面试官常常会设置一些陷阱,考察候选人的基础知识、理解深度以及问题解决能力。以下是对这些常见面试问题的详细解释: 1. **final, finally, finalize的区别**: - `final`:用于声明类、方法或变量...
例如,在 Person 类中,可以这样访问和修改 age 实例变量: ```java Person person = new Person(); person.age = 30; // 设置年龄 int currentAge = person.age; // 获取年龄 ``` 在类的设计中,合理地使用实例...
静态方法不能访问实例成员,因为它们不依赖于任何特定的对象实例。 3. **构造器与同名方法**:类可以有与类名或构造器相同的方法名。然而,构造器是用于初始化新对象的,它没有返回值且不能被继承。 4. **线程启动...
在Java中,抽象方法的声明不应该包含花括号,并且应该以分号结尾。因此,正确的写法是: ```java abstract class Name { private String name; public abstract boolean isStupidName(String name); } ``` 2....
15. **无抽象方法的类仍可声明为抽象类**:如果一个类没有实现所有抽象方法,即使它没有声明为抽象的,也会自动被视为抽象类。 16. **RandomAccessFile继承自Object,并实现了DataInput和DataOutput接口**:...
局部内部类(在方法内部定义的类)可以访问外部方法中的局部变量,但这些变量必须被声明为`final`或者等效于`final`(例如,未修改的局部变量)。否则,编译器将报错,因为这样做可能会导致数据不一致的问题。 ####...
- Interface(接口)只能有抽象方法和默认方法,不包含实例变量,强制实现所有方法。 21. **abstract method**:不能同时是 static、native、synchronized。 22. **接口继承与实现**: - 接口可以继承其他接口。...
在Java中,静态方法无法直接访问实例成员,因为静态方法在任何对象创建之前就已经存在,因此不存在实例上下文。 ### 三、方法名与构造函数的重名问题 尽管方法名可以与构造函数和类名相同,但构造函数没有返回类型...
局部变量在方法内定义,当方法执行时创建,使用前必须初始化,这是为了防止未初始化的局部变量导致程序行为不确定。 2. **抽象方法声明**:抽象方法是不包含实现体的方法,声明时需使用abstract关键字。因此,正确...
- 抽象类可以有方法实现,可以有非抽象方法,可以有实例变量。 - 接口只有方法声明,没有实现,不能有实例变量,可以多继承。 21. **abstract与static、native、synchronized**: - abstract不能与static、...
实现接口表示一个类实现了接口中定义的所有抽象方法。接口可以提供一种标准的方式让不同的类来实现相同的行为,提高代码的灵活性和可扩展性。 #### 三、静态内部类与普通内部类的区别 - **静态内部类**(也称为...
finalize是Object类中的一个方法,它在垃圾收集器准备回收对象时被调用。通常用于清理资源,但不推荐直接使用,因为其执行时间不确定且性能影响较大。 第二,Anonymous Inner Class (匿名内部类) 可以继承其他类,...
- **局部变量**:在方法、构造器或块内部声明的变量。 - **成员变量**:在类体中但不在任何方法或构造器内部声明的变量。 **4.10 Java方法参数传值陷阱** - Java中所有方法参数都是按值传递的。 - 对于基本数据类型...
Java语言在设计上有着丰富的特性和机制,但同时也存在一些陷阱和细节问题,这使得面试时经常出现一些挑战性的题目。下面将详细解释标题和描述中提到的一些关键知识点。 1. **final, finally, finalize的区别**: -...
Java程序员在面试中可能会遇到各种技术陷阱,这些陷阱主要涵盖了语言特性和常用库的理解。以下是对这些知识点的详细解析: 1. **final, finally, finalize的区别**: - `final`:用来修饰类、方法和变量,表示不可...
- **静态内部类**(也称为嵌套类)可以访问外部类的静态成员,但不能访问实例成员。它们更像是独立的类,与外部类仅共享命名空间。 - **非静态内部类**可以直接访问外部类的所有成员,包括私有成员,但会携带一个对...