About using assertion

M

Michal Kleczek

Lew said:
That is wrong. That needs to be checked with an 'if' if 'NaN' is not a
legitimate input. 'assert' is not meant to correct things, only to make
sure

I totally agree with you.
that the correction is documented and proven. If 'assert' is turned off
in production, you still have the bug if you use 'assert' as the only
guard.

I was imprecise - just wanted to praise an example of "having confidence"
being sooo wrong and how having assertions (even though they look redundant)
_may_ help you.
 
L

Lew

I totally agree with you.


I was imprecise - just wanted to praise an example of "having confidence"
being sooo wrong and how having assertions (even though they look redundant)
_may_ help you.

Totally correct.

Assertions are a signpost: HERE THERE BE AN INVARIANT!

When subtypes or refactored code violate the invariant, the assertion can help
catch it.

public class Foo
{
private Attribute attribute;

public void setAttribute( Attribute attr )
{
if ( attr == null )
{
throw new IllegalArgumentException( "null argument, dummy" );
}
attribute = attr;
assert attribute != null;
}

public Attribute getAttribute()
{
assert attribute != null;
return attribute;
}
}

public class Bar extends Foo()
{
public void setAttribute( Attribute attr )
{
attribute = attr;
}
}

The assertion will help reveal that class 'Bar' violated the invariant. In
production, the 'NullPointerException' (in the logs from 'getAttribute()'
clients) will trigger an investigation, which will include enabling assertions
for the class that yields the value, and then the invariant checks will help
find the problem.
 
R

Robert Klemme

Totally correct.

Assertions are a signpost: HERE THERE BE AN INVARIANT!

When subtypes or refactored code violate the invariant, the assertion canhelp
catch it.

  public class Foo
  {
    private Attribute attribute;

    public void setAttribute( Attribute attr )
    {
      if ( attr == null )
      {
        throw new IllegalArgumentException( "null argument, dummy" );
      }
      attribute = attr;
      assert attribute != null;
    }

    public Attribute getAttribute()
    {
      assert attribute != null;
      return attribute;
    }
  }

  public class Bar extends Foo()
  {
    public void setAttribute( Attribute attr )
    {
      attribute = attr;

Sorry for the nitpicking, but this cannot compile unless you make
"attribute" protected or package visible. But that in itself would be
a code smell IMHO. (Even though Java's std lib uses protected in
various places. But that's a completely different topic...)
    }
  }

The assertion will help reveal that class 'Bar' violated the invariant.  In
production, the 'NullPointerException' (in the logs from 'getAttribute()'
clients) will trigger an investigation, which will include enabling assertions
for the class that yields the value, and then the invariant checks will help
find the problem.

I think I get your point about the usage of assert here but we might
find a better example. In this particular case the NPE would catch
misbehaved sub class code anyway which must go through setAttribute if
the member variable remains declared "private" (my preferred
solution).

How about this as an example using template method pattern.

public abstract class Base {
/** Sub classes must override this and return an Attribute
* where {@link Attribute#getProperty()} returns something
* useful (!= null).
* @return an Attribute with Property, not null.
*/
protected abstract Attribute getAttribute();

/** This is the great algorithm this class is all about. */
public void theAlgorithm() {
final Attribute at = getAttribute();
/* We use individual asserts instead of && to easier find the
* violated rule. */
assert at != null;
assert at.getProperty() != null;
// now we can start working
System.out.println("Now this works: " +
at.getProperty().getLength());
}
}

Kind regards

robert
 
L

Lew

Sorry for the nitpicking, but this cannot compile unless you make
"attribute" protected or package visible. But that in itself would be
a code smell IMHO. (Even though Java's std lib uses protected in
various places. But that's a completely different topic...)

Good call.
I think I get your point about the usage of assert here but we might
find a better example. In this particular case the NPE would catch
misbehaved sub class code anyway which must go through setAttribute if
the member variable remains declared "private" (my preferred
solution).

How about this as an example using template method pattern.

public abstract class Base {
/** Sub classes must override this and return an Attribute
* where {@link Attribute#getProperty()} returns something
* useful (!= null).
* @return an Attribute with Property, not null.
*/
protected abstract Attribute getAttribute();

/** This is the great algorithm this class is all about. */
public void theAlgorithm() {
final Attribute at = getAttribute();
/* We use individual asserts instead of&& to easier find the
* violated rule. */
assert at != null;
assert at.getProperty() != null;
// now we can start working
System.out.println("Now this works: " +
at.getProperty().getLength());
}
}

My point would've been better made if I'd referred to refactoring instead of
subclassing. Your example is better. I do worry about the use of 'assert' to
check the invariant without backing logic, OTOH this is a use case where the
superclass seeks to avoid the overhead of runtime checking when the
implementor is supposedly following the documentation. So it's a really good
example.

Because the method is protected, it's part of the API contract for 'Base', so
a paranoid author would have put 'if' checks, possibly exceptions into
'theAlgorithm()'. But it's only part of the contract for programmers who live
close to the implementation, so it's perfectly reasonable to insist that the
subclass handle all the 'if' checks, and that the superclass have just
'assert' to provide a safety net. An NPE at the 'println()' call would hint
to ops to enable assertions, then the problem diagnosis is simple via those
assertions.

This will now be part of my pedagogical toolkit for explaining 'assert'.
Thank you.
 
T

Tim McDaniel

Negative zero is a strange beast. As far as I can tell, it exists
mainly to produce negative infinity when it is used as a divisor. For
example, it is equal to zero for comparison purposes.

Hm, I thought it didn't, but the authoritative-looking but old
<http://www.concentric.net/~ttwang/tech/javafloat.htm> says otherwise.

However, Float/Double apparently acts differently from float/double:

Comparing two Java "Float" objects can have different semantics
than comparing two Java "float" values. Recall the "float" class
is a Java primitive class, while java.lang.Float is a subclass of
"Object".

A "NaN" value is not equal to itself. However, a "NaN" Java
"Float" object is equal to itself. The semantic is defined this
way, because otherwise "NaN" Java "Float" objects cannot be
retrieved from a hash table.

(new Float(0.0 / 0.0)).equals(new Float(0.0 / 0.0)) -> true

For the class java.lang.Float, objects are ordered from lowest to
highest: -Infinity, negative numbers, -0.0, 0.0, positive numbers,
Infinity, NaN. "java.lang.Double" objects are identically ordered.

(new Float(0.0)).equals(new Float(-0.0)) -> false
 
L

Lew

Hm, I thought it didn't, but the authoritative-looking but old
<http://www.concentric.net/~ttwang/tech/javafloat.htm> says otherwise.

Authoritative-looking is not authoritative, though it is correct.

Authoritative is the official documentation, which your source elucidates.
However, Float/Double apparently acts differently from float/double:

Maybe because they *are* different?

For example, the mechanism of comparison differs. Primitives don't use method
calls, object types do.
Comparing two Java "Float" objects can have different semantics
than comparing two Java "float" values. Recall the "float" class
is a Java primitive class, while java.lang.Float is a subclass of
"Object".

A "NaN" value is not equal to itself. However, a "NaN" Java
"Float" object is equal to itself. The semantic is defined this
way, because otherwise "NaN" Java "Float" objects cannot be
retrieved from a hash table.

(new Float(0.0 / 0.0)).equals(new Float(0.0 / 0.0)) -> true

For the class java.lang.Float, objects are ordered from lowest to
highest: -Infinity, negative numbers, -0.0, 0.0, positive numbers,
Infinity, NaN. "java.lang.Double" objects are identically ordered.

(new Float(0.0)).equals(new Float(-0.0)) -> false

The primitives are ordered thus:
"Except for NaN, floating-point values are ordered; arranged from smallest to
largest, they are negative infinity, negative finite nonzero values, positive
and negative zero, positive finite nonzero values, and positive infinity."
JLS §4.2.3

It goes on to say that NaN can be represented by multiple different bit
patterns that can be distinguished programmatically.

As with other primitives, 'double' is ordered via the ==, >, <, and related
operators.

With the reference type 'Double' comparison is via the 'compareTo()' method,
which of course is different from and independent of the primitive operators.
Since the purposes of a reference type differ from those of a primitive type
in Java, for example, 'Comparable#compareTo()' should be consistent with
'equals()' (as mentioned in the docs for 'Double'), it makes sense that the
semantics might differ. Unfortunate, perhaps, but sensible.

<http://download.oracle.com/javase/6/docs/api/java/lang/Double.html#compareTo(java.lang.Double)>

"Compares two Double objects numerically. There are two ways in which
comparisons performed by this method differ from those performed by the Java
language numerical comparison operators (<, <=, ==, >= >) when applied to
primitive double values:

"- Double.NaN is considered by this method to be equal to itself and greater
than all other double values (including Double.POSITIVE_INFINITY).

"- 0.0d is considered by this method to be greater than -0.0d.

"This ensures that the natural ordering of Double objects imposed by this
method is consistent with equals."

This doesn't quite assure me that all forms of 'NaN' (by bit pattern) would
box to 'Double.valueOf( Double.NaN )'. I'll have to run an example program.

Anyway, it is an interesting point of comparison between the very different
'double' and 'Double' types (and their narrower counterparts) and a good thing
to watch out for in the mapping between them. Thanks for bringing it up.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,664
Latest member
RoseannBow

Latest Threads

Top