我在同一个java文件中有以下代码。
import javax.swing.SwingUtilities;
import java.io.File;
public class MainClass2{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run() {
javax.swing.JFileChooser jfc = new MyFileChooser();
File file = jfc.getSelectedFile();
}
});
}
}
class MyFileChooser extends javax.swing.JFileChooser{
public MyFileChooser(){
System.out.println("constructor call");
}
@Override
public java.io.File getSelectedFile(){
System.out.println("call to getSelectedFile");
return null;
}
}
当我运行它时,输出给了我
call to getSelectedFile
constructor call
call to getSelectedFile
输出不应该是
constructor call
call to getSelectedFile
我正在使用java 5.
答案 0 :(得分:8)
MyFileChooser
的构造函数相当于:
public MyFileChooser() {
super(); // ***
System.out.println("constructor call");
}
对getSelectedFile()
的第一次调用是由MyFileChooser
的基类构造函数构成的,该构造函数在***
之前的System.out.println("constructor call")
上隐式调用。 }。
这是堆栈跟踪:
MyFileChooser.getSelectedFile() line: 16
AquaFileChooserUI.installComponents(JFileChooser) line: 1436
AquaFileChooserUI.installUI(JComponent) line: 122
MyFileChooser(JComponent).setUI(ComponentUI) line: 670
MyFileChooser(JFileChooser).updateUI() line: 1798
MyFileChooser(JFileChooser).setup(FileSystemView) line: 360
MyFileChooser(JFileChooser).<init>(File, FileSystemView) line: 333
MyFileChooser(JFileChooser).<init>() line: 286
MyFileChooser.<init>() line: 11
答案 1 :(得分:1)
构造函数:
public MyFileChooser(){
System.out.println("constructor call");
}
似乎与基类的构造函数无关。但是有一个对javax.swing.JFileChooser()的隐式超级调用,它调用getSelectedFile();
。所以你的构造函数实际上是这样的:
public MyFileChooser(){
super();
System.out.println("constructor call");
}
因为jfc是MyFileChooser的对象,所以这个方法:
@Override
public java.io.File getSelectedFile(){
System.out.println("call to getSelectedFile");
return null;
}
被调用。打印出“调用getSelectedFile”,然后“调用getSelectedFile”。
答案 2 :(得分:1)
如果你查看堆栈跟踪,你会看到JFileChooser
构造函数调用setup(FileSystemView view)
调用updateUI()
,它调用JComponent超类中的setUI()
,在特定于平台的UI类上调用installUI
,然后该类调用installComponents
,再次调用getSelectedFile
。
Effective Java 2nd Edition引用:
为了允许继承,类必须遵守一些限制。构造函数不得直接或间接调用可覆盖的方法。如果违反此规则,将导致程序失败。超类构造函数在子类构造函数之前运行,因此在子类构造函数运行之前将调用子类中的重写方法。如果重写方法依赖于子类构造函数执行的任何初始化,则该方法将不会按预期运行。
但是,当然,Swing工具包并不总是遵循这个建议; - )
完整堆栈跟踪:
at MyFileChooser.getSelectedFile(MainClass2.java:27)
at com.apple.laf.AquaFileChooserUI.installComponents(AquaFileChooserUI.java:1436)
at com.apple.laf.AquaFileChooserUI.installUI(AquaFileChooserUI.java:122)
at javax.swing.JComponent.setUI(JComponent.java:670)
at javax.swing.JFileChooser.updateUI(JFileChooser.java:1798)
at javax.swing.JFileChooser.setup(JFileChooser.java:360)
at javax.swing.JFileChooser.<init>(JFileChooser.java:333)