Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: re-wrote explanatory prose. Broke conformant guideline up to show both two-if and short-circuit implementations. Noted assumption that files are held in secure storage.

The conditional AND and OR operators (&& and ||, respectively) exhibit short-circuit behavior. That is, the second operand is evaluated only when the result of the conditional operator cannot be deduced solely by evaluating the first operand. Consequently, when the result of the conditional operator can be deduced solely from the result of the first operand, the second operand will remain unevaluated; its side-effects, if any, will never occur.

One should exercise caution when the operands following the first operand contain side effects. In the following code, the value of i is incremented only when i >= 0.

...

Although the behavior is well defined, it is unclear whether i gets is incremented on any particular execution.

Noncompliant Code Example

This noncompliant code example attempts to rename a given file if it exists, perform operations on the renamed file, and then delete the renamed file. For the purposes of this example, we assume that the file operations are performed on a secure portion of the filesystem. Consequently, we need not consider the time-of-check to time-of-use vulnerabilities that would otherwise be of concern.

When However, because of the short-circuit behavior of the || operator, the renameTo() method does not execute when the exists() method returns true. Because of this, the renamed file could or could not exist, execution continues with the call to File.delete(); the call to File.renameTo() remains unexecuted in this case. Consequently, the code as written fails to guarantee the existence of the renamed file, which can result in an attempt to use and then subsequently to delete a nonexistent file. This problem is exacerbated by the fact that Further, File.delete() does not throw an exception but returns an error code on failure , which is sometimes silently ignored or perceived as unnecessary. (See rather than throwing an exception; this noncompliant example incorrectly ignores the return value from File.delete() (see guideline EXP00-J. Do not ignore values returned by methods).)

Code Block
bgColor#ffcccc
class BadRenameFile {
  public static void main(String[] args) {
    File fOriginal = new File("original.txt");
    File fNew = new File("new.txt");
    if (fOriginal.exists() || fOriginal.renameTo(fNew)) {
      // do something with fNew
      fNew.delete();
    }
  }
} 

Compliant Solution

Knowledge of the short-circuit behavior can be used to enforce the desired specification. This compliant solution traps an error if the file does not exist or when it cannot be renamed to the new file name. Operations on the new file followThis compliant solution checks both for the existence of the original file as well as for the success of the rename operation. It also handles the error when either check fails. It deletes the new file when operations are complete, checking for and handling the possible failure of the delete operation.

Code Block
bgColor#ccccff
class RenameFile {
  public static void main(String[] args) {
    File fOriginal = new File("original.txt");
    File fNew = new File("new.txt");

    if (!fOriginal.exists() || ) {
      // handle error
    }
    if (!fOriginal.renameTo(fNew)) {
      // handle error 
    }
    // do something with fNew
    if (!fNew.delete()) {
      // handle error  
    }
  }
} 

When error handling for failure of the existence and rename operations is identical, that portion of the code could be rewritten as:

Code Block
bgColor#ccccff

    if (!fOriginal.exists() || !fOriginal.renameTo(fNew)) {
      // handle error 
    }

In this form, the short-circuit behavior of the || operation provides identical semantics to the "two-if-statement" version shown above.

Exceptions

Wiki Markup
*EXP06-EX1:* Programmers who are aware of the short-circuit behavior often use it to their advantage, as in this example from Flanagan \[[Flanagan 2005|AA. Bibliography#Flanagan 05]\]:

...

Wiki Markup
\[[Flanagan 2005|AA. Bibliography#Flanagan 05]\] 2.5.6. Boolean Operators
\[[JLS 2005|AA. Bibliography#JLS 05]\] Sections [15.23|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.23] "Conditional-And Operator &&" and [15.24|http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.24] "Conditional-Or Operator ||"

...