10

同じ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を使用しています。

4

3 に答える 3

1

スタック トレースを見ると、JFileChooserコンストラクターがsetup(FileSystemView view)which を呼び出しupdateUI()setUI()JComponent スーパークラスを呼び出しinstallUI、プラットフォーム固有の UI クラスを呼び出し、このクラスが を呼び出しinstallComponentsgetSelectedFile再び呼び出すことがわかります。

有効な 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)
于 2013-04-04T08:01:59.830 に答える