Are there type-safe and more concise alternatives to generics in Java?

I find generics to be good for encouraging generalization and improving type safety by removing casting. Sometimes it seems to me that the resulting code is much more for added value. Are there special cases where redundant generic code is eliminated and type safety is not regressed?

For example, I have a small invariant utility that checks, among other things, if a composite object (such as a collection of strings or a character string) is empty. When the invariant is not saved, the utility throws a predefined exception. It seems tempting to use generic for the class object type to avoid casting.

public interface Invariant<T> {
    void enforce(@SuppressWarnings("unchecked") T... arg) throws RuntimeException;
}

public class StringNotEmpty implements Invariant<String> {
    @Override
    public void enforce(String... arg) throws RuntimeException {
        for (int i = 0; i < arg.length; i++) {
            if (arg[i].trim().isEmpty()) {
            throw new IllegalArgumentException();
        }
    }
}

public class CollectionNotEmpty<T> implements Invariant<T extends Collection> {
    @Override
    public void enforce(@SuppressWarnings("unchecked") T... arg) throws RuntimeException {
        for (int i = 0; i < arg.length; i++) {
            if (arg[i].isEmpty()) {
            throw new IllegalArgumentException();
        }
    }
}

      

And here's how the invariant utility is used:

public void aMethod(String aString, String bString, List<Integer> aList) {
    Invariant<String> inv1 = new StringNotEmpty();
    Invariant<? extends List<Integer> inv2 = new CollectionNotEmpty<List<Integer>>();

    // Throw runtime exception when invariant1 is not kept
    inv1.enforce(aString, bString);

    // Do some business...

    // Throw runtime exception when invariant2 is not kept
    inv2.enforce(aList);
}

      

The end result is mediocre: Invariants are gulps to use, and type safety is compromised: see the alert-alert annotation which simply masks a risky attempt to use a template for varargs.

Could an "invariant" API be more concise but retain its type safety?

+3


source to share





All Articles