What is called a replaceable method in the constructor?

6

In a class that extends JFrame , I have some calls in the constructor, as can be seen below:

 public ListaDeOficiosUI() {
        try {
            this.oficioController = new OficioController();
            this.initComponents();
            //o alerta é exibido nas 3 chamadas de métodos
           //  seguintes, todos da classe JFrame
            this.setTitle(GerOficiosUI.TITULO + " - Lista de Oficios");
            this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            this.addWindowListener(
                    new WindowAdapter() {
                        @Override
                        public void windowClosed(WindowEvent e) {
                            GerOficiosUI x = new GerOficiosUI();
                            x.setLocationRelativeTo(null);
                            x.setVisible(true);
                        }

                        @Override
                        public void windowOpened(WindowEvent e) {
                            requestFocus();
                        }
                    });
            this.setRowSorter();
        } catch (ExcecaoErroIO ex) {
            PrintMessageUI.exibirError(this.getInstance(), ex.getMessage());
            System.exit(0);
        }
    }

However, netbeans is pointing out some snippets of the message Replaceable method call in the constructor , as can be seen in the print below:

The code does not generate errors, it runs normally without any problems.

What does this alert message mean? Can ignoring it cause some problem in the application?

    
asked by anonymous 22.02.2016 / 11:57

2 answers

5

What is

Replaceable method means a method that can be overridden by a subclass.

The warning

This is just an warning of your IDE about a potential problem, not necessarily an error or something inherent in Java.

The problem in this case is that your constructor is depending on a method that can be overridden by a subclass. If this occurs, the subclass can change the behavior of the method and make class construction unpredictable.

This breaks the inheritance agreement, because if the subclass wants to change the initialization behavior, it should overwrite the constructor rather than a method that affects the superclass constructor.

Particularly I do not consider this a very serious case. In most cases, how should this be, this is simply not a class that will be overwritten and this will never happen. So I would simply turn off this warning in the IDE settings.

Some IDEs allow you to omit the warning in the code snippet, in the class, in the project, or globally.

The solution

It is certainly not putting the call in another method private as the other answer says, because you are simply adding unnecessary code in order to omit a warning from the IDE, but does not solve anything , that is, to allow overwriting of a method used in the constructor.

If this class is not designed to be inherited, the solution is to simply do nothing and disable the warning.

If you are designing the class for inheritance, a possible workaround would simply be to make the setTitle method private. It does not make sense for a subclass to change something that has been defined in the superclass constructor.

If the subclass needs to change the title, add a new constructor with a String titulo parameter. Example:

public ListaDeOficiosUI() {
    this("Título default");
}
public ListaDeOficiosUI(String titulo) {
    ...
    this.setTitulo(titulo);
    ...
}
private setTitulo() { ... } 

In this way you maintain the expected behavior of the superclass and the child classes can explicitly change the title, making clear the contract behavior in the hierarchy.

Note on JFrame

Because you are using the method inherited from JFrame , you can not change the visibility of setTitulo and other methods.

In this specific case, you could use the JFrame constructor that already receives the title. Example

public ListaDeOficiosUI() {
    super("Meu Título");
}

For other cases, there is not much of a way.

However, another approach is not to use inheritance. You do not need to extend JFrame ! You can simply reference an attribute in your class that represents the screen, like this:

public class ListaDeOficiosUI {
    private JFrame frame;
    public ListaDeOficiosUI() {
        frame = new JFrame();
        frame.setTitle("Título");
        ....
    }
    ...
}

I consider this approach better because it avoids inheritance where it is simply not needed.

Considerations

Tip: Avoid using IDEs in Portuguese. I do not say evil of who translated, but translation of technical terms are hardly reliable.

    
23.02.2016 / 01:52
0

The way to fix this problem is to not use methods that are replaceable (since Java does not use the virtual word) inside the constructor.

Only use static, private, or final methods in constructors.

    
22.02.2016 / 13:07