• Post Reply Bookmark Topic Watch Topic
  • New Topic

Is there a facility within a constructor that shows object construction is complete?  RSS feed

 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

To have the least obtrusive API, there are times when I want the constructor of the object to launch a thread that is needed by the object.

In most cases, such a thread needs some level of access to the object itself.  This means that I'm leaking out "this" to something that might access the object before it's done creating.

For instance, this is a no-no:

Question: Is there a facility similar to the following (or perhaps in an upcoming version of Java, like 9):Something like the above would guarantee that the object construction is safely over before the thread (that has "this")

I'm rather leery of implementing a separate "start-it" routine that has to be called similar to this by the caller:(etc.)

And I'm similarly leery of hiding the Thread.start() within methods that I know have to be called after the object is done, but have other duties, such as in the case of Swing, co-opting paintComponent to check if Thread is alive, and if not start it.  Or checking for when the object is laidout within its container.  Those are all clumsy.
 
Paul Clapham
Sheriff
Posts: 22841
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nope... consider this situation:





As you can see, the thread is started before the SpecializedThing's initialization is complete. As you say, that could be a disaster.
 
Campbell Ritchie
Marshal
Posts: 56584
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That looks like letting a this reference escape the constructor; as Paul C says, it is something you sh‍ould never do.
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Possible solution: Make the constructor private and provide a static factory method:
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:That looks like letting a this reference escape the constructor; as Paul C says, it is something you sh‍ould never do.


Well in that case, it seems more of a different kind of disaster: Overriding a constructor's helper method.

As far as some "whendone" clause, I suppose the rules could be that the finally block I propose happens after all descendants have been created, no?
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sorry, I'm not used to the reply buttons being on top of the message.  My fault.  Redoing:


Paul Clapham wrote:Nope... consider this situation:





As you can see, the thread is started before the SpecializedThing's initialization is complete. As you say, that could be a disaster.


Well in that case, it seems more of a different kind of disaster: Overriding a constructor's helper method.

As far as some "whendone" clause, I suppose the rules could be that the finally block I propose happens after all descendants have been created, no?
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jesper de Jong wrote:Possible solution: Make the constructor private and provide a static factory method:


That would work and I have made factories in the past, but I

1. Can't do the private: I need this to be extendable by another class
2. would like it to function using this idiom:

X x = new X();

And have that manage everything.

Bottom line though: Asked and answered.  Java does not have a facility similar to what I pondered.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
NEVER DO THIS, even in the way that Jesper presented.

Programmers expect methods to either return something, or do something that causes side-effects. Sure, methods that have side-effects can return something (such as Map.put()), but in those cases the return value is usually not of primary interest. Programs that use constructors or methods that return something interesting are extremely hard to debug when they also cause unexpected side-effects, such as starting threads. How many hours I've lost debugging a program because I skipped over lines because they returned the value I was expecting, but secretly started a background thread or mutated one of the arguments I passed.

createThing() should create a thing. It should not modify any of the arguments it needs to create the thing, it should not modify fields, and it should not start background tasks. If it must do something in the background AND return a thing, it doesn't have a single responsibility.

What's wrong with creating an object (either through the constructor or with a factory method) and then letting the client method call another method that obviously starts a background task?

Thomas Gard wrote:To have the least obtrusive API, there are times when I want the constructor of the object to launch a thread that is needed by the object.

I would argue that APIs that do more than what is expressed by the method names are INTRUSIVE, and much harder to use than obtrusive APIs where every action is explicit.
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:That looks like letting a this reference escape the constructor; as Paul C says, it is something you sh‍ould never do.


Now that I've had my caffeine for the morning and grown an actually functioning brain cell, let me address this statement, since I botched it earlier.  In the case I suggested above (the finally clause that doesn't exist for constructors) the finally code block would only be executed after all construction has completed.  In other words, it functions nearly identically to having that code show up after the call.  Let's use a different keyword:


I'm positing that the above would be functionally identical to:



Perhaps that's more clear.  In any case, there's no facility for it.
 
Campbell Ritchie
Marshal
Posts: 56584
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, that isn't possible. There is no facility for guaranteeing that certain code is executed after other code, except as provided for in the Java® Language Specification by the words “happens‑before”. Even if you have a last line in the constructor to print such a message, it is still possible for the message to be printed before the other lines are completed; if there is a delay getting any of the information the JVM is permitted to optimise execution speed by altering the order of lines with a disjoint frame. There is also no facility for an initialiser block to run after the constructor; initialiser block usually run as if they were in the beginning of the constructor.
You cannot even guarantee that your second code snippet will complete instantiation before the print statement runs because they have disjoint frames; you could consider printing something like the class name of the new object. . . which would mean the object has to be instantiated before starting printing.

Stephan is right about method names; the name shou‍ld make it clear to all reading it what it does: here are three examples of methods whose names don't tell users what they do: 1 2 3. At least I think the names don't make it obvious what those methods do. Stephan is right: that sort of side‑effect can be dangerous.
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:You cannot even guarantee that your second code snippet will complete instantiation before the print statement runs because they have disjoint frames

I'm sorry, I don't understand.  In that code snippet, I had two lines, each with a single action.

1. Create the Thing object
2. Print a statement.

The JLS doesn't require that the line above the println() happen (and complete) first?  Please clarify.

Campbell Ritchie wrote:Stephan is right about method names; the name shou‍ld make it clear to all reading it what it does: here are three examples of methods whose names don't tell users what they do: 1 2 3. At least I think the names don't make it obvious what those methods do. Stephan is right: that sort of side‑effect can be dangerous.

Well it's not a method name with side effects, it's an constructor with side effects.  In this particular case I've created a RepeatButton class that extends JButton (and is also further extensible to other buttons I created such as LEDButton, etc.).  The Repeat button functions by spawning a thread for the button that waits().  The mouseDown event on the button tiggers (notifies) the thread to start its loop.  It's loop that calls the RepeatButton listeners as long as the button remains down, separated by delays.  The delays actually can decrease according to a passed in List of delays to manage acceleration as well (the longer the button is held down).

Basically, invoking the constructor:should be idiomatically identical to any other button:or(etc.), or I will most certainly violate the law of least surprise.

What's unacceptable in this case is to have the threading implementation of the repeating strobe be made external in any way because it's not something that I want to have only show up occasionally.  Consider this mistake: Here I have a button suddenly break the already known idiom.  The user certainly is expecting to create a repeating button that works when you create it.

In other words, the meaning of the constructor is 100% clear: A repeating button.  It's not "a repeating button with a thread you have to start externally".

I suppose I could live with the following:....or some such, but it's still an unexpected idiom to the programmer.

To get around the leaking of this within the constructor, in the past I've usually made such a thing external (as in the .go() or similar---something I won't do for the reason above) or co-opted another method that is guaranteed to be called already.  For instance, right now with RepeatButton, though I'm unhappy with it, I've temporarily co-opted paintComponent() to have the following override
   
As stated, the job of this thread is to simply start and wait() for notification from the button itself.

 
Campbell Ritchie
Marshal
Posts: 56584
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thomas Gard wrote:. . . The JLS doesn't require that the line above the println() happen (and complete) first?
Not unless you can find somewhere in the JLS saying line 1 happens before line 2.
. . .  it's not a method name with side effects, it's an constructor with side effects.
Does that make any difference?
. . . spawning a thread for the button that waits(). . . .
So you are accessing Swing Components via two threads? Dangerous: most Swing classes are non‑thread‑safe. If you want something to be done repeatedly, you are probably better off with a Swing Timer.
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
Thomas Gard wrote:. . . The JLS doesn't require that the line above the println() happen (and complete) first?
Not unless you can find somewhere in the JLS saying line 1 happens before line 2.
. . .  it's not a method name with side effects, it's an constructor with side effects.
Does that make any difference?


Yes, for the reason I stated: The idiom expected.  It's going to completely foul up someone reading my code for no reason.

Campbell Ritchie wrote:. . . spawning a thread for the button that waits(). . . .
So you are accessing Swing Components via two threads? Dangerous: most Swing classes are non‑thread‑safe. If you want something to be done repeatedly, you are probably better off with a Swing Timer.

No, a swing component is notifying a distinct thread.  The only backward reference is a single boolean (key down or not), which is protected.  Swing is certainly not thread safe....I believe I'm.  But what I didn't know was there WAS such a thing as javax.util.SwingTimer class.  THANKS!   I'll look into it.  What JDK revision did that show up in?

But it might not be what I need: I'll have to see how smoothly it changes the delays with setDelay(); I don't want any hiccups.
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is there any way to edit a post like I can in every other forum?  It would help when I foul up a nested quote like I did above (and I forget to preview).
 
Campbell Ritchie
Marshal
Posts: 56584
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thomas Gard wrote:Is there any way to edit a post . . . .
No. We have had trouble with people “correcting” old posts so replies look nonsense. At the moment editing is tightly restricted.
Please PM one of use mods with what you would like to change.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thomas Gard wrote:Well it's not a method name with side effects, it's an constructor with side effects.

Well, constructors simply should never have side-effects. They have only one responsibility: initialize the object to a consistent state. No more than that.

The Repeat button functions by spawning a thread for the button that waits().

So the thread has to wait anyway until the button is held? Then why not just start it in the mouse down event?

Basically, invoking the constructor:should be idiomatically identical to any other button:or(etc.), or I will most certainly violate the law of least surprise.

I don't see how starting the thread in the listener would change anything about the idiomatic use of your custom button. If anything, it's constructors with side-effects that are going to cause the most surprise.

What's unacceptable in this case is to have the threading implementation of the repeating strobe be made external in any way because it's not something that I want to have only show up occasionally.

You can add the listener in the constructor. Just don't start the thread.

Consider this mistake: Here I have a button suddenly break the already known idiom.  The user certainly is expecting to create a repeating button that works when you create it.

This example is flawed, because the thread doesn't need to be running from the start, only when you hold the button down. Besides, you shouldn't be working with threads directly, you should use executor services, or as Campbell has already mentioned, Swing timers.

In other words, the meaning of the constructor is 100% clear: A repeating button.  It's not "a repeating button with a thread you have to start externally".

It doesn't need to start externally, just not in the constructor. There's nothing that needs to be done in the background by the time the object is created, as illustrated by the pointless call of the wait() method. I'll see if I can devise an example with a better approach later.
 
Paul Clapham
Sheriff
Posts: 22841
43
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thomas Gard wrote:But what I didn't know was there WAS such a thing as javax.util.SwingTimer class.  THANKS!   I'll look into it.  What JDK revision did that show up in?


That's javax.swing.Timer and it showed up in Java 2 (which was in 1999 if I remember right).
 
Campbell Ritchie
Marshal
Posts: 56584
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is even a Java™ Tutorials page about it.
 
Thomas Gard
Ranch Hand
Posts: 51
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:
Thomas Gard wrote:The Repeat button functions by spawning a thread for the button that waits().

So the thread has to wait anyway until the button is held? Then why not just start it in the mouse down event?


As my 13 year old likes to tell me often: "because reasons".    Actually, in all GUI designs it's best to keep the stuff of openended expense (e.g. creating threads and timers) out of the human initiate-action/see-results loop.  A repeating button necessitates internally responding on the mouse-down.  The very first Event is fired there.  That "wait()" isn't waiting hardly any time at all.  I don't want any kind of hiccup there, I don't care how short, and especially on potentially slower machines.  It's amazing how the human perception system can detect minute differences in response times from element to element at different times.

Thanks for the heads up: I'm looking into the jx.s.Timers class now; it's dusting off a very distant memory.  I might have actually used it once before, but the majority of my programming was maybe done in 1.1.7 and prior, so perhaps not.

One possible approach will be to make an AcceleratedTimerTask extension that understands the acceleration pairs I'm envisioning.  I could then use that for both javax.swing and java.util Timers in the future.

Thanks everyone.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So you're doing premature optimization. Have you actually benchmarked what the speed difference is between having the thread scheduler notify your background thread, and simply submitting a task to an initialized executor service?

You're throwing away important software engineering principles for the sake of speed optimizations that are so minimal that you probably won't notice them, even on slower machines.

Here's the approach I talked about earlier:
 
Tim Holloway
Saloon Keeper
Posts: 18799
74
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In short: A constructor is called as part of the initialization of an object. In some cases, in fact, more than one constructor will be invoked. Not to mention the initialization code that forms an anonymous function as part of instance initialization. The completion of a constructor does not indicate that the object is ready for use. The Java object construction framework may have other work to do before the object is actually ready.

So it's simply not safe to test or apply within the construction process. The object is only ready for use after the "new" operation is done, or, if using the class methods, the newInstance() method has returned.



When using a bean construction service such as CDI or the Spring Framework, you can employ service amenities such as the @PostConstruct annotation processor, but that's just a call from the object factory after the factory has done a "new" operation to create the bean.
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!