checkers.nullness.NullnessUtils Maven / Gradle / Ivy
Show all versions of checker-quals-jdk5 Show documentation
package checkers.nullness;
import checkers.nullness.quals.*;
/**
* Utilities class for the Nullness Checker.
*
*
* To avoid the need to write the NullnessUtils class name, do:
*
import static checkers.nullness.NullnessUtils.castNonNull;
* or
* import static checkers.nullness.NullnessUtils.*;
*
*
* Runtime Dependency
*
*
* Please note that using this class introduces a Runtime dependency.
* This means that if you need to distribute (or link to) the Checker
* Framework, along with your binaries.
*
* To eliminate this dependency, you can simply copy this class into your
* own project.
*/
// Nullness utilities are trusted regarding nullness.
// Casts look redundant if Nullness Checker is not run.
@SuppressWarnings({"nullness",
"cast"})
public final class NullnessUtils {
private NullnessUtils()
{ throw new AssertionError("shouldn't be instantiated"); }
/**
* A method that suppresses warnings from the Nullness Checker.
*
*
* The method takes a possibly-null reference, unsafely casts it to
* have the @NonNull type qualifier, and returns it. The Nullness
* Checker considers both the return value, and also the argument, to
* be non-null after the method call. Therefore, the
* castNonNull method can be used either as a cast expression or
* as a statement. The Nullness Checker issues no warnings in any of
* the following code:
*
*
* // one way to use as a cast:
* @NonNull String s = castNonNull(possiblyNull1);
*
* // another way to use as a cast:
* castNonNull(possiblyNull2).toString();
*
* // one way to use as a statement:
* castNonNull(possiblyNull3);
* possiblyNull3.toString();`
*
*
* The castNonNull method is intended to be used in situations
* where the programmer definitively knows that a given reference is
* not null, but the type system is unable to make this deduction. It
* is not intended for defensive programming, in which a programmer
* cannot prove that the value is not null but wishes to have an
* earlier indication if it is. See the Checker Framework manual for
* further discussion.
*
*
* The method throws {@link AssertionError} if Java assertions are
* enabled and the argument is {@code null}. If the exception is ever
* thrown, then that indicates that the programmer misused the method
* by using it in a circumstance where its argument can be null.
*
*
* @param ref a reference of @Nullable type
* @return the argument, casted to have the type qualifier @NonNull
*/
@AssertParametersNonNull
public static
/*@NonNull*/ T castNonNull(T ref) {
assert ref != null : "Misuse of castNonNull: called with a null argument";
return (/*@NonNull*/ T) ref;
}
/**
* Like castNonNull, but whereas that method only checks and casts the
* reference itself, this traverses all levels of the argument array.
* The array is recursively checked to ensure that all elements at
* every array level are non-null.
* @see #castNonNull(Object)
*/
@AssertParametersNonNull
public static
/*@NonNull*/ T /*@NonNull*/ []
castNonNullDeep(T /*@Nullable*/ [] arr) {
return (/*@NonNull*/ T[]) castNonNullArray(arr);
}
/**
* Like castNonNull, but whereas that method only checks and casts the
* reference itself, this traverses all levels of the argument array.
* The array is recursively checked to ensure that all elements at
* every array level are non-null.
* @see #castNonNull(Object)
*/
@AssertParametersNonNull
public static
/*@NonNull*/ T /*@NonNull*/ [][]
castNonNullDeep(T /*@Nullable*/ [] /*@Nullable*/ [] arr) {
return (/*@NonNull*/ T[][]) castNonNullArray(arr);
}
/**
* Like castNonNull, but whereas that method only checks and casts the
* reference itself, this traverses all levels of the argument array.
* The array is recursively checked to ensure that all elements at
* every array level are non-null.
* @see #castNonNull(Object)
*/
@AssertParametersNonNull
public static
/*@NonNull*/ T /*@NonNull*/ [][][]
castNonNullDeep(T /*@Nullable*/ [] /*@Nullable*/ [] /*@Nullable*/ [] arr) {
return (/*@NonNull*/ T[][][]) castNonNullArray(arr);
}
/**
* Like castNonNull, but whereas that method only checks and casts the
* reference itself, this traverses all levels of the argument array.
* The array is recursively checked to ensure that all elements at
* every array level are non-null.
* @see #castNonNull(Object)
*/
@AssertParametersNonNull
public static
/*@NonNull*/ T /*@NonNull*/ [][][][]
castNonNullDeep(T /*@Nullable*/ [] /*@Nullable*/ [] /*@Nullable*/ [] /*@Nullable*/ [] arr) {
return (/*@NonNull*/ T[][][][]) castNonNullArray(arr);
}
/**
* Like castNonNull, but whereas that method only checks and casts the
* reference itself, this traverses all levels of the argument array.
* The array is recursively checked to ensure that all elements at
* every array level are non-null.
* @see #castNonNull(Object)
*/
@AssertParametersNonNull
public static
/*@NonNull*/ T /*@NonNull*/ [][][][][]
castNonNullDeep(T /*@Nullable*/ [] /*@Nullable*/ [] /*@Nullable*/ [] /*@Nullable*/ [] /*@Nullable*/ [] arr) {
return (/*@NonNull*/ T[][][][][]) castNonNullArray(arr);
}
@AssertParametersNonNull
private static
/*@NonNull*/ T /*@NonNull*/ [] castNonNullArray(T /*@Nullable*/ [] arr) {
assert arr != null : "Misuse of castNonNullArray: called with a null array argument";
for (int i = 0; i < arr.length; ++i) {
assert arr[i] != null : "Misuse of castNonNull: called with a null array element";
checkIfArray(arr[i]);
}
return (/*@NonNull*/ T[]) arr;
}
private static void checkIfArray(/*@NonNull*/ Object ref) {
assert ref != null : "Misuse of checkIfArray: called with a null argument";
Class> comp = ref.getClass().getComponentType();
if (comp != null) {
// comp is non-null for arrays, otherwise null.
if (comp.isPrimitive()) {
// Nothing to do for arrays of primitive type: primitives are
// never null.
} else {
castNonNullArray((Object[])ref);
}
}
}
}