Skip to main content

"Fail fast" and constructors...

12 replies [Last post]
Anonymous

... what do if super constructors misbehave? Any way to check for
parameter validity first? Thinking about it, "chaining" constructors
have the same problem with "this"

An example: JList(Vector) and JList(Object[]) don't check if the given
Vector/Object parameter is !null. This leads to NPE "later" - when
accessing model.getSize(), f.i. JXList tries to fail at once, currently like

<br />
super(...);<br />
if (listData == null) throw ...<br />

Naturally, I would like to force the check before calling super. And far
back in my mind is some trick with ternary operator, but I can't
remember it or if it really is possible. Any ideas?

Thanks
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
dmouse
Offline
Joined: 2003-06-09
Points: 0

> looks a bit funny (but there's the ternary again )
> Might generics
> help somehow in the checkArg?

Might we implement this using annotations? I'd prefer to not see this type of code littered all over the place.

Noel Grandin

A little bit hacky, but .....

public class Test2 extends Something {

public Test2(Float f)
{
super(isNotNull(f));
}

private static T isNotNull(T obj)
{
if (obj==null) throw new IllegalArgumentException();
return obj.getClass().cast(obj);
}
}

Kleopatra wrote:
> Noel Grandin wrote:
>> public class Test extends Something {
>>
>> public Test(Object arg)
>> {
>> super(checkArg(arg));
>> }
>>
>> private static void checkArg(arg)
>> {
>> if (arg==null) throw new IllegalParameterException();
>> }
>> }
>>
>
> Hmm ... the devil's in the details: we need a return value in the
> checkArg. Which is different for the different J/X/List constructors.
>
> [code]
> public Test(SomeType arg) {
> super(checkArg(arg) ? arg : null);
> }
>
> public Test(OtherType arg) {
> super(checkArg(arg) ? arg : null);
> }
>
> static boolean checkArg(Object value) {
> if (value == null) throw ..
> return true;
> }
> [/code]
>
> looks a bit funny (but there's the ternary again ) Might generics
> help somehow in the checkArg?
>
>
> Thanks
> Jeanette
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>
>

NOTICE: Please note that this email, and the contents thereof,
are subject to the standard Peralex email disclaimer, which may
be found at: http://www.peralex.com/disclaimer.html

If you cannot access the disclaimer through the URL attached
and you wish to receive a copy thereof please send
an email to email@peralex.com

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Noel Grandin wrote:
> public class Test extends Something {
>
> public Test(Object arg)
> {
> super(checkArg(arg));
> }
>
> private static void checkArg(arg)
> {
> if (arg==null) throw new IllegalParameterException();
> }
> }
>

Hmm ... the devil's in the details: we need a return value in the
checkArg. Which is different for the different J/X/List constructors.

[code]
public Test(SomeType arg) {
super(checkArg(arg) ? arg : null);
}

public Test(OtherType arg) {
super(checkArg(arg) ? arg : null);
}

static boolean checkArg(Object value) {
if (value == null) throw ..
return true;
}
[/code]

looks a bit funny (but there's the ternary again ) Might generics
help somehow in the checkArg?

Thanks
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

david_hall
Offline
Joined: 2003-06-12
Points: 0

> Hmm ... the devil's in the details: we need a return
> value in the
> checkArg. Which is different for the different
> J/X/List constructors.
[code]
> public Test(SomeType arg) {
> super(checkArg(arg) ? arg : null);
> }
>
> public Test(OtherType arg) {
> super(checkArg(arg) ? arg : null);
> }
>
> static boolean checkArg(Object value) {
> if (value == null) throw ..
> return true;
> }
[/code]
> looks a bit funny (but there's the ternary again )
> Might generics help somehow in the checkArg?

No, not really -- generics can't really tell you if the runtime argument is present or not. You'd probably end up writing something like
[code]
public class Test extends Base{
public Test(T... args) {
super(checkArg(args) ? arg : null);
}

public Test(Collection args) {
super(checkArg(args) ? arg : null);
}

static boolean checkArg(Object value) {
if (value == null) throw ..
return true;
}
[/code]
... which has some benefits, but checking for nulls at construction isn't one of them. As long as you're doing the ternary thing anyway, why not supply an empty resource when given a null?
[code]
public class Test extends Base{
public Test(Object... args) {
super(checkArg(args) ? arg : new Object[0]);
}

public Test(Collection args) {
super(checkArg(args) ? arg : new ArrayList());
}

static boolean checkArg(Object value) {
if (value == null) throw ..
return true;
}
[/code]
I made it non-generic because don't have access to the code that makes arrays of T's in a typesafe manner, and (as far as I can remember) it requires a Class argument, and because I can't remember off the top of my head without having had a lot more coffee than I've had this morning if
[code]
super(checkArg(args) ? arg : (T[]) new Object[0]);
[/code]
would compile with a warning or be rejected entirely

dave

Kleopatra

Hi David,

>
>
> No, not really -- generics can't really tell you if the runtime argument is present or not.

yeah, that's what I suspected - thanks for spelling it out again!

> As long as you're doing the ternary thing anyway, why not supply an empty resource when given a null?

That's a good question: whether or not to silently substitute a null
resource depends on what to view as a programmer's error, IMO. In an
ideal world, these preconditions (plus the resulting runtime exception
if violated) would be documented. In the concrete case of JList that's
not the case: both JList(Vector) and JList(Object[]) silently accept the
null but not so silently throw NPEs sometime later. Now what was the
intention: the half-hearted implemeted "makes-no-sense to wrap a
ListModel around a null whatever structure" or the documented (by
omission - in SwingX' convention) "we-take-care-of-null"?

Personally, I would opt for the first - a developer using the wrapping
constructors expects the wrapped structures to at least exist, so a
runtime error would help her to find its source quickly.

Hmmm ... not really a big point but makes me feel itchy ...

Thanks!
Jeanette

PS: lucky you - that coffee helps to get generics right :-)

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

david_hall
Offline
Joined: 2003-06-12
Points: 0

It's definitely easy to come up with good justifications either way. As a general rule, I tend to agree with where you seem to be going: either extreme (throw NPE (or the equivalent) on construction vs. silently insert a default resource) is far better than throwing NPE on first use, as it either works (presumably correctly) or fails close to the error.

It's the 'presumably correctly' that gets you in trouble in many cases, as it can be difficult to know what the right answer is. Having been down the path of attempting a much more humane framework, I've seen the logical/rhetorical/usability pitfalls that can result from trying to presume the defaults consistently and predictably.

OTOH, in this one case, I tend to take a slightly different perspective. I don't believe that we're really "wrapping" the input object here -- we're copying its contents into some other structure under our control (aren't we?).

The array/collection that is being passed isn't important in and of itself: it is just there for the things that it contains. The internal state mechanism isn't shared with clients, and since the implementation is going to copy the contents of the array/collection to some internal structure anyway, there can be no harm in interpreting a null array/collection as equivalent to an empty array/collection.

dave

Kleopatra

jdnc-interest@javadesktop.org wrote:
> It's definitely easy to come up with good justifications either way.

yes, I fully agree (with your next paragraphs as well - have been all
the places :-)

>
> OTOH, in this one case, I tend to take a slightly different perspective. I don't believe that we're really "wrapping" the input object here -- we're copying its contents into some other structure under our control (aren't we?).
>

that's the problem: JList (and JTable) _really_ wrap a model around the
input parameter. Nothing I would do (at least not without good reason,
which super's implementators might have but decided not to publish ),
but it's the heritage we live with. Hmm... on the other hand: it's
SwingX, so we are free to change it. Should we? Are they used by
anybody? Honestly, I never do - except when testing.

> The array/collection that is being passed isn't important in and of itself: it is just there for the things that it contains. The internal state mechanism isn't shared with clients, and since the implementation is going to copy the contents of the array/collection to some internal structure anyway, there can be no harm in interpreting a null array/collection as equivalent to an empty array/collection.
>

100% ACK. The question here is if it's an implementation accident that
the internal implementation state is shared (by creating the model on
top of the data source) or really useful.

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Thanks everybody for your interesting input - I'll take a couple of days
to digest the various aspects and then come back to this (and decide
what-to/how-to solve in swingx :-).

CU
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Hi folks,

this has been a really interesting thread - answering my how-to question
with several technical possibilities and a deeper why-to/when-to debate.
All this brought me back to earth: my concrete problem is working around
a concrete misbehaviour of super constructors, not solving a general
case (as was my first impression). So going for the most readable while
explicitly exposing the throwing looks like a good simple solution.

Thanks everybody!
Jeanette

PS: there's still the old question - which Exception should be thrown?
The most fitting would be a NPE, super throws an IllegalArgument in the
constructor taking a ListModel (which should be a NPE as well?), so I
currently do throw a IAE int the Object[]/Vector constructors ... hmmm ..

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Jesse Wilson

On 6/12/06, Kleopatra wrote:
> [code]
> super(...);
> if (listData == null) throw ...
> [/code]
> Naturally, I would like to force the check before calling super....

Ideally the Java language would allow you to
have a few statements before the super() call.

Since the language doesn't have this feature,
doing the precondition checks after super() looks
like the cleanest, most readable solution.

Cheers,
Jesse

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Noel Grandin

public class Test extends Something {

public Test(Object arg)
{
super(checkArg(arg));
}

private static void checkArg(arg)
{
if (arg==null) throw new IllegalParameterException();
}
}

Kleopatra wrote:
>
> ... what do if super constructors misbehave? Any way to check for
> parameter validity first? Thinking about it, "chaining" constructors
> have the same problem with "this"
>
> An example: JList(Vector) and JList(Object[]) don't check if the given
> Vector/Object parameter is !null. This leads to NPE "later" - when
> accessing model.getSize(), f.i. JXList tries to fail at once,
> currently like
>
> [code]
> super(...);
> if (listData == null) throw ...
> [/code]
>
> Naturally, I would like to force the check before calling super. And
> far back in my mind is some trick with ternary operator, but I can't
> remember it or if it really is possible. Any ideas?
>
> Thanks
> Jeanette
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>
>

NOTICE: Please note that this email, and the contents thereof,
are subject to the standard Peralex email disclaimer, which may
be found at: http://www.peralex.com/disclaimer.html

If you cannot access the disclaimer through the URL attached
and you wish to receive a copy thereof please send
an email to email@peralex.com

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Kleopatra

Hi Noel,

I knew I overlooked something obvious :-)

Thanks!
Jeanette

Noel Grandin wrote:
> public class Test extends Something {
>
> public Test(Object arg)
> {
> super(checkArg(arg));
> }
>
> private static void checkArg(arg)
> {
> if (arg==null) throw new IllegalParameterException();
> }
> }
>
> Kleopatra wrote:
>
>>... what do if super constructors misbehave? Any way to check for
>>parameter validity first? Thinking about it, "chaining" constructors
>>have the same problem with "this"
>>
>>An example: JList(Vector) and JList(Object[]) don't check if the given
>>Vector/Object parameter is !null. This leads to NPE "later" - when
>>accessing model.getSize(), f.i. JXList tries to fail at once,
>>currently like
>>
>>[code]
>>super(...);
>>if (listData == null) throw ...
>>[/code]
>>
>>Naturally, I would like to force the check before calling super. And
>>far back in my mind is some trick with ternary operator, but I can't
>>remember it or if it really is possible. Any ideas?
>>
>>Thanks
>>Jeanette
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
>>For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>>
>>
>
>
>
> NOTICE: Please note that this email, and the contents thereof,
> are subject to the standard Peralex email disclaimer, which may
> be found at: http://www.peralex.com/disclaimer.html
>
> If you cannot access the disclaimer through the URL attached
> and you wish to receive a copy thereof please send
> an email to email@peralex.com
>
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net