接口方法可以有主体吗?


72

我知道一个接口就像一个100%纯的抽象类。因此,它不能包含方法实现。但是,我看到了一个奇怪的代码。有人可以解释吗?

代码段:

 interface Whoa {
        public static void doStuff() {
            System.out.println("This is not default implementation");
        }
 }

编辑:

我的IDE是Intellij Idea 13.1。项目SDK是Java 7 <1.7.0_25>。IDE未显示任何编译器错误。但是,当我在命令行编译代码时,我收到以下消息。

Whoa.java:2: error: modifier static not allowed here
    public static void doStuff() {
                       ^

它给出了错误。
JDK

在Java中那是不可能的
Salah 2014年

37
Java8允许接口使用默认方法主体。
sp00m 2014年

2
Java 8,是的。在此之前,没有。
伊恩·麦克劳德

3
仅在Java 8中引入了默认方法。在此之前
Omoro

Answers:


100

Java 8中,除了默认方法外,您还可以在接口中定义静态方法。

  • 静态方法是与其定义的类相关联的方法,而不是与任何对象相关联的方法。该类的每个实例都共享其静态方法。

  • 这使您更轻松地在库中组织帮助程序方法。您可以将特定于接口的静态方法保留在同一接口中,而不是在单独的类中。

  • 以下示例定义了一个静态方法,该方法检索ZoneId与时区标识符相对应的对象;如果没有ZoneId与给定标识符对应的对象,它将使用系统默认时区。(因此,您可以简化方法getZonedDateTime

这是代码:

public interface TimeClient {
   // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +"; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

   default public ZonedDateTime getZonedDateTime(String zoneString) {
      return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
   }    
}

也可以看看


4
也是方法的默认实现。
伊恩·麦克劳德

1
我没有使用Java8。它是javac 1.7.0_25。

2
您的IDE是否使用代码合规性8?这应该不是7及以下编译。这是一篇好文章
Giovanni Botta 2014年

1
@Phoenix我也使用1.7.0_25版本,但此版本不允许使用
Shekhar Khairnar 2014年

1
这似乎真的模糊了接口和抽象类之间的界限。
asteri 2014年

20

这仅在Java 8中才有可能。在Java 7语言规范§9.4中,它明确声明:

如果在接口中声明的方法声明为静态的,则是编译时错误,因为静态方法不能是抽象的。

因此,在Java 7中,接口中的静态方法存在。

如果转到Java 8 Language Specification§9.4.3,您会看到它说:

静态方法也有一个块体,它提供了该方法的实现。

因此,它明确指出在Java 8中它们可以存在。

我什至尝试在Java 1.7.0_45中运行您的确切代码,但是它给了我错误“此处不允许使用修饰符静态”。


这是直接来自Java 8教程“默认方法(学习Java语言>接口和继承)”的引文:

静态方法

除了默认方法外,您还可以在接口中定义静态方法。(静态方法是与其定义的类相关联的方法,而不是与任何对象相关联的方法。该类的每个实例都共享其静态方法。)这使您更容易在库中组织帮助程序方法;您可以将特定于接口的静态方法保留在同一接口中,而不是在单独的类中。下面的示例定义一个静态方法,该方法检索ZoneId与时区标识符相对应的对象;如果没有ZoneId与给定标识符对应的对象,它将使用系统默认时区 。(因此,您可以简化方法getZonedDateTime):

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

与类中的静态方法一样,您可以指定接口中的方法定义是静态方法,并static在方法签名的开头带有关键字。接口中的所有方法声明(包括静态方法)都是隐式的public,因此您可以省略public修饰符。


13

对于Java版本7或更低版本,在功能上类似,您可以使用在接口主体中声明的嵌套类来实现。并且此嵌套类实现了外部接口。

例:

interface I1{
    public void doSmth();

    class DefaultRealizationClass implements  I1{

        @Override
        public void doSmth() {
           System.out.println("default realization");
        }
    }
}

我们如何在代码中使用它?

class MyClass implements I1{

    @Override
    public void doSmth() {
         new I1.DefaultRealizationClass().doSmth();
    }   
}

因此,默认实现封装在接口内。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.