0

These days I was reading about good pratices on java, and at some point my world has broken in pieces, because they say that call "init" methods on constructor can be a bad pratice, I know.. public methods can be overridden, but in my case is a little bit different, so please help take it of my head. example:

    public class MLabel extends JLabel {

    private Color color;

    public MLabel(String txt, Color color, int align) {
        super(txt, null, align);
        this.color = color;
        init(); 
    }

    private void init() {
        setFont(new Font(Font.SERIF, Font.BOLD, 16));
        setForeground(color);
    }

}

I already read that answer, but still couldn't find the solution, think that factories will make a much robust code for this simple task, I just want to "configure" the JLabel for easy usage

thank you all, study about good pratices on programming is a little hard because the problems don't appear with errors but with how it could be made, I've upvoted all for the great answers, and I'll change inits() for factories for now, at least.. thank you

3 Answers3

1

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 get 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. To make this concrete, here’s a class that violates this rule:

Source : Effective Java, Second Edition, page 89.

You can read the whole discussion to get the idea why not to call init methods in constructor. It is a good idea to use life cycle hooks, e.g. frameworks like spring provide such features.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
Imran
  • 1,732
  • 3
  • 21
  • 46
  • "program failure **can** result", not "**will**". – Olivier Grégoire Aug 28 '17 at 20:22
  • Yeah, you should tell this to the book's authors. :) – Imran Aug 28 '17 at 20:24
  • Since you kindly gave the source, I checked. Indeed they say so, (it's on page 89, not 90). However, the source can sometimes be wrong. Everybody can make such overridable method, but if you use it responsibly, there's **no reason that the program will** result in a failure. It only **can** and will happen only if you fail to override responsibly. – Olivier Grégoire Aug 28 '17 at 20:36
  • And how can I avoid this? have another (and good) way to do? – Marcelo Perez Maciel Aug 29 '17 at 12:45
  • Other than that, if you put init methods in your constructor, that may result in duplicate code. E.g. you have a no arg constructor from where you call the method. Then you decided to add a new constructor with args, then either your init method will not be called or you have to copy the method to all constructors that is a bad practice. And your init method might be private which is not over ridable, but you may call another method which can be override, and this is difficult to restrict as the project grows.The best is to delighted the initialization process to a framework like Spring – Imran Aug 29 '17 at 13:18
  • or create static factory methods see Effective Java, personally I would not use static factory methods as long as I can use a framework that initializes beans for me. – Imran Aug 29 '17 at 13:23
0

Its better to simplify constructors by simple field initialization at the max and seperating complex initialization like init() in another Factory class dedicated for the purpose.

Rahul Raj
  • 3,197
  • 5
  • 35
  • 55
  • I don't want to use factories because the code will be always the same, is just to make a personalized label, and I'll use it for the entire program (is a very small program) – Marcelo Perez Maciel Aug 29 '17 at 12:48
0

It is a good practice in java to use "Lean - constructors". Especially in frameworks like spring. In a constructor, if there is a init, there is a good chance it could be used to mis use it. Lets say there is a connection to database via init. That is a potential failure point. It is a good practice to avoid that. It is better to be able to create the bean or object first and then have it fail upon the first use of the object if there is a wrong configuration or init.

In your case, what if there was a failure in creating object Font? You are not even creating MLabel in that case. It is best to avoid this situation.

BudsNanKis
  • 224
  • 5
  • 17