ChatGPT解决这个技术问题 Extra ChatGPT

为什么我不能在 Java 接口中定义静态方法?

编辑:从 Java 8 开始,接口中现在允许使用静态方法。

这是示例:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

这当然行不通。但为什么不呢?

可能的问题之一是,当你打电话时会发生什么:

IXMLizable.newInstanceFromXML(e);

在这种情况下,我认为它应该只调用一个空方法(即{})。所有子类都将被迫实现静态方法,因此在调用静态方法时它们都可以。那么为什么这不可能呢?

编辑:我想我正在寻找比“因为 Java 就是这样”更深的答案。

静态方法不能被覆盖是否有特定的技术原因?也就是说,为什么 Java 的设计者决定让实例方法可覆盖而不是静态方法?

编辑:我的设计问题是我正在尝试使用接口来强制执行编码约定。

也就是说,接口的目标是双重的:

我希望 IXMLizable 接口允许我将实现它的类转换为 XML 元素(使用多态,工作正常)。如果有人想创建一个实现 IXMLizable 接口的类的新实例,他们总是知道会有一个 newInstanceFromXML(Element e) 静态构造函数。

除了在界面中添加评论之外,还有其他方法可以确保这一点吗?

顺便说一句,您不需要在接口中使用 public 来混淆方法(和字段)定义。
嗯,似乎是 stackoverflow.com/questions/21817/… 的副本。以前没见过。
您能否提供一些代码,您希望如何使用静态接口方法?
这在 Java 8 中是可能的:docs.oracle.com/javase/tutorial/java/IandI/…
@dakshang 是的,但它不符合 OP 的要求。

e
erickson

Java 8 允许静态接口方法

在 Java 8 中,接口可以有静态方法。它们也可以有具体的实例方法,但不能有实例字段。

这里真的有两个问题:

为什么在过去糟糕的日子里,接口不能包含静态方法?为什么不能覆盖静态方法?

接口中的静态方法

没有强有力的技术原因说明接口在以前的版本中不能有静态方法。这是重复问题的 summed up nicely by the poster。静态接口方法最初被认为是 a small language change,,然后在 Java 7 中有 an official proposal 来添加它们,但后来是 dropped due to unforeseen complications.

最后,Java 8 引入了静态接口方法,以及具有默认实现的可覆盖实例方法。他们仍然不能有实例字段。这些功能是 lambda 表达式支持的一部分,您可以在 Part H of JSR 335. 中阅读有关它们的更多信息

覆盖静态方法

第二个问题的答案有点复杂。

静态方法在编译时是可解析的。动态分派对实例方法有意义,其中编译器无法确定对象的具体类型,因此无法解析要调用的方法。但是调用静态方法需要一个类,并且由于该类是静态已知的——在编译时——动态调度是不必要的。

了解实例方法如何工作的一些背景知识对于理解这里发生的事情是必要的。我确信实际的实现是完全不同的,但让我解释一下我的方法分派的概念,它可以准确地模拟观察到的行为。

假设每个类都有一个哈希表,该哈希表将方法签名(名称和参数类型)映射到实际的代码块以实现该方法。当虚拟机尝试调用实例上的方法时,它会查询对象的类并在类的表中查找请求的签名。如果找到方法体,则调用它。否则,获取该类的父类,并在那里重复查找。这将继续进行,直到找到该方法,或者没有更多的父类 - 这会导致 NoSuchMethodError

如果超类和子类在其表中都有相同方法签名的条目,则首先遇到子类的版本,并且永远不会使用超类的版本——这是“覆盖”。

现在,假设我们跳过对象实例并从子类开始。解决方案可以如上进行,为您提供一种“可覆盖”的静态方法。然而,解析都可以在编译时发生,因为编译器是从一个已知的类开始的,而不是等到运行时为它的类查询一个未指定类型的对象。 “覆盖”静态方法没有意义,因为总是可以指定包含所需版本的类。

构造函数“接口”

这里有更多材料来解决最近对该问题的编辑。

听起来您想为 IXMLizable 的每个实现有效地强制使用类似构造函数的方法。暂时忘记尝试使用接口强制执行此操作,并假装您有一些满足此要求的类。你会如何使用它?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

由于在“构造”新对象时必须显式命名具体类型 Foo,编译器可以验证它确实具有必要的工厂方法。如果没有,那又如何?如果我可以实现缺少“构造函数”的 IXMLizable,并创建一个实例并将其传递给您的代码,那么它一个具有所有必要接口的 IXMLizable

构造是实现的一部分,而不是接口。任何与接口一起成功工作的代码都不关心构造函数。任何关心构造函数的代码无论如何都需要知道具体类型,接口可以忽略。


#1 的原因可能是多重继承吗?由于我们可以从多个接口继承,如果两个接口包含相同的静态方法签名,然后一个类实现了它们并调用了该方法,那么事情可能会变得复杂,Java 语言创建者希望通过禁止多个类继承来避免第一名。显然可以为接口提出相同的论点,根本不允许在其中定义任何方法。
@shrini1000 - 不,静态方法在编译时解析。可以像处理常量一样处理歧义:with a compiler error. 但是,Project Coin 下的提案被拒绝,理由是一些不可预见的困难。不知道他们是什么,但我不认为这是沿着这些路线。
@tgm1024 是的,“构造函数'接口'”部分解释了为什么尝试通过编译时已知的类型调用多态行为没有意义。您将如何在给定的类上调用 RESET()?你会写 SomeClass.RESET()。所以你不需要一个接口来描述那个 API;它的静态。当您在编译时不知道具体类型时,将使用接口。静态方法绝不会出现这种情况。
“构造是实现的一部分,而不是接口。任何与接口一起成功工作的代码都不关心构造函数。” ——这显然不是真的。在其他语言(例如 Swift)中,我可以在不知道 T 的情况下静态创建 T 的新实例,因为我在接口中承诺某个构造函数(或静态方法)将在运行时存在。无法在 Java 中指定生成这一事实并不意味着这不是一件有意义的事情。
C
Community

这已经被问及回答了,here

复制我的答案:

在接口中声明静态方法是没有意义的。它们不能通过正常调用 MyInterface.staticMethod() 来执行。如果您通过指定实现类 MyImplementor.staticMethod() 来调用它们,那么您必须知道实际的类,因此接口是否包含它是无关紧要的。

更重要的是,静态方法永远不会被覆盖,如果你尝试这样做:

MyInterface var = new MyImplementingClass();
var.staticMethod();

static 的规则说必须执行在声明的 var 类型中定义的方法。因为这是一个接口,所以这是不可能的。

无法执行“result=MyInterface.staticMethod()”的原因是它必须执行 MyInterface 中定义的方法版本。但是在 MyInterface 中不能定义一个版本,因为它是一个接口。它没有定义的代码。

虽然您可以说这相当于“因为 Java 这样做”,但实际上该决定是其他设计决策的逻辑结果,也是有充分理由做出的。


如果您使用 作为泛型类型参数,最好通过接口保证 T 可以 .doSomething()。
虽然我理解这些论点,但我同意@Chris_Betti(即使对于非泛型类型):代码结构确保某些类实现特定的静态 API 会很好。也许可以使用不同的概念......
这似乎不正确:“在接口中声明静态方法从来没有意义。”如果我有一个类的集合,无需实例化,就可以为我提供一些信息,但我需要一个通用接口来放入这个静态类级信息(即具有可覆盖静态方法的接口),那么这是一个有效的用途.想想反射++,您可以在其中捕获有关类属性的元信息,而无需使用属性、反射等。
在接口中声明静态方法是没有意义的。有时接口中的静态方法是有意义的,因为它们强制执行更多功能的方法。接口中的静态方法不能改变接口的静态状态,因为接口中根本没有状态。
“在接口中声明静态方法是没有意义的。”这不是真的:想象你的系统有一个默认的类解析器。如果它检测到您实现了 ContainerInjectionInterce::create(Container $container) 方法,那么它将使用此函数创建对象。
V
Victor Stafusa

随着 Java 8 的出现,现在可以在接口中编写 defaultstatic 方法。 docs.oracle/staticMethod

例如:

public interface Arithmetic {

    public int add(int a, int b);

    public static int multiply(int a, int b) {
        return a * b;
    }
}
public class ArithmaticImplementation implements Arithmetic {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = Arithmetic.multiply(2, 3);
        System.out.println(result);
    }
}

结果:6

提示:调用静态接口方法不需要由任何类实现。当然,这是因为超类中静态方法的相同规则适用于接口上的静态方法。


这是这个问题的一个完美例子。
P
Peter Lawrey

通常这是使用工厂模式完成的

public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}

+1 工厂模式听起来像是解决问题的方法。 (虽然不是问题)
有人能告诉我把 放在这里是什么意思吗?我是java新手。它有什么作用?
@NuwanHarshakumaraPiyarathna T 必须是扩展 IXMLizable 的类。查看 Java 泛型以更好地理解这意味着什么
M
Michael Myers

因为静态方法不能在子类中被覆盖,因此它们不能是抽象的。接口中的所有方法实际上都是抽象的。


您总是可以强制每种类型实现任何静态接口方法。类型类,有人吗?
走出自己,回答问题:为什么不能覆盖静态方法?如果可以覆盖静态方法,它会是什么样子?你能用他们做什么?这个答案基本上是“你不能因为你不能”。
a
akhil_mittal

为什么我不能在 Java 接口中定义静态方法?

实际上你可以在 Java 8 中。

根据 Java doc

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

在 Java 8 中,接口可以有默认方法和静态方法。这使我们更容易在我们的库中组织辅助方法。我们可以将特定于接口的静态方法保留在同一个接口中,而不是在单独的类中。

默认方法示例:

list.sort(ordering);

代替

Collections.sort(list, ordering);

静态方法示例(来自文档本身):

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

很高兴知道这些 Util 类可以用接口本身中的静态方法替换。
c
cliff.meyers

接口与多态性有关,多态性本质上与对象实例相关,而不是类。因此静态在接口的上下文中没有意义。


逻辑清晰,简洁。说得好。
t
tallgirl

首先,所有语言决策都是由语言创建者做出的决定。在软件工程或语言定义或编译器/解释器编写的世界中,没有任何东西说静态方法不能成为接口的一部分。我已经创建了几种语言并为它们编写了编译器——这一切都只是坐下来定义有意义的语义。我认为接口中静态方法的语义非常清楚——即使编译器必须将方法的解析推迟到运行时。

其次,我们完全使用静态方法意味着拥有包含静态方法的接口模式是有正当理由的——我不能代表你们任何人,但我经常使用静态方法。

最可能的正确答案是,在定义语言时,接口中的静态方法并不需要。 Java 多年来发展了很多,这显然引起了人们的兴趣。对 Java 7 的研究表明它已上升到可能导致语言更改的程度。一方面,当我不再需要实例化一个对象时,我会很高兴,这样我就可以调用我的非静态 getter 方法来访问子类实例中的静态变量......


D
Darron

“是否有特定原因不能覆盖静态方法”。

让我通过填写定义为您重新提出这个问题。

“是否有特殊原因导致在编译时解析的方法无法在运行时解析。”

或者,更完整地说,如果我想调用一个没有实例但知道类的方法,如何根据我没有的实例来解决它。


A
Adrian Pronk

静态方法不像实例方法那样是虚拟的,所以我想 Java 设计者决定他们不希望它们出现在接口中。

但是您可以将包含静态方法的类放在接口中。你可以试试!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}

f
flavio

评论 EDIT: As of Java 8, static methods are now allowed in interfaces.

没错,接口中允许使用 Java 8 以来的静态方法,但您的示例仍然无法正常工作。你不能只定义一个静态方法:你必须实现它,否则你会得到一个编译错误。


M
Mr. Shiny and New 安宇

几个答案讨论了可覆盖静态方法概念的问题。但是,有时您会遇到一种看起来正是您想要使用的模式。

例如,我使用具有值对象的对象关系层,但也具有用于操作值对象的命令。由于各种原因,每个值对象类都必须定义一些静态方法,让框架找到命令实例。例如,要创建一个 Person 你会做:

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

并通过 ID 加载 Person 你会做

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

这相当方便,但也有问题;值得注意的是静态方法的存在不能在接口中强制执行。接口中的一个可覆盖的静态方法正是我们所需要的,只要它能够以某种方式工作。

EJB 通过 Home 接口解决了这个问题;每个对象都知道如何找到它的 Home 并且 Home 包含“静态”方法。这样,可以根据需要覆盖“静态”方法,并且您不会将普通(称为“远程”)接口与不适用于 bean 实例的方法混淆。只需让普通接口指定一个“getHome()”方法即可。返回 Home 对象的一个实例(我想它可能是一个单例),调用者可以执行影响所有 Person 对象的操作。


M
MichaelGG

好吧,没有泛型,静态接口就毫无用处,因为所有静态方法调用都是在编译时解决的。所以,它们没有真正的用处。

使用泛型,它们可以使用——有或没有默认实现。显然需要覆盖等等。但是,我的猜测是,这种用法不是很 OO(正如其他答案所指出的那样),因此不值得他们为有效实现所需付出的努力。


泛型与此有什么关系?接口上的静态方法仍然无法执行。
首先,这将是一个实施决策。但我猜他不想在接口上调用静态方法(他可以只使用一个类)。但相反,希望有一些类似于类型类或其他类型参数的东西。事实上,他的最新编辑更清楚地表明了这一点。
A
Aniket Thakur
Why can't I define a static method in a Java interface?

接口中的所有方法都是显式抽象的,因此您不能将它们定义为静态,因为静态方法不能是抽象的。


B
Bill the Lizard

永远不能静态地取消引用接口,例如 ISomething.member。接口总是通过引用接口子类实例的变量来取消引用。因此,如果没有子类的实例,接口引用永远无法知道它引用的是哪个子类。

因此,与接口中的静态方法最接近的方法是忽略“this”的非静态方法,即不访问实例的任何非静态成员。在低级抽象中,每个非静态方法(在任何 vtable 中查找之后)实际上只是一个具有类范围的函数,它将“this”作为隐式形式参数。请参阅 Scala's singleton object and interoperability with Java 作为该概念的证据。因此,每个静态方法都是一个具有类范围的函数,它不带“this”参数。因此,通常可以静态调用静态方法,但如前所述,接口没有实现(是抽象的)。

因此,要最接近接口中的静态方法,就是使用非静态方法,然后不要访问任何非静态实例成员。任何其他方式都不可能带来性能优势,因为无法静态链接(在编译时)ISomething.member()。我在接口中看到静态方法的唯一好处是它不会输入(即忽略)隐式“this”,因此不允许访问任何非静态实例成员。这将隐式声明不访问“this”的函数是不可变的,甚至就其包含的类而言甚至不是只读的。但是在接口 ISomething 中声明“静态”也会使试图使用 ISomething.member() 访问它的人感到困惑,这会导致编译器错误。我想如果编译器错误足够解释,它会比试图教育人们使用非静态方法来完成他们想要的(显然主要是工厂方法)更好,就像我们在这里所做的那样(并且已经重复了 3这个网站上的问答时间),所以这显然是一个对很多人来说并不直观的问题。我不得不考虑一段时间才能得到正确的理解。

在接口中获取可变静态字段的方法是在接口中使用非静态 getter 和 setter 方法来访问子类中的静态字段。旁注,显然不可变的静态可以用 static final 在 Java 接口中声明。


s
samoz

接口只是提供一个类将提供的东西的列表,而不是这些东西的实际实现,这就是你的静态项目。

如果您想要静态,请使用抽象类并继承它,否则,请删除静态。

希望有帮助!


好吧,理论上,您可以定义一个包含静态行为的接口,即“此接口的实现将具有带有此签名的静态方法 foo()”,并将实现留给特定的类。我遇到过这种行为有用的情况。
H
Handerson

您不能在接口中定义静态方法,因为静态方法属于类而不属于类的实例,并且接口不是类。 Read more here.

但是,如果你愿意,你可以这样做:

public class A {
  public static void methodX() {
  }
}

public class B extends A {
  public static void methodX() {
  }
}

在这种情况下,您拥有的是两个具有 2 个不同的静态方法的类,称为 methodX()。


M
Michael Myers

假设你能做到;考虑这个例子:

interface Iface {
  public static void thisIsTheMethod();
}

class A implements Iface {

  public static void thisIsTheMethod(){
    system.out.print("I'm class A");
  }

}

class B extends Class A {

  public static void thisIsTheMethod(){
    System.out.print("I'm class B");
  } 
}

SomeClass {

  void doStuff(Iface face) {
    IFace.thisIsTheMethod();
    // now what would/could/should happen here.
  }

}

它会打印“我是 A 级”。但是,如果您键入 A.thisIsTheMethod(),它将打印“我是 B 级”。
但是在接口上调用方法时,您(或编译器)如何知道应该调用哪个方法? (请记住,可以有更多的类直接实现 Iface
抱歉,我的意思是:但是,如果您键入 B.thisIsTheMethod(),它将打印“我是 B 级”。
我故意说 IFace.thisIsTHeMethod,因为这就是问题所在。如果没有未定义的行为,就不可能在接口上调用它(即使它在上面声明了)
C
Christophe Bouchon

可以实现的是静态接口(而不是接口中的静态方法)。所有实现给定静态接口的类都应该实现相应的静态方法。您可以使用从任何 Class clazz 获取静态接口 SI

SI si = clazz.getStatic(SI.class); // null if clazz doesn't implement SI
// alternatively if the class is known at compile time
SI si = Someclass.static.SI; // either compiler errror or not null

那么您可以调用 si.method(params)。这将很有用(例如对于工厂设计模式),因为您可以从编译时未知类中获取(或检查)SI 静态方法的实现!动态调度是必要的,您可以通过扩展类的静态方法(如果不是最终方法)(通过静态接口调用时)来覆盖它。显然,这些方法只能访问其类的静态变量。


R
Ryan

虽然我意识到 Java 8 解决了这个问题,但我想我会加入我目前正在处理的场景(锁定使用 Java 7),其中能够在接口中指定静态方法会很有帮助。

我有几个枚举定义,其中我定义了“id”和“displayName”字段以及出于各种原因评估值的辅助方法。实现一个接口可以让我确保 getter 方法就位,但不是静态辅助方法。作为枚举,确实没有一种干净的方法可以将辅助方法卸载到继承的抽象类或类似的东西中,因此必须在枚举本身中定义方法。也因为它是一个枚举,你永远不能真正将它作为实例对象传递并将其视为接口类型,但是能够通过接口要求存在静态帮助方法是我喜欢的Java 8 支持它。

这是说明我的观点的代码。

接口定义:

public interface IGenericEnum <T extends Enum<T>> {
    String getId();
    String getDisplayName();
    //If I was using Java 8 static helper methods would go here
}

一个枚举定义的示例:

public enum ExecutionModeType implements IGenericEnum<ExecutionModeType> {
    STANDARD ("Standard", "Standard Mode"),
    DEBUG ("Debug", "Debug Mode");

    String id;
    String displayName;

    //Getter methods
    public String getId() {
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    //Constructor
    private ExecutionModeType(String id, String displayName) {
        this.id = id;
        this.displayName = displayName;
    }

    //Helper methods - not enforced by Interface
    public static boolean isValidId(String id) {
        return GenericEnumUtility.isValidId(ExecutionModeType.class, id);
    }

    public static String printIdOptions(String delimiter){
        return GenericEnumUtility.printIdOptions(ExecutionModeType.class, delimiter);
    }

    public static String[] getIdArray(){
        return GenericEnumUtility.getIdArray(ExecutionModeType.class);
    }

    public static ExecutionModeType getById(String id) throws NoSuchObjectException {
        return GenericEnumUtility.getById(ExecutionModeType.class, id);
    }
}

通用枚举实用程序定义:

public class GenericEnumUtility {
    public static <T extends Enum<T> & IGenericEnum<T>> boolean isValidId(Class<T> enumType, String id) {       
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(enumOption.getId().equals(id)) {
                return true;
            }
        }

        return false;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String printIdOptions(Class<T> enumType, String delimiter){
        String ret = "";
        delimiter = delimiter == null ? " " : delimiter;

        int i = 0;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(i == 0) {
                ret = enumOption.getId();
            } else {
                ret += delimiter + enumOption.getId();
            }           
            i++;
        }

        return ret;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String[] getIdArray(Class<T> enumType){
        List<String> idValues = new ArrayList<String>();

        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            idValues.add(enumOption.getId());
        }

        return idValues.toArray(new String[idValues.size()]);
    }

    @SuppressWarnings("unchecked")
    public static <T extends Enum<T> & IGenericEnum<T>> T getById(Class<T> enumType, String id) throws NoSuchObjectException {
        id = id == null ? "" : id;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(id.equals(enumOption.getId())) {
                return (T)enumOption;
            }
        }

        throw new NoSuchObjectException(String.format("ERROR: \"%s\" is not a valid ID. Valid IDs are: %s.", id, printIdOptions(enumType, " , ")));
    }
}

b
beibichunai

假设接口中允许使用静态方法: * 它们将强制所有实现类声明该方法。 * 接口通常会通过对象使用,因此唯一有效的方法是非静态方法。 * 任何知道特定接口的类都可以调用其静态方法。因此,将在下面调用实现类的静态方法,但调用者类不知道是哪个。怎么知道?它没有实例化来猜测!

接口被认为是在处理对象时使用的。这样,一个对象是从一个特定的类中实例化的,所以最后一个问题就解决了。调用类不需要知道哪个特定类是因为实例化可以由第三个类完成。所以调用类只知道接口。

如果我们希望将其扩展到静态方法,我们应该可以在之前指定一个实现类,然后将引用传递给调用类。这可以通过接口中的静态方法使用该类。但是这个引用和一个对象有什么区别呢?我们只需要一个对象来表示它是什么类。现在,该对象代表旧类,并且可以实现包括旧静态方法的新接口——这些现在是非静态的。

元类用于此目的。你可以试试 Java 类。但问题是 Java 对此不够灵活。您不能在接口的类对象中声明方法。

这是一个元问题 - 当你需要做的时候

..胡说八道

无论如何,您有一个简单的解决方法 - 使该方法具有相同的逻辑非静态。但是你必须首先创建一个对象来调用该方法。


佚名

解决这个问题:错误:缺少方法体,或声明抽象静态无效主(字符串[] args);

interface I
{
    int x=20;
    void getValue();
    static void main(String[] args){};//Put curly braces 
}
class InterDemo implements I
{
    public void getValue()
    {
    System.out.println(x);
    }
    public static void main(String[] args)
    {
    InterDemo i=new InterDemo();
    i.getValue();   
    }

}

输出:20

现在我们可以在接口中使用静态方法


不过那也没用。在接口上定义静态方法不会强制在实现此类接口的类中进一步定义。如果您只是从接口 I 中完全删除静态方法,您的代码将毫无问题地编译和运行。换句话说,您不是在InterDemo 类中覆盖I 接口的main 方法,而是创建一个具有相同签名的新方法。
P
Pavel Feldman

我认为 java 没有静态接口方法,因为您不需要它们。你可能认为你这样做了,但是......你会如何使用它们?如果你想这样称呼他们

MyImplClass.myMethod()

那么你不需要在接口中声明它。如果你想这样称呼他们

myInstance.myMethod()

那么它不应该是静态的。如果您实际上要使用第一种方式,但只是想强制每个实现都具有这样的静态方法,那么它实际上是一种编码约定,而不是实现接口的实例和调用代码之间的约定。

接口允许您在实现接口的类实例和调用代码之间定义契约。而java可以帮助你确保这个契约没有被违反,所以你可以依赖它,不用担心什么类实现了这个契约,只要“签署契约的人”就足够了。如果是静态接口,您的代码

MyImplClass.myMethod()

不依赖每个接口实现都有这个方法,所以不需要java帮你确定。


B
BenMorel

接口中需要静态方法是什么,当您不必创建对象的实例时基本上使用静态方法接口的整个想法是引入OOP概念并引入静态方法,您正在转移概念。