In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces you how to learn Java object construction process through examples, the content is very detailed, interested friends can refer to, I hope to help you.
The following provides an example of a bug in a project, provides observation and analysis of it, reveals the concrete process of instantiating an object in the Java language, and finally summarizes an important rule for designing Java classes. Reading this article will enable Java programmers to understand the construction of Java objects and design more robust code.
The author once provided an abstract dialog base class for project team members in a project. Users only need to implement an abstract method of the base class to draw an interface to display data, so that dialog boxes within the project have the same style. The code snippet is as follows (other unrelated code is omitted for brevity):
public abstract class BaseDlg extends JDialog {
public BaseDlg(Frame frame, String title) {
super(frame, title, true);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(createHeadPanel(), BorderLayout.NORTH);
this.getContentPane().add(createClientPanel(), BorderLayout.CENTER);
this.getContentPane().add(createButtonPanel(), BorderLayout.SOUTH);
}
private JPanel createHeadPanel() {
... //Create dialog header
}
//Create a dialog customer area and hand it over to the subclass to implement
protected abstract JPanel createClientPanel();
private JPanel createButtonPanel {
... //Create button area
}
}
This class works fine in some code, but when a colleague uses it, the program throws a NullPointerException violation! After comparing, the nuances of working and not working programs are identified. The code fragments are as follows:
I. Code for normal operation:
public class ChildDlg1 extends BaseDlg {
JTextField jTextFieldName;
public ChildDlg1() {
super(null, "Title");
}
public JPanel createClientPanel() {
jTextFieldName = new JTextField();
JPanel panel = new JPanel(new FlowLayout());
panel.add(jTextFieldName);
... //Other codes
return panel;
}
...
}
ChildDlg1 dlg = new ChildDlg1(frame, "Title"); //external invocation
II. Code that does not work properly:
public class ChildDlg2 extends BaseDlg {
JTextField jTextFieldName = new JTextField();
public ChildDlg2() {
super(null, "Title");
}
public JPanel createClientPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.add(jTextFieldName);
... //Other codes
return panel;
}
...
}
ChildDlg2 dlg = new ChildDlg2(); //external calls
Do you see the difference between the two pieces of code? Yes, the only difference is the initialization time of the class variable jTextFieldName. Tracing shows that jTextFieldName is indeed null when the panel.add(jTextFieldName) statement is executed.
As we know, Java allows you to assign initial values to variables while defining them. When the system needs to create an object during operation, it first allocates memory space for the object, then initializes the variables according to the order in which the variables are defined within the class "before calling any methods," and then calls the constructor methods of the class. So why, in this case, would code initialized at variable definition have a null pointer violation?
Object creation and initialization
In fact, the statement that variable initialization occurs before any method is called, including constructor methods, is inaccurate when we focus on a single class; however, it is not true when we expand our vision to two or more classes with inheritance relationships.
There are generally two ways to create objects, one is to use the new operator, and the other is to call the newInstance method on a Class object; the actual process of creation and initialization is the same:
First, allocate memory space for the object, including all visible or invisible variables of its parent class, and initialize these variables to default values, such as int type 0, boolean type false, object type null;
Then initialize the new object in the following five steps:
1) Assign parameters to the specified constructor;
2)If the first statement of the specified constructor explicitly calls other constructors of the class with this pointer, recursively execute these five steps; if the execution process is normal, skip to step 5;
3)If the first statement of constructor does not explicitly call other constructor methods of this class, and this class is not Object class (Object is the ancestor of all other classes), call the constructor method of parent class explicitly (with super pointer) or implicitly specified, and recursively execute these 5 steps; if the execution process is normal, skip to step 5;
4)Initialize variables of this class according to the order in which variables are defined in the class, and jump to step 5 if the execution process is normal;
5)Executes the rest of the statements in this constructor and ends if execution is normal.
This process can be seen more clearly in the following timing diagram:
对分析本文的实例最重要的,用一句话说,就是"父类的构造方法调用发生在子类的变量初始化之前"。可以用下面的例子来证明:
// Petstore.java
class Animal {
Animal() {
System.out.println("Animal");
}
}
class Cat extends Animal {
Cat() {
System.out.println("Cat");
}
}
class Store {
Store() {
System.out.println("Store");
}
}
public class Petstore extends Store{
Cat cat = new Cat();
Petstore() {
System.out.println("Petstore");
}
public static void main(String[] args) {
new Petstore();
}
}
运行这段代码,它的执行结果如下:
Store
Animal
Cat
Petstore
从结果中可以看出,在创建一个Petstore类的实例时,首先调用了它的父类Store的构造方法;然后试图创建并初始化变量cat;在创建cat时,首先调用了Cat类的父类Animal的构造方法;其后才是Cat的构造方法主体,最后才是Petstore类的构造方法的主体。
寻找程序产生例外的原因
现在回到本文开始提到的实例中来,当程序创建一个ChildDlg2的实例时,根据super(null, "Title")语句,首先执行其父类BaseDlg的构造方法;在BaseDlg的构造方法中调用了createClientPanel()方法,这个方法是抽象方法并且被子类ChildDlg2实现了,因此,实际调用的方法是ChildDlg2中的createClientPanel()方法(因为Java里面采用"动态绑定"来绑定所有非final的方法);createClientPanel()方法使用了ChildDlg2类的实例变量jTextFieldName,而此时ChildDlg2的变量初始化过程尚未进行,jTextFieldName是null值!所以,ChildDlg2的构造过程掷出一个NullPointerException也就不足为奇了。
再来看ChildDlg1,它的jTextFieldName的初始化代码写在了createClientPanel()方法内部的开始处,这样它就能保证在使用之前得到正确的初始化,因此这段代码工作正常。
解决问题的两种方式
通过上面的分析过程可以看出,要排除故障,最简单的方法就是要求项目组成员在继承使用BaseDlg类,实现createClientPanel()方法时,凡方法内部要使用的变量必须首先正确初始化,就象ChildDlg1一样。然而,把类变量放在类方法内初始化是一种很不好的设计行为,它最适合的地方就是在变量定义块和构造方法中。
在本文的实例中,引发错误的实质并不在ChildDlg2上,而在其父类BaseDlg上,是它在自己的构造方法中不适当地调用了一个待实现的抽象方法。
从概念上讲,构造方法的职责是正确初始化类变量,让对象进入可用状态。而BaseDlg却赋给了构造方法额外的职责。
本文实例的更好的解决方法是修改BaseDlg类:
public abstract class BaseDlg extends JDialog {
public BaseDlg(Frame frame, String title) {
super(frame, title, true);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(createHeadPanel(), BorderLayout.NORTH);
this.getContentPane().add(createButtonPanel(), BorderLayout.SOUTH);
}
/** 创建对话框实例后,必须调用此方法来布局用户界面
*/
public void initGUI() {
this.getContentPane().add(createClientPanel(), BorderLayout.CENTER);
}
private JPanel createHeadPanel() {
... // 创建对话框头部
}
// 创建对话框客户区域,交给子类实现
protected abstract JPanel createClientPanel();
private JPanel createButtonPanel {
... // 创建按钮区域
}
}
新的BaseDlg类增加了一个initGUI()方法,程序员可以这样使用这个类:
ChildDlg dlg = new ChildDlg();
dlg.initGUI();
dlg.setVisible(true);
总结
类的构造方法的基本目的是正确初始化类变量,不要赋予它过多的职责。
设计类构造方法的基本规则是:用尽可能简单的方法使对象进入就绪状态;如果可能,避免调用任何方法。在构造方法内唯一能安全调用的是基类中具有final属性的方法或者private方法(private方法会被编译器自动设置final属性)。final的方法因为不能被子类覆盖,所以不会产生问题。
关于如何通过实例学习Java对象的构造过程就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 204
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.