Alex Rivera | Logout

Java Flow of execution - overridden method gets executed first than the constructor

Asked 2013-04-04T07:28:28.820
10

I have the following code, in the same java file.

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;
    }
}

When I run it, the output gives me

call to getSelectedFile

constructor call

call to getSelectedFile

Shouldn't the output be

constructor call

call to getSelectedFile

I'm using java 5.

Edit
Report

1 Answer

1

If you look at the stack trace, you'll see that the JFileChooser constructor calls setup(FileSystemView view) which calls updateUI(), which calls setUI() in the JComponent superclass, which calls installUI on a platform-specific UI class, this class then calls installComponents, which calls getSelectedFile again.

A quote from Effective Java 2nd Edition:

There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

But of course, the Swing toolkit doesn't always follow this advice ;-)

Full stack trace:

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)
answered 2013-04-04T08:01:59.830

Your Answer