【问题标题】:Default method return value in Java interfacesJava 接口中的默认方法返回值
【发布时间】:2011-04-18 18:43:57
【问题描述】:

在使用注释时,我偶然发现了以下代码(它是 Hibernate @NotNull 注释):

@Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {})
public @interface NotNull {

    @Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {

        public NotNull[] value();
    }

    public String message() default "{javax.validation.constraints.NotNull.message}";

    public Class<?>[] groups() default {};

    public Class<? extends Payload>[] payload() default {};
}

我想知道方法定义中的default 关键字/构造,这是我以前从未见过的。据我了解,它允许您为此方法(或注释属性)定义一个默认值。

现在我试图将此构造应用于普通接口,但失败了。这将无法编译:

public interface DefaultTest {
    public String test() default "value";
}

但这会起作用:

public @interface DefaultTest {
    public String test() default "value";
}

所以我的问题是:default 关键字注解是特定的吗?如果是,那么在普通接口定义中使用这种结构有何不妥?

【问题讨论】:

    标签: java interface annotations language-features


    【解决方案1】:

    Java 8 及更高版本

    是的,现在可以在接口上使用 default 关键字。更多详情请见Oracle's docs

    实施与您的想法略有不同。应该是:

    public interface DefaultTest {
        default public String test() {
            return "value";
        }
    }
    

    Java 7 及更早版本

    默认关键字只能用于注解。

    如果你想要一个接口的默认返回值,你需要使用一个抽象类来代替。

    public abstract class DefaultTest {
    
      public String test() {
        return "value";
      }
    
    }
    

    【讨论】:

    • 多接口继承非常有意义。感谢您指出这一点。
    • 原来你真的很有先见之明。 Java 8 现在让您随心所欲!我已经更新了我的答案。
    【解决方案2】:

    此处的“默认”关键字不是特定于注释的。 为接口方法提供默认实现是java的特性。

    需要这种行为: 假设最初定义了一个接口 Vehicle 以支持所有车辆功能方法 -

    interface Vehicle {
      void speed();
    
      ... 
      //other interface methods
    } 
    

    现在实现这个 Vehicle 接口的类已经实现了这些抽象方法。

    现在未来的车辆具有飞行能力。所以你还需要添加飞行功能。 现在如果你在 Vehicle 接口中添加 flySpeed() 方法,你需要修改所有现有的类以避免破坏代码。 不可行的解决方案。

    为了向后兼容,java 提供了 Default 方法的特性。这样您就可以添加新方法来与默认实现接口,因此现有类不需要实现该方法。并且新的 Vehicle 类可以根据需要覆盖这些方法。

    interface Vehicle {
      void speed();
    
      ...
      //other interface methods
    
      //default method
      default void flyingSpeed() {
        System.out.println("Default flying speed");
      }
    }
    

    使用这种方式,以前现有的 Vehicle 类将不需要实现此方法。

    更多信息see在这里。

    【讨论】:

      【解决方案3】:

      您提到的默认关键字专门适用于注释;用于指定注释属性的默认值(请参阅:https://docs.oracle.com/javase/specs/jls/se12/html/jls-9.html#jls-9.6.2)。请注意,注释属性只能是基元、字符串、类、注释、枚举或它们的一维数组。接口属性只能声明(默认情况下)public static final。我认为它的值必须在声明期间使用 Java 赋值语法进行赋值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        • 1970-01-01
        • 2018-06-13
        相关资源
        最近更新 更多