MutableException

Since Checkstyle 3.2

Description

Ensures that exception classes (classes with names conforming to some pattern and explicitly extending classes with names conforming to other pattern) are immutable, that is, that they have only final fields.

The current algorithm is very simple: it checks that all members of exception are final. The user can still mutate an exception's instance (e.g. Throwable has a method called setStackTrace which changes the exception's stack trace). But, at least, all information provided by this exception type is unchangeable.

Rationale: Exception instances should represent an error condition. Having non-final fields not only allows the state to be modified by accident and therefore mask the original condition but also allows developers to accidentally forget to set the initial state. In both cases, code catching the exception could draw incorrect conclusions based on the state.

Properties

name description type default value since
extendedClassNameFormat Specify pattern for extended class names. Pattern "^.*Exception$|^.*Error$|^.*Throwable$" 6.2
format Specify pattern for exception class names. Pattern "^.*Exception$|^.*Error$|^.*Throwable$" 3.2

Examples

To configure the check:

<module name="Checker">
  <module name="TreeWalker">
    <module name="MutableException"/>
  </module>
</module>
        

Example:

class FirstClass extends Exception {
  private int code; // OK, class name doesn't match with default pattern

  public FirstClass() {
    code = 1;
  }
}

class MyException extends Exception {
  private int code; // violation, The field 'code' must be declared final

  public MyException() {
    code = 2;
  }
}

class MyThrowable extends Throwable {
  final int code; // OK
  String message; // violation, The field 'message' must be declared final

  public MyThrowable(int code, String message) {
    this.code = code;
    this.message = message;
  }
}

class BadException extends java.lang.Exception {
  int code; // violation, The field 'code' must be declared final

  public BadException(int code) {
    this.code = code;
  }
}
        

To configure the check so that it checks for class name that ends with 'Exception':

<module name="Checker">
  <module name="TreeWalker">
    <module name="MutableException">
      <property name="format" value="^.*Exception$"/>
    </module>
  </module>
</module>
        

Example:

class FirstClass extends Exception {
  private int code; // OK, class name doesn't match with given pattern

  public FirstClass() {
    code = 1;
  }
}

class MyException extends Exception {
  private int code; // violation, The field 'code' must be declared final

  public MyException() {
    code = 2;
  }
}

class MyThrowable extends Throwable {
  final int code; // OK, class name doesn't match with given pattern
  String message; // OK, class name doesn't match with given pattern

  public MyThrowable(int code, String message) {
    this.code = code;
    this.message = message;
  }
}

class BadException extends java.lang.Exception {
  int code; // violation, The field 'code' must be declared final

  public BadException(int code) {
    this.code = code;
  }
}
        

To configure the check so that it checks for type name that is used in 'extends' and ends with 'Throwable':

<module name="Checker">
  <module name="TreeWalker">
    <module name="MutableException">
      <property name="extendedClassNameFormat" value="^.*Throwable$"/>
    </module>
  </module>
</module>
        

Example:

class FirstClass extends Exception {
  private int code; // OK, extended class name doesn't match with given pattern

  public FirstClass() {
    code = 1;
  }
}

class MyException extends Exception {
  private int code; // OK, extended class name doesn't match with given pattern

  public MyException() {
    code = 2;
  }
}

class MyThrowable extends Throwable {
  final int code; // OK
  String message; // violation, The field 'message' must be declared final

  public MyThrowable(int code, String message) {
    this.code = code;
    this.message = message;
  }
}

class BadException extends java.lang.Exception {
  int code; // OK, extended class name doesn't match with given pattern

  public BadException(int code) {
    this.code = code;
  }
}
        

Example of Usage

Violation Messages

All messages can be customized if the default message doesn't suit you. Please see the documentation to learn how to.

Package

com.puppycrawl.tools.checkstyle.checks.design

Parent Module

TreeWalker