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


498

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

这是示例:

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

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

可能的问题之一是,当您致电时会发生什么:

IXMLizable.newInstanceFromXML(e);

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

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

有某种特殊的技术原因为什么不能覆盖静态方法?也就是说,为什么Java的设计者决定使实例方法可重写而不是静态方法?

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

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

  1. 我希望IXMLizable接口允许我将实现它的类转换为XML元素(使用多态性,效果很好)。

  2. 如果有人想创建实现IXMLizable接口的类的新实例,那么他们将始终知道将有一个newInstanceFromXML(Element e)静态构造函数。

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


4
不需要在接口中使用public来杂乱方法(和字段)定义,顺便说一句。
Tom Hawtin-大头钉

嗯,似乎是stackoverflow.com/questions/21817/…的副本。以前没看过。
迈克尔·迈尔斯

1
您能否提供一些代码,您想如何使用静态接口方法?
Pavel Feldman


1
@dakshang是的,但是它不执行OP想要的操作。
user253751

Answers:


518

Java 8允许使用静态接口方法

使用Java 8,接口可以具有静态方法。它们也可以有具体的实例方法,但没有实例字段。

这里确实有两个问题:

  1. 为什么在糟糕的过去,接口不能包含静态方法?
  2. 为什么不能覆盖静态方法?

接口中的静态方法

没有任何强大的技术原因可以使接口在以前的版本中不能具有静态方法。重复问题的发贴人很好地总结了这一点。静态接口方法最初被认为是一种小的语言更改,然后正式提议在Java 7中添加它们,但是由于无法预料的复杂性而将删除。

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

覆盖静态方法

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

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

需要一些实例方法的工作背景,以了解这里发生的情况。我确定实际的实现是完全不同的,但是让我解释一下我的方法分派的概念,该方法可以准确地对观察到的行为建模。

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

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

现在,假设我们跳过对象实例,而只是从子类开始。解决方法可以如上所述进行,从而为您提供一种“可重写”的静态方法。但是,由于编译器是从一个已知的类开始的,而不是等到运行时才为该类查询一个未指定类型的对象,所以解析可能全部在编译时发生。“覆盖”静态方法没有意义,因为可以始终指定包含所需版本的类。


构造函数“接口”

这是解决该问题的最新编辑的更多材料。

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

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

Foo obj = Foo.newInstanceFromXML(e);

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

构造是实现的一部分,而不是接口。任何与接口成功工作的代码都不关心构造函数。任何关心构造函数的代码都必须知道具体的类型,并且可以忽略该接口。



12
#1的原因可能是多重继承吗?因为我们可以从多个接口继承,所以如果两个接口包含相同的静态方法签名,然后一个类同时实现了这两个方法并调用该方法,那么事情就可能变得很复杂,Java语言创建者希望通过禁止使用多个类继承来避免这种情况。第一名。很明显,接口完全可以使用相同的参数,而根本不允许任何方法定义。
shrini1000 2011年

1
@ shrini1000-否,静态方法在编译时解析。歧义的处理方式可以与常量处理方式相同:带有编译器错误。但是,由于一些无法预见的困难,项目硬币项目下的提案被拒绝了。不知道它们是什么,但我不认为这是沿着这些思路。
埃里克森

1
@ tgm1024是的,“构造函数'接口'”部分解释了为什么尝试通过在编译时已知的类型来调用多态行为没有意义。您将如何RESET()在给定的类上调用?你会写SomeClass.RESET()。因此,您不需要一个接口来描述该API。它的静态。当您在编译时不知道具体类型时,可以使用接口。静态方法绝不是这种情况。
erickson

2
“构造是实现的一部分,而不是接口的一部分。任何与接口成功工作的代码都不会在意构造函数。” -这显然是不正确的。在其他语言中(例如Swift),我可以创建新实例而T无需T静态地知道,因为我承诺在接口中某个特定的构造函数(或静态方法)将在运行时存在。Java无法指定生成这一事实,并不意味着它不是有意义的事情。
拉斐尔

48

这已经被问到并回答

复制我的答案:

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

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

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

静态规则说必须执行声明的var类型中定义的方法。由于这是一个接口,因此这是不可能的。

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

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


14
如果使用<T extended MyInterface>作为泛型类型参数,则最好通过接口保证T可以.doSomething()。
克里斯·贝蒂

4
虽然我理解了这些参数,但我也同意@Chris_Betti(即使对于非泛型类型也是如此):很好的是,代码结构可确保某些类实现特定的静态API。也许可以使用其他概念...
Juh_

@Juh_,.....或绝对必要的新关键字。我相信static无论如何,这是一个措辞拙劣的语言,而且已经延伸得太远了。因此,拥有它本身已经很困难。请参阅我上面的示例stackoverflow.com/questions/512877/…{shrug }。

3
这似乎是不正确的:“永远不要在接口中声明静态方法。” 如果我有一些类的集合,可以在不实例化的情况下为我提供一些信息,但是我需要一个公共接口将这些静态类级别的信息放入其中(例如,具有可覆盖的静态方法的接口),那么这是一种有效的用法。想想反射++,在那里你可以捕捉关于类属性的元信息没有黑客各地的属性,反射等
杰森

1
“在接口中声明静态方法永远没有意义。” 事实并非如此:假设您的系统具有默认的类解析器。如果它检测到您实现了ContainerInjectionInterce :: create(Container $ container)方法,则它将使用此函数创建该对象。
user3790897

37

通常,这是使用Factory模式完成的

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

public interface IXMLizable {
  public Element toXMLElement();
}

7
+1工厂模式听起来像是解决问题的方法。(尽管不是这个问题)
pvgoddijn

有人可以告诉我在这里放<T extended IXMLizable>是什么意思。我是java的新手,它是做什么的?
Nuwan Harshakumara Piyarathna

1
@NuwanHarshakumaraPiyarathna T必须是扩展IXMLizable的类。查看Java泛型以更好地理解其含义
adrian

37

随着Java 8的出现,现在可以在接口中编写默认方法和静态方法。 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

提示:调用静态接口方法不需要任何类实现。确实发生这种情况是因为超类中静态方法的相同规则适用于接口上的静态方法。


这是这个问题的完美例子。

21

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


2
您总是可以强制每种类型实现任何静态接口方法。类型类,有人吗?
MichaelGG,

16
走出自己并回答以下问题:为什么不能覆盖静态方法?如果可以重写静态方法,它将是什么样?你能和他们做什么?答案基本上是“不能,因为不能”。
erickson

10

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

实际上,您可以使用Java 8。

根据Java doc

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

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

默认方法示例:

list.sort(ordering);

代替

Collections.sort(list, ordering);

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

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

6

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


清晰简洁的逻辑。说得好。
Oke Uwechue

6

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

其次,我们完全使用静态方法意味着有一个包含静态方法的接口模式是有道理的-我无法代表你们,但是我会定期使用静态方法。

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


5

静态方法并不像实例方法那样是虚拟的,因此我想Java设计人员会决定他们不想在接口中使用它们。

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

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

5
  • “是否有不能覆盖静态方法的特殊原因”。

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

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

或者,更全面地说,如果我想在没有实例的情况下调用一个方法,但又知道该类,那么如何根据我没有的实例来解决它。


3

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

例如,我使用的对象关系层既有值对象,又有操纵值对象的命令。由于各种原因,每个值对象类都必须定义一些静态方法,这些静态方法使框架可以找到命令实例。例如,要创建一个人物,您需要执行以下操作:

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

并通过ID加载人

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

这是相当方便的,但是它有问题。值得注意的是,静态方法的存在无法在接口中强制执行。接口中可重写的静态方法正是我们所需要的,只要它能以某种方式起作用。

EJB通过具有Home接口来解决此问题。每个对象都知道如何找到其Home,并且Home包含“静态”方法。这样,可以根据需要覆盖“静态”方法,并且不会用不应用于bean实例的方法使常规(称为“远程”)接口杂乱无章。只需使普通接口指定“ getHome()”方法即可。返回Home对象的一个​​实例(我想应该是单例),并且调用者可以执行影响所有Person对象的操作。


3

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

是的,因为接口中允许使用Java 8,所以是静态方法,但是您的示例仍然无法使用。您不能只定义一个静态方法:您必须实现它,否则将获得编译错误。


2

好吧,没有泛型,静态接口就没用了,因为所有静态方法调用都在编译时解决。因此,它们没有实际用途。

使用泛型时,它们可以使用-带有或不带有默认实现。显然,将需要重写等等。但是,我的猜测是这样的用法不是很“ OO”(正如其他答案所指出的那样晦涩),因此认为不值得他们为有效实施而付出的努力。


1
泛型与此有什么关系?接口上的静态方法仍然无法执行。
DJClayworth

首先,这将是一个实施决策。但是我猜他不想在接口上调用静态方法(他可以只使用一个类)。但是相反,它希望有某种像类型类之类的东西,而不是类型参数之类的东西。实际上,他的最新编辑更清楚地显示了这一点。
MichaelGG

2
Why can't I define a static method in a Java interface?

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


1

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

因此,接口中与静态方法最接近的近似值将是忽略“ this”(即不访问实例的任何非静态成员)的非静态方法。在低层抽象中,每个非静态方法(在任何vtable中查找之后)实际上只是一个具有类范围的函数,该函数将“ this”作为隐式形式参数。请参阅Scala的单例对象以及与Java的互操作性作为该概念的证据。因此,每个静态方法都是具有类范围的函数,并且不采用“ this”参数。因此,通常可以静态调用静态方法,但是如前所述,接口没有实现(抽象)。

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

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


0

接口仅提供类将提供的内容的列表,而不是这些内容的实际实现,而这正是您的静态项。

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

希望有帮助!


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

0

您不能在接口中定义静态方法,因为静态方法属于类而不属于类的实例,并且接口不是类。在这里阅读更多。

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

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

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

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


0

假设您可以做到;考虑这个例子:

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

}

1
它会显示“我是A类”。但是,如果键入A.thisIsTheMethod(),它将显示“我是B级”。
cdmckay,2009年

但是如果在接口上调用方法,您(或编译器)将如何知道应调用哪个方法?(请注意,可能会有更多的类认真地实现Iface
pvgoddijn

抱歉,我的意思是说:但是,如果您键入B.thisIsTheMethod()它,则会显示“我是B级”。
cdmckay

我之所以说IFace.thisIsTHeMethod是因为存在问题。如果没有未定义的行为(即使已在其上声明),则不可能在接口上调用它
pvgoddijn

0

可以实现的是静态接口(而不是接口中的静态方法)。所有实现给定静态接口的类都应实现相应的静态方法。您可以使用以下方法从任何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静态方法实现!动态分派是必需的,并且可以通过扩展类(通过静态接口调用时)来覆盖类的静态方法(如果不是最终方法)。显然,这些方法只能访问其类的静态变量。


0

当我意识到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, " , ")));
    }
}

0

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

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

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

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

这是一个元问题-当您需要做屁股时

..等等等等

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


0

解决此问题的方法:错误:缺少方法主体,或声明抽象静态void main(String [] 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

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


1
不过那没用。在接口上定义静态方法不会在实现此类接口的类中强制执行进一步的定义。如果仅从接口I完全删除静态方法,则您的代码将始终可以编译和运行,而不会出现问题。换句话说,您不会在InterDemo类中重写 I接口的main方法,而只是创建一个具有相同签名的新方法。
弗朗·马索亚

-2

我认为Java没有静态接口方法,因为您不需要它们。您可能会认为自己做到了,但是...您将如何使用它们?如果你想给他们打电话

MyImplClass.myMethod()

那么您无需在接口中声明它。如果你想给他们打电话

myInstance.myMethod()

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

接口允许您定义实现接口的类实例和调用代码之间的协定。Java可以帮助您确保不违反该合同,因此您可以依靠它,不用担心哪个类可以实现此合同,仅“签署合同的人”就足够了。在静态接口的情况下,您的代码

MyImplClass.myMethod()

并不依赖于每个接口实现都具有此方法这一事实,因此您不需要Java来帮助您确定它。


-5

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

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.