7

so I just saw this code at work, and the author told me it's for inline optimization.

Class Test{
...
void init(){
   //sets variables, call functions, etc
} 
...
}

then he calls it in main like this

Test t=new Test();
t.init();

Instead of having a default constructor with the code from init() in it. He told me it's for inline optimization. Is this correct? How is it faster? where do I read up about this?

  • 4
    Nothing optimize anything in your code.. – Maroun Jan 06 '15 at 16:11
  • How is that supposed to work? – Natix Jan 06 '15 at 16:13
  • 7
    Utter nonsense -- the author is a fool – Software Engineer Jan 06 '15 at 16:14
  • 1
    [See here](http://www.programcreek.com/2011/10/java-class-instance-initializers/) for some subtleties with constructors and initializers. (Even though this Q is about calling "helper" or worker methods after the default constructor, it is is slightly relevant.) Moving *all* the work a named constructor could be doing with pseudo-bean init or setter methods is... not advisable. –  Jan 06 '15 at 16:17
  • the results of the init() are not published with the same strict requirements as the constructor, on the other hand all null-values would be published strictly. So its doubtfull it helps performance, it surely has nothing to do with inlining. – eckes Jan 06 '15 at 17:02

2 Answers2

14

It's not faster. It seems to be predicated on the assumption that a method can be inlined but a constructor can't. Unfortunately that's nonsense, so the entire point of it goes out the window.

Even if this were faster, it would almost certainly be a bad idea. Code should not be optimised at the expense of readability, except in extreme circumstances where every last CPU cycle is critical, and in that case you're unlikely to be using Java.

In fact, this is worse than just being harder to read. The next refactoring will inevitably be for the Test constructor to call the init() method, so that it doesn't always have to be done manually (and doing it manually is a pain and a potential source of bugs if it gets forgotten); and it is bad practice if a constructor calls a method that can be overridden, because a subclass might inadvertently change what happens at construction time when the superclass constructor is called (see this question for more details). When this happens, a subclass of Test within the same package will be able to override the init() method, and then when the subclass invokes super(), either implicitly or explicitly, the superclass's constructor will end up calling the overridden init(). (This particular problem could be got rid of by declaring init() to be private.)

Don't do it.

Community
  • 1
  • 1
chiastic-security
  • 20,430
  • 4
  • 39
  • 67
  • What if there were 2 constructors? It would be easier to read if both called the init method – EDToaster Jan 06 '15 at 16:20
  • _Unless_ the `init` method is doing anything multithreaded (such as registering `this` as a listener to some other thread, starting a new thread that knows about `this`, etc), in which case you _must_ keep `init()` separate for thread safety. – yshavit Jan 06 '15 at 16:21
  • 2
    @JClassic One nice way to handle that is by making one "canonical" constructor (possibly private, if need be) and having the other constructors invoke it via `this(someArg, anotherArg, maybeSomeArg + 42)`. – yshavit Jan 06 '15 at 16:23
1

I do not think that you have anything to optimize. That being said, I do not think that it is a good idea at a design phase either because class initialization is something which each class must do on its own. Placing such behaviour in a seperate method which:

  1. Has to be called separately
  2. Can, in turn be also overridden

Is something which is not usually recommended.

npinti
  • 51,780
  • 5
  • 72
  • 96