Jeff G
Jeff G

Reputation: 4677

Java Utility Singleton With Matching Static Interface

I would like to make a set of utility classes that implement an interface. In order to do this, I will be using the singleton pattern. However, it would also be nice to be able to use those utility classes via static method calls. For example:

public interface IValidator<T> {
    boolean isValid(T value);
}

public class StringValidator implements IValidator<String> {
    public static final StringValidator instance = new StringValidator();

    @Override
    public boolean isValid(final String value) {
        return true;
    }
}

The above provides a singleton which enables me to call the utility methods using an interface, as follows:

// Use case #1
IValidator<String> validator1 = StringValidator.instance;
validator1.isValid("");

// Use case #2
StringValidator.instance.isValid("");

However, I would also like to be able to use StringValidator in the following, more succinct way:

// Use case #3: How can I also allow this syntax?
StringValidator.isValid("");

Is there a way in Java to make all three of the above syntaxes work without renaming the method? The only idea I had was to add a varargs parameter to the static definition, as follows:

public class StringValidator implements IValidator<String> {
    public static final StringValidator instance = new StringValidator();

    @Override
    public boolean isValid(final String value) {
        return StringValidator.isValid(value);
    }

    public static boolean isValid(final String value, final Object... ignored) {
        return true;
    }
}

However, that fails with the message "Cannot make a static reference to the non-static method isValid(String) from the type StringValidator". Again, is there some way to make the compiler allow all three of my use-case syntaxes? Thanks.

Upvotes: 1

Views: 120

Answers (2)

Jeff G
Jeff G

Reputation: 4677

I figured out a way. Change the code to the following:

public interface IValidator<T> {
    boolean isValid(T value, Object... ignored);
}

public class StringValidator implements IValidator<String> {
    public static final StringValidator instance = new StringValidator();

    @Override
    public boolean isValid(final String value, final Object... ignored) {
        return isValid(value);
    }

    public static boolean isValid(final String value) {
        return true;
    }
}

Then all three of the use cases compile. Java will generate a warning for use case #2, but that doesn't bother me as I think the only sane use of the implementing class are cases #1 and #3.

Upvotes: -1

wero
wero

Reputation: 32980

If the interface is a functional interface you could drop the singleton

public class StringValidator {
    public static boolean isValid(final String value) {
        return ...;
    }
}

and whenever you need a instance of Validator<String> use a method handle to the static method:

IValidator<String> validator1 = StringValidator::isValid; 

Upvotes: 3

Related Questions