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

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


当然这不会工作。但是为什么不呢?

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

IXMLizable.newInstanceFromXML(e);


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

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

是否存在无法覆盖静态方法的特殊技术原因?那就是为什么Java的设计者为什么决定使实例方法可重写而不是静态方法?

编辑:我的设计的问题是我试图使用接口来实施编码约定。 br />
也就是说,接口的目标是双重的:


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

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

评论

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

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

您能否提供一些代码,您希望如何使用静态接口方法?

这将在Java 8中实现:docs.oracle.com/javase/tutorial/java/IandI / ...

@dakshang是的,但是它没有OP想要的。

#1 楼

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

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

这里确实有两个问题:


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

接口中的静态方法

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

最后,Java 8引入了static接口方法以及具有默认实现的可重写实例方法。他们仍然没有实例字段。这些功能是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

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

评论


呼吁Project Coin。 mail.openjdk.java.net/pipermail/coin-dev/2009-March/000117.html

–迈克尔·迈尔斯(Michael Myers)♦
09年3月9日在18:53

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

–shrini1000
2011年3月1日4:56



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

– erickson
2011年3月1日下午5:47

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

– erickson
16年9月2日在19:43

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

–拉斐尔
18 Mar 7 '18 at 12:24

#2 楼

这已经有人问过并回答了,在这里

要重复我的答案:

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

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

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


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

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

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

评论


如果使用作为泛型类型参数,最好通过接口保证T可以.doSomething()。

–克里斯·贝蒂(Chris Betti)
2013年9月24日14:25在

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

– Juh_
15年7月16日在15:05



@Juh_,.....或绝对必要的新关键字。我相信静态无论如何在语言中都是一个愚蠢的术语,并且已经被拉伸得太远了。因此,拥有它本身已经很困难。请参阅上面的示例stackoverflow.com/questions/512877/…{shrug}。

–user4229245
16-09-2在18:14



这似乎是不正确的:“永远不要在接口中声明静态方法。”如果我有一些类的集合,可以在不实例化的情况下为我提供一些信息,但是我需要一个公共接口将这些静态类级别的信息放入其中(例如,具有可覆盖的静态方法的接口),那么这是一种有效的用法。想想反射++,您可以在其中捕获有关类属性的元信息,而无需四处寻找属性,反射等。

–詹森
17年3月16日在19:18

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

–user3790897
18年7月6日在13:09

#3 楼

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

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

public interface IXMLizable {
  public Element toXMLElement();
}


评论


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

– pvgoddijn
09年2月20日在9:34

有人可以告诉我在这里放是什么意思。我是java的新手。它是做什么的?

–努湾Harshakumara Piyarathna
5月6日12:08

@NuwanHarshakumaraPiyarathna T必须是扩展IXMLizable的类。查看Java泛型以更好地理解这意味着什么

–阿德里安
5月17日19:29

#4 楼

随着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

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

评论


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

–user8389458
18年2月18日在3:45

#5 楼

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

评论


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

– MichaelGG
09年2月4日在19:54

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

– erickson
09年2月4日在20:34

#6 楼


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


实际上您可以在Java 8中使用。

根据Java文档:


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


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


评论


很高兴知道这些Util类可以在接口本身中替换为静态方法。

–加拉夫
8月26日20:36

#7 楼

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

评论


简洁明了的逻辑。说得好。

–奥克·乌韦楚
19年8月15日19:00



#8 楼

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

其次,我们使用静态方法绝对有一个包含静态方法的接口模式的正当理由-我无法代表所有人,但是我会定期使用静态方法。

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

#9 楼

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

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

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


#10 楼


“是否存在不能覆盖静态方法的特殊原因”。

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


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

或者,更完整地说,如果我想在没有实例的情况下调用方法,但是了解该类后,如何根据我没有的实例来解决它。

#11 楼

注释EDIT: As of Java 8, static methods are now allowed in interfaces.

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

#12 楼

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

例如,我使用的对象关系层既具有值对象,又具有用于操纵对象的命令。价值对象。由于各种原因,每个值对象类都必须定义一些静态方法,这些静态方法使框架可以找到命令实例。例如,要创建一个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对象的操作。

#13 楼

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

使用泛型时,它们可以使用-带有或不带有默认实现。显然,将需要重写等等。但是,我的猜测是这样的用法不是非常面向对象(因为其他答案都令人费解地指出),因此认为不值得他们为有效实施而付出的努力。

评论


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

– DJClayworth
09年2月5日在15:21

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

– MichaelGG
09年2月5日在16:49

#14 楼

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


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

#15 楼

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

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

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

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

#16 楼

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

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

希望有帮助!

评论


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

–Rob
09年2月4日在20:21

#17 楼

您不能在接口中定义静态方法,因为静态方法属于类而不是类的实例,并且接口不是类。在此处了解更多信息。

但是,如果您愿意,可以执行以下操作:

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

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


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

#18 楼

假设您可以做到;考虑以下示例:

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类”。

– cdmckay
09年2月15日在15:59

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

– pvgoddijn
09年2月16日在8:47

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

– cdmckay
09年2月19日在20:43

我故意说IFace.thisIsTHeMethod,因为其中存在问题。如果没有未定义的行为,就不可能在接口上调用它(即使已在其上声明)

– pvgoddijn
09年2月20日在9:30

#19 楼

可以实现的是静态接口(而不是接口中的静态方法)。所有实现给定静态接口的类都应实现相应的静态方法。您可以使用

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
从任何Class clazz获取静态接口SI,然后可以调用si.method(params)
这将很有用(例如,用于工厂设计模式)因为您可以从编译时未知的类中获取(或检查其实现)SI静态方法的实现!
动态分配是必需的,并且可以通过扩展它来覆盖类的静态方法(如果不是最终方法)(通过静态接口调用时。)
显然,这些方法只能访问其类的静态变量。

#20 楼

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


#21 楼

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

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

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

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

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

..blah blah

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

#22 楼

解决此问题的方法:
错误:缺少方法主体,或声明抽象
static 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

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

评论


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

– Fran Marzoa
18-10-26在13:48



#23 楼

我认为Java没有静态接口方法,因为您不需要它们。您可能会认为自己可以,但是...
您将如何使用它们?如果要像

MyImplClass.myMethod()


这样称呼它们,则无需在接口中声明它。如果您想像这样称呼他们

myInstance.myMethod()


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

接口允许您定义实现该方法的类的实例之间的协定。接口和调用代码。 Java帮助您确保不违反此合同,因此您可以依靠它,不用担心哪个类可以实现此合同,仅“签署合同的人”就足够了。如果是静态接口,则您的代码
MyImplClass.myMethod()


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

#24 楼

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