Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4957061

Incorrect logic in example demonstrating assertions as preconditions

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 1.4.1
    • docs
    • x86
    • windows_2000


      Name: jl125535 Date: 11/19/2003


      URL OF FAULTY DOCUMENTATION :
      http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html#preconditions

      A DESCRIPTION OF THE PROBLEM :
      In the given example, the combination of IllegalArgumentException and assertion as shown will reject every value for the parameter of setRefreshRate() except MAX_REFRESH_RATE.

      That is, every value larger than MAX_REFRESH_RATE will result in an IllegalArgumentException being thrown by the public method, whereas values smaller than MAX_REFRESH_RATE will be passed to the private method as values larger than 1000/MAX_REFRESH_RATE and then will trigger an AssertionError.



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      One way to fix this is to rewrite the assertion as:
      assert interval < 1000 && interval >= 1000/MAX_REFRESH_RATE : interval;

      But then the "Note" in the following paragraph makes no sense. Of course, as it stands the "Note" makes no sense anyway.

      ACTUAL -
      (from http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html#preconditions)
      <current documentation>
      Preconditions

      By convention, preconditions on public methods are enforced by explicit checks that throw particular, specified exceptions. For example:

          /**
           * Sets the refresh rate.
           *
           * @param rate refresh rate, in frames per second.
           * @throws IllegalArgumentException if rate <= 0 or
           * rate > MAX_REFRESH_RATE.
           */
           public void setRefreshRate(int rate) {
               // Enforce specified precondition in public method
               if (rate <= 0 || rate > MAX_REFRESH_RATE)
                   throw new IllegalArgumentException("Illegal rate: " + rate);

               setRefreshInterval(1000/rate);
           }

      This convention is unaffected by the addition of the assert construct. Do not use assertions to check the parameters of a public method. An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError.

      You can, however, use an assertion to test a nonpublic method's precondition that you believe will be true no matter what a client does with the class. For example, an assertion is appropriate in the following "helper method" that is invoked by the previous method:

         /**
          * Sets the refresh interval (which must correspond to a legal frame rate).
          *
          * @param interval refresh interval in milliseconds.
          */
          private void setRefreshInterval(int interval) {
              // Confirm adherence to precondition in nonpublic method
              assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;

              ... // Set the refresh interval
          }

      Note, the above assertion will fail if MAX_REFRESH_RATE is greater than 1000 and the client selects a refresh rate greater than 1000. This would, in fact, indicate a bug in the library!
      </current>
      (Incident Review ID: 186201)
      ======================================================================
      ###@###.### 2003-11-19

            santhoshla Santhosh La (Inactive)
            jleesunw Jon Lee (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: