【问题标题】:Java Utility Singleton With Matching Static Interface具有匹配静态接口的 Java 实用程序单例
【发布时间】:2016-07-11 10:14:37
【问题描述】:

我想制作一组实现接口的实用程序类。为了做到这一点,我将使用单例模式。但是,如果能够通过静态方法调用来使用这些实用程序类,那就太好了。例如:

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;
    }
}

上面提供了一个单例,它使我能够使用接口调用实用程序方法,如下所示:

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

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

但是,我也希望能够以更简洁的方式使用StringValidator

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

Java 中有没有一种方法可以在不重命名方法的情况下使上述所有三种语法都工作?我唯一的想法是在静态定义中添加一个 varargs 参数,如下所示:

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;
    }
}

但是,失败并显示消息“无法从 StringValidator 类型对非静态方法 isValid(String) 进行静态引用”。同样,有没有办法让编译器允许我的所有三种用例语法?谢谢。

【问题讨论】:

  • 我没想到会这样。一般来说,处理这个问题的方法是从类中静态导入实例......
  • StringValidator.instance.isValid(""); 有什么问题?

标签: java java-8 singleton static-methods


【解决方案1】:

如果接口是函数式接口,您可以删除单例

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

当您需要Validator&lt;String&gt; 的实例时,请使用静态方法的方法句柄:

IValidator<String> validator1 = StringValidator::isValid; 

【讨论】:

    【解决方案2】:

    我想出了一个办法。将代码更改为以下内容:

    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;
        }
    }
    

    然后所有三个用例都会编译。 Java 将为用例 #2 生成警告,但这并不困扰我,因为我认为实现类的唯一合理使用是用例 #1 和 #3。

    【讨论】:

    • 这看起来不是一个好方法:引入ignored 变量是一种代码气味。并且忽略编译器警告绝不是一个好主意。
    • 我发现整个 Java 语言都是一种代码味道。尤其是类型擦除,会产生最难闻的气味。
    • @Tunaki 我最终只是放弃了用例 #3(例如,只是接受我必须在类和方法名称之间输入“.instance”),即使我的解决方案确实回答了原始问题.我同意这不是一个好的解决方案,并建议任何未来的访问者避免使用这种技术。
    猜你喜欢
    • 2012-06-14
    • 1970-01-01
    • 2018-07-29
    • 2018-02-18
    • 2023-03-08
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多