【问题标题】:interface constants not initialized at runtime in implementing classes在实现类时未在运行时初始化的接口常量
【发布时间】:2013-08-05 09:51:21
【问题描述】:

我有一个接口,其中使用
static final Repsonse = new Response(...) 定义常量。
这些常量被接口中定义的方法使用(或者更确切地说:应该使用)作为返回值。

现在我让 Spring 实例化实现此接口的类,但在运行应用程序时这些常量并未启动(它们是 null)。

这是接口的普遍问题还是 Spring 特有的问题?
也许有更好的方法来实现预期的功能?

对于那些需要 mroe 信息的人:
该接口定义了一个“检查器”,它定义了几种不同的方法来检查对象的状态。这些方法中的每一个都应返回一个标准化的Response 对象,该对象是一个简单的容器,其中包含有关该方法正在检查的对象状态的标准化信息。
我认为将所有可能的响应代码定义为常量是一个好主意,这样使用该接口的实现者就可以将它们放在手边。也许我错了?

这里有一些代码sn-ps:

public interface Validator
{
    static final Response VALID = new Response(some params);

    /** is expected to return the Response VALID */
    Response validate(String param1, String param2);
}

public class ValidatorImpl implements Validator
{
    public Response validate(String param1, String param2)
    {
        //VALID is null; also tried explicit static access here, no luck either
        return VALID;
    }
}

【问题讨论】:

  • 它应该可以工作。能否请您发布一些原始的 sn-ps,也许有人在其中发现了一个错误。
  • 我刚刚尝试了一个独立的程序,它运行良好。事实上,spring 推荐基于接口的方法。它应该工作。静态变量是在类加载时初始化的。
  • 感谢您试用!您鼓励我使用显式构造方法编写一个小测试,而不是使用 Spring 进行注入,并且确实以这种方式工作。所以我猜其他地方有错误,我会看看我的 Spring 集成。
  • @m00hk00h:您在评论中写道“......使用显式构造函数方法而不是使用 Spring 注入,并且确实以这种方式工作。” ---您的意思是,您发布的问题和代码不是使用的一种用途;而是使用@Inject@Autowired 作为接口中的静态变量?
  • @Ralph 不,我的意思是我用 new() 调用了 Validator 类,而不是使用 Spring 将类注入到变量中。不过,我刚刚发现了错误:我在用于处理该类的单例实例的“getInstance()”方法中犯了一个错误,它现在按预期工作。如果没有您的帮助,就不会查看该代码。非常感谢!

标签: java spring interface constants


【解决方案1】:

可以在接口中初始化常量,但尽管在 Java 库本身中使用它,但通常被认为是一种反模式。 http://en.wikipedia.org/wiki/Constant_interface

您可能需要考虑以下事项。如果 Response 对象很简单,并且您只想能够区分不同级别的有效性,请在您的界面之外为此创建一个枚举:

public enum Validity
{
    VALID, INVALID
}

public interface Validator
{
    Validity validate(String param1, String param2);
}

public class ValidatorImpl implements Validator
{
    public Validity validate(String param1, String param2)
    {
        return Validity.VALID;
    }
}

如果您想为响应添加更多状态(例如描述),我建议您在配置文件中初始化它们,将它们添加到映射并将映射注入到您的实现类中,如下所示,值类型为您的之前的“响应”类型。下面的map是一个EnumMap,它使用Validity枚举作为key。

<util:map id="validityMap">
  <entry key="#{T(com.acme.Validity).VALID}" value-ref="valid" />
  <entry key="#{T(com.acme.Validity).INVALID}" value-ref="invalid" />
</util:map>

<bean id="valid" class="com.acme.Response">
    <property name="comment" value="This is valid" />
</bean>

<bean id="invalid" class="com.acme.Response">
    <property name="comment" value="This is invalid" />
</bean>

public enum Validity
{
    VALID, INVALID
}

public interface Validator
{
    Response validate(String param1, String param2);
}

public class ValidatorImpl implements Validator
{
    // Inject from config (remember to add getter and setter)
    private validityMap;

    public Response validate(String param1, String param2)
    {
        return getValidityMap().get(Validity.VALID);
    }
}

【讨论】:

  • 这是一个有用的答案,但它回答了“如何防止恒定接口”的问题,这从来不是我的问题。常量只是接口的一部分,有很多不同的方法用广泛的 javadoc 为实现者定义。而且由于 API 不是公开的,我不认为提供额外信息的难易程度是个问题。不过,我完全意识到了这个问题 - 事实上,我在 Response 对象本身中广泛使用了枚举。
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 2017-03-13
  • 2012-10-10
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
相关资源
最近更新 更多