【问题标题】:Why can't static methods be abstract in Java?为什么Java中的静态方法不能是抽象的?
【发布时间】:2010-09-27 02:58:34
【问题描述】:

问题是在 Java 中为什么我不能定义一个抽象的静态方法?例如

abstract class foo {
    abstract void bar( ); // <-- this is ok
    abstract static void bar2(); //<-- this isn't why?
}

【问题讨论】:

  • 几个原因:静态方法必须有一个主体,即使它们是抽象类的一部分,因为不需要创建一个类的实例来访问它的静态方法。另一种思考方式是,如果我们暂时假设它是允许的,那么问题是静态方法调用不提供任何运行时类型信息 (RTTI),请记住不需要创建实例,因此它们无法重定向对其特定的覆盖实现,因此允许抽象静态完全没有意义。换句话说,它不能提供任何多态性的好处,因此是不允许的。

标签: java abstract-class static-methods


【解决方案1】:

您不能覆盖静态方法,因此将其抽象化将毫无意义。此外,抽象类中的静态方法属于该类,而不是覆盖类,因此无论如何都不能使用。

【讨论】:

  • 是的,Java 中的静态方法不能被覆盖,这真的很可惜。
  • @Michel:重点是什么?如果您想要基于实例的行为,请使用实例方法。
  • 这个答案不正确。抽象类中的静态方法工作正常并且很常用。只是类本身的静态方法可能不是抽象的。 @Michel 重写静态方法没有意义。如果没有实例,运行时如何知道调用哪个方法?
  • @erickson - 即使没有实例,类层次结构也是完整的 - 静态方法的继承可以像实例方法的继承一样工作。 Smalltalk 做到了,而且非常有用。
  • @matiasg 这一点都不新鲜。抽象类一直被允许拥有静态的、非抽象方法。
【解决方案2】:

因为“抽象”的意思是:“不实现任何功能”,而“静态”的意思是:“即使没有对象实例也有功能”。这是一个逻辑矛盾。

【讨论】:

  • 更简洁的答案是“糟糕的语言设计”。静态应该意味着“属于该类”,因为正如这个问题所展示的那样,这就是它的直观使用方式。请参阅 Python 中的“类方法”。
  • @Tomalak 抱歉,我不清楚。当然,静态方法“属于类”。尽管如此,它只是在它存在于同一个命名空间中的意义上。静态方法不是类对象本身的方法:它不以 'this' 作为类对象进行操作,也没有正确参与继承链。如果它真的是一个类方法abstract static 将非常有意义。这将是子类对象必须实现的类对象本身的方法。当然,尽管我对语言感到不满,但你的答案是正确的。
  • 这不是逻辑矛盾,这是语言的缺陷,其他多种语言都支持这个概念。 “抽象”表示“在子类中实现”,“静态”表示“在类而不是类实例上执行”,没有逻辑矛盾。
  • @Eric:还有还是,你说的不适用于abstract static:“在子类中实现”的函数X不能 同时被“在类上执行”——只在子类上。它不再是抽象的了。
  • @Tomakak:你的逻辑是循环的。 static 并不意味着“不为空”——这只是 Java 不允许抽象静态方法的结果。它的意思是“可在课堂上调用”。 (这应该意味着“在类上可调用 only”,但这是另一个问题。)如果 Java 支持 abstract static 方法,我希望它意味着方法 1) 必须由子类实现,并且2) 是子类的类方法。有些方法作为实例方法没有意义。不幸的是,Java 不允许您在创建抽象基类(或接口)时指定。
【解决方案3】:

可以在没有类实例的情况下调用静态方法。在您的示例中,您可以调用 foo.bar2(),但不能调用 foo.bar(),因为对于 bar,您需要一个实例。 以下代码可以工作:

foo var = new ImplementsFoo();
var.bar();

如果您调用静态方法,它将始终执行相同的代码。在上面的例子中,即使你在 ImplementsFoo 中重新定义了 bar2,对 var.bar2() 的调用也会执行 foo.bar2()。

如果 bar2 现在没有实现(这就是抽象的意思),您可以调用没有实现的方法。这是非常有害的。

【讨论】:

  • 并且可以在没有实例的情况下调用抽象静态方法,但需要在子类中创建实现。这不完全是多态性,但解决它的唯一方法是让具体的孩子实现一个“需要”“抽象静态”方法的接口。凌乱,但可行。
  • 其实我错了。接口中也不能有静态方法。语言缺陷。
【解决方案4】:

方法的abstract 注释表明该方法必须在子类中被覆盖。

在 Java 中,static 成员(方法或字段)不能被子类覆盖(在其他面向对象语言中不一定如此,请参阅 SmallTalk。)static 成员可能隐藏,但这与覆盖有着根本的不同。

由于静态成员不能在子类中被覆盖,abstract 注释不能应用于它们。

顺便说一句 - 其他语言确实支持静态继承,就像实例继承一样。从语法的角度来看,这些语言通常要求在语句中包含类名。例如,在 Java 中,假设你在 ClassA 中编写代码,这些是等价的语句(如果 methodA() 是静态方法,并且没有具有相同签名的实例方法):

ClassA.methodA();

methodA();

在SmallTalk中,类名不是可选的,所以语法是(注意SmallTalk不使用.来分隔“主语”和“动词”,而是使用它作为statemend终止符):

ClassA methodA.

因为总是需要类名,所以总是可以通过遍历类层次结构来确定方法的正确“版本”。对于它的价值,我偶尔会想念static 继承,并且在我刚开始使用它时被 Java 中缺乏静态继承所困扰。此外,SmallTalk 是鸭子类型的(因此不支持按合同编程。)因此,它没有 abstract 类成员的修饰符。

【讨论】:

  • “静态成员不能被子类覆盖”是错误的。至少在 Java6 中是可能的。不知道从什么时候开始。
  • @Steven De Groote 静态成员确实不能被子类覆盖。如果子类具有与超类中的静态方法具有相同签名的静态方法,它不会覆盖它,而是隐藏它。 http://docs.oracle.com/javase/tutorial/java/IandI/override.html 不同的是,多态性只对被覆盖的方法起作用,对隐藏的方法不起作用。
  • @John29 感谢您的澄清,但除了命名不同之外,它的用法似乎相似。
  • @Steven De Groote 是的,用法相似,但行为不同。这就是为什么没有静态抽象方法的原因——如果静态抽象方法不支持多态性,那还有什么意义?
  • @Steven De Groote:当您在超类本身中调用该方法时,差异就会变得明显。假设 Super.foo 调用 Super.bar。如果子类实现了 Subclass.bar,然后调用 foo,那么 foo 仍然会调用 Super.bar,而不是 Subclass.bar。因此,您真正拥有的是两种完全不同且不相关的方法,都称为“bar”。这在任何有用的意义上都不是压倒一切的。
【解决方案5】:

糟糕的语言设计。直接调用静态抽象方法比仅仅为使用该抽象方法而创建实例要有效得多。当使用抽象类作为枚举无法扩展的解决方法时尤其如此,这是另一个糟糕的设计示例。希望他们在下一个版本中解决这些限制。

【讨论】:

  • Java 充满了奇怪的限制。仅访问最终变量的闭包是另一种情况。剩下的名单几乎是无穷无尽的。了解它们及其变通方法是 Java 程序员的工作。为了玩得开心,我们必须在业余时间使用比 Java 更好的东西。但我不会打扰。这是取得进步的种子。
  • 我相信你所说的“糟糕的语言设计”实际上更像是一种“保护性语言设计”,其目的是限制程序员由于不必要的语言特性而违反 OO 原则。
  • “抽象静态”的概念是否违反了OO原则?
  • @threed,一点也不,但当然也有人说static 本身的概念本身就已经违反了......
  • 对静态的需求清楚地表明“OO 原则”并不像通常声称的那样包罗万象。
【解决方案6】:

这是一种糟糕的语言设计,真的没有理由说明为什么它不可能。

事实上,这是一种模式或方式,说明它如何在 **Java ** 中被模仿,让您至少能够修改自己的实现:

public static abstract class Request {                 

        // Static method
        public static void doSomething() {
                get().doSomethingImpl();
        }
        
        // Abstract method
        abstract void doSomethingImpl();

        /////////////////////////////////////////////
        private static Request SINGLETON;
        private static Request get() {
            if ( SINGLETON == null ) {
                // If set(request) is never called prior,
                // it will use a default implementation. 
                return SINGLETON = new RequestImplementationDefault();
            }
            return SINGLETON;
        }
        public static Request set(Request instance){
            return SINGLETON = instance;
        }
        /////////////////////////////////////////////
}

两种实现方式:

/////////////////////////////////////////////////////

public static final class RequestImplementationDefault extends Request {
        @Override void doSomethingImpl() {
                System.out.println("I am doing something AAA");
        }
}

/////////////////////////////////////////////////////

public static final class RequestImplementaionTest extends Request {
        @Override void doSomethingImpl() {
                System.out.println("I am doing something BBB");
        }
}

/////////////////////////////////////////////////////

可以如下使用:

Request.set(new RequestImplementationDefault());

// Or

Request.set(new RequestImplementationTest());

// Later in the application you might use

Request.doSomething();

这将允许您静态地调用您的方法,但能够更改测试环境的实现。

理论上,您也可以在 ThreadLocal 上执行此操作,并且能够为每个线程上下文设置实例,而不是像这里看到的那样完全全局,然后可以执行 Request.withRequest(anotherRequestImpl, () -&gt; { ... }) 或类似操作。

现实世界通常不需要ThreadLocal 方法,通常只要能够全局更改测试环境的实现就足够了。

请注意,这样做的唯一目的是启用一种方式保留直接轻松调用方法的能力CLEANLY 静态方法提供的同时能够切换 实现 应该 欲望的产生是以稍微复杂的实现为代价的。

这只是一种绕过通常不可修改的静态代码的模式。

【讨论】:

  • 我不明白您在哪里提供了问题中提出的 abstract static 方法的示例,并且您用粗体写了 CAN BE DONE IN JAVA。这完全是误导。
  • 它本身不允许您将其定义为抽象静态,但您可以获得类似的结果,您可以使用此模式/hack 更改静态方法的实现。这几乎不会被误导。可以做到,但使用不同的语义。
  • 这是一个扩展抽象类,然后将静态方法放入子类的示例。无论如何,这不是可以在 JAVA 中完成的示例。
  • @ScubaSteve 首先,你的结论是错误的。其次,它达到了相同的结果。这意味着对类的静态访问可以由另一个实现更改。说我使 static 关键字可抽象并不是一个答案,但是使用这种模式,您可以使用静态方法并仍然更改它们的实现。虽然它确实具有全局性的负面影响,但对于测试/生产/开发环境,它对我们有用。
【解决方案7】:
  • 一个抽象方法的定义只是为了它可以在子类中被覆盖。但是,静态方法不能被覆盖。因此,有一个抽象的静态方法是一个编译时错误。

    现在下一个问题是为什么不能覆盖静态方法??

  • 这是因为静态方法属于特定类而不属于其实例。如果您尝试覆盖静态方法,您不会收到任何编译或运行时错误,但编译器只会隐藏超类的静态方法。

【讨论】:

    【解决方案8】:

    因为如果一个类扩展了一个抽象类,那么它必须覆盖抽象方法,这是强制性的。并且由于静态方法是在编译时解析的类方法,而被覆盖的方法是在运行时解析并遵循动态多态性的实例方法。

    【讨论】:

    • 请大写和标点这个烂摊子。
    【解决方案9】:

    我也问了同样的问题,这就是为什么

    既然抽象类说了,就不给实现,让子类给它

    所以子类必须重写超类的方法,

    RULE NO 1 - 静态方法不能被覆盖

    因为静态成员和方法是编译时元素,这就是为什么允许静态方法的重载(编译时多态性)而不是覆盖(运行时多态性)

    所以,它们不能是 Abstract 。

    没有像 abstract static

    【讨论】:

    • -1,“Java 不允许重写静态方法,因为静态成员和方法是编译时元素”是不正确的。使用abstract static 绝对可以进行静态类型检查,请参阅stackoverflow.com/questions/370962/…。 Java 不允许覆盖静态方法的真正原因是因为 Java 不允许覆盖静态方法。
    • 重载与多态无关。除了前缀“over”之外,重载和覆盖没有任何共同之处,就像 Java 和 JavaScript 恰好都有“Java”一样。方法的名称不是它的身份,而是它的签名。所以foo(String)foo(Integer) 不同——仅此而已。
    • @CaptainMan 重载字面上称为“参数多态”,因为根据参数的类型,会调用不同的方法,即多态。
    【解决方案10】:

    拥有一个抽象静态方法的想法是,您不能直接为该方法使用该特定抽象类,但只允许一阶导数实现该静态方法(或对于泛型:实际类您使用的泛型)。

    这样,您可以创建例如 sortableObject 抽象类甚至接口 使用(自动)抽象静态方法,它定义了排序选项的参数:

    public interface SortableObject {
        public [abstract] static String [] getSortableTypes();
        public String getSortableValueByType(String type);
    }
    

    现在您可以定义一个可排序的对象,该对象可以按所有这些对象相同的主要类型进行排序:

    public class MyDataObject implements SortableObject {
        final static String [] SORT_TYPES = {
            "Name","Date of Birth"
        }
        static long newDataIndex = 0L ;
    
        String fullName ;
        String sortableDate ;
        long dataIndex = -1L ;
        public MyDataObject(String name, int year, int month, int day) {
            if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
            if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
            this.fullName = name ;
            this.sortableDate = MyUtils.createSortableDate(year,month,day);
            this.dataIndex = MyDataObject.newDataIndex++ ;
        }
        public String toString() {
            return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
        }
    
        // override SortableObject 
        public static String [] getSortableTypes() { return SORT_TYPES ; }
        public String getSortableValueByType(String type) {
            int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
            switch(index) {
                 case 0: return this.name ;
                 case 1: return this.sortableDate ;
            }
            return toString(); // in the order they were created when compared
        }
    }
    

    现在你可以创建一个

    public class SortableList<T extends SortableObject> 
    

    可以检索类型,构建弹出菜单,以通过从该类型获取数据来选择要对列表进行排序和度假函数的类型,以及Hainv Add函数,即在选择排序类型时, 可以自动排序新项目。 注意SortableList的实例可以直接访问“T”的静态方法:

    String [] MenuItems = T.getSortableTypes();
    

    必须使用实例的问题是 SortableList 可能还没有项目,但已经需要提供首选排序。

    欢呼, 奥拉夫。

    【讨论】:

      【解决方案11】:

      您可以使用 Java 8 中的接口来做到这一点。

      这是关于它的官方文档:

      https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

      【讨论】:

      • 怎么样?我一直在寻找解决方案,但找不到任何解决方案。
      • 什么?你不能。所有静态接口方法都必须使用接口类调用。
      • 这个答案是错误的,并且会误导 Java 新手。 这确实显示了抽象静态方法的任何示例,因为它无法在其他答案中实现和说明
      【解决方案12】:

      首先,关于抽象类的一个关键点—— 无法实例化抽象类(请参阅wiki)。因此,您不能创建抽象类的 any 实例。

      现在,java 处理静态方法的方式是与该类的所有实例共享方法。

      所以,如果你不能实例化一个类,那么这个类就不能有抽象的静态方法,因为抽象方法需要被扩展。

      轰隆隆。

      【讨论】:

      • 抽象类中的每个方法都需要对其类进行扩展才能执行,所以这不是借口。您可以扩展抽象类(同时实现抽象方法)。所以这不能作为解释。
      【解决方案13】:

      假设有两个类,ParentChildParentabstract。声明如下:

      abstract class Parent {
          abstract void run();
      }
      
      class Child extends Parent {
          void run() {}
      }
      

      这意味着Parent 的任何实例都必须指定run() 的执行方式。

      但是,现在假设 Parent 不是 abstract

      class Parent {
          static void run() {}
      }
      

      这意味着Parent.run() 将执行静态方法。

      abstract 方法的定义是“已声明但未实现的方法”,这意味着它本身不返回任何内容。

      static 方法的定义是“无论在哪个实例上调用它,都为相同参数返回相同值的方法”。

      abstract 方法的返回值会随着实例的变化而变化。 static 方法不会。 static abstract 方法几乎是一种返回值恒定但不返回任何内容的方法。这是一个逻辑矛盾。

      另外,static abstract 方法确实没有太多理由。

      【讨论】:

        【解决方案14】:

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

        【讨论】:

          【解决方案15】:

          抽象类不能有静态方法,因为抽象是为了实现动态绑定,而静态方法静态绑定到它们的功能。静态方法意味着 行为不依赖于实例变量,因此没有实例/对象 是必需的。只是类。静态方法属于类而不是对象。 它们存储在称为PERMGEN 的内存区域中,从该区域与每个对象共享。 抽象类中的方法动态绑定到它们的功能。

          【讨论】:

          • 抽象类当然可以有静态方法。但不是静态抽象方法。
          • 那么请Java添加一个新关键字,用于属于类而不是实例的动态绑定方法。
          【解决方案16】:

          我相信我已经找到了这个问题的答案,即为什么接口的方法(就像父类中的抽象方法一样工作)不能是静态的。 Here is the full answer (not mine)

          基本上静态方法可以在编译时绑定,因为要调用它们,您需要指定一个类。这与实例方法不同,实例方法的引用类在编译时可能是未知的(因此调用的代码块只能在运行时确定)。

          如果您正在调用静态方法,则您已经知道实现它的类或它的任何直接子类。如果你定义

          abstract class Foo {
              abstract static void bar();
          }
          
          class Foo2 {
              @Override
              static void bar() {}
          }
          

          那么任何Foo.bar();的调用显然都是非法的,你会一直使用Foo2.bar();

          考虑到这一点,静态抽象方法的唯一目的是强制子类实现这样的方法。您可能最初认为这是非常错误的,但如果您有一个泛型类型参数&lt;E extends MySuperClass&gt;,那么通过接口保证E 可以.doSomething() 会很好。请记住,由于类型擦除,泛型仅在编译时存在。

          那么,它有用吗?是的,也许这就是 Java 8 允许在接口中使用静态方法的原因(尽管只有默认实现)。为什么不在类中使用默认实现抽象静态方法?仅仅因为具有默认实现的抽象方法实际上是具体方法。

          为什么不抽象/接口没有默认实现的静态方法?显然,仅仅是因为 Java 识别它必须执行哪个代码块的方式(我的答案的第一部分)。

          【讨论】:

            【解决方案17】:

            因为“抽象”意味着该方法将被覆盖,而不能覆盖“静态”方法。

            【讨论】:

            • 这个答案没有增加以前的答案尚未解决的任何内容。
            • @MarsAtomic 我认为这比最高投票的答案更合适。也很简洁。
            • 然后,当您有足够的代表时,您可以编辑较早的答案以改进它们。您所做的只是通过创建重复的答案给信号添加噪音。请遵循 Stack Overflow 的既定规则和习惯,而不是创建自己的规则和习惯并期望其他人都遵守。
            • 我不同意,请将我的答案与其他答案进行比较,尤其是票数最高的答案。
            • “为什么我不能这样做?”答案:“因为你不能”。
            【解决方案18】:

            当常规方法旨在被子类覆盖并提供功能时,它们可以是抽象的。 想象类FooBar1, Bar2, Bar3 等扩展。所以,每个人都会根据自己的需要拥有自己的抽象类版本。

            现在,静态方法根据定义属于类,它们与类的对象或其子类的对象无关。它们甚至不需要它们存在,它们可以在不实例化类的情况下使用。因此,它们需要随时可用,并且不能依赖子类向它们添加功能。

            【讨论】:

              【解决方案19】:

              根据定义,静态方法不需要知道this。因此,它不能是虚方法(根据this 提供的动态子类信息重载);相反,静态方法重载仅基于编译时可用的信息(这意味着:一旦您引用超类的静态方法,您就调用超类方法,而不是子类方法)。

              据此,抽象静态方法将毫无用处,因为您永远不会将其引用替换为某个已定义的主体。

              【讨论】:

                【解决方案20】:

                我看到已经有无数的答案,但我没有看到任何实际的解决方案。当然,这是一个真正的问题,没有充分的理由在 Java 中排除这种语法。由于原始问题缺少可能需要的上下文,因此我提供了上下文和解决方案:

                假设您在一堆相同的类中有一个静态方法。这些方法调用特定于类的静态方法:

                class C1 {
                    static void doWork() {
                        ...
                        for (int k: list)
                            doMoreWork(k);
                        ...
                    }
                    private static void doMoreWork(int k) {
                        // code specific to class C1
                    }
                }
                class C2 {
                    static void doWork() {
                        ...
                        for (int k: list)
                            doMoreWork(k);
                        ...
                    }
                    private static void doMoreWork(int k) {
                        // code specific to class C2
                    }
                }
                

                C1C2 中的doWork() 方法是相同的。可能有很多这样的类:C3C4 等。如果允许static abstract,您可以通过执行以下操作来消除重复代码:

                abstract class C {
                    static void doWork() {
                        ...
                        for (int k: list)
                            doMoreWork(k);
                        ...
                    }
                
                    static abstract void doMoreWork(int k);
                }
                
                class C1 extends C {
                    private static void doMoreWork(int k) {
                        // code for class C1
                    }
                }
                
                class C2 extends C {
                    private static void doMoreWork(int k) {
                        // code for class C2
                    }
                }
                

                但这不会编译,因为static abstract 组合是不允许的。 但是,这可以通过 static class 构造来规避,这是允许的:

                abstract class C {
                    void doWork() {
                        ...
                        for (int k: list)
                            doMoreWork(k);
                        ...
                    }
                    abstract void doMoreWork(int k);
                }
                class C1 {
                    private static final C c = new  C(){  
                        @Override void doMoreWork(int k) {
                            System.out.println("code for C1");
                        }
                    };
                    public static void doWork() {
                        c.doWork();
                    }
                }
                class C2 {
                    private static final C c = new C() {
                        @Override void doMoreWork(int k) {
                            System.out.println("code for C2");
                        }
                    };
                    public static void doWork() {
                        c.doWork();
                    }
                }
                

                使用此解决方案,唯一重复的代码是

                    public static void doWork() {
                        c.doWork();
                    }
                

                【讨论】:

                • 既然在您的最终解决方案中,抽象类 C 没有任何静态方法,那么为什么不让 C1 和 C2 扩展它并覆盖 doMoreWork() 方法并让任何其他类使其实例和调用成为必需方法。基本上你正在做同样的事情,即使用匿名类扩展类 C,然后在 C1 和 C2 中使用它的静态实例来允许从静态方法中进行访问,但这根本不是必需的。
                • 我不明白您在此处提供的上下文。在您的最终解决方案中,您可以调用C1.doWork()C2.doWork(),但您不能调用C.doWork()。同样在您提供的示例中,它不起作用,假设如果它被允许,那么C 类将如何找到doMoreWork() 的实现?最后,我将您的上下文代码称为糟糕的设计。为什么?仅仅是因为您为唯一的代码创建了一个单独的函数,而不是为常见的代码创建一个函数,然后在类C 中实现一个静态函数。这更容易!!!
                【解决方案21】:

                因为 abstract 是一个应用于抽象方法的关键字,所以不指定主体。如果我们谈论静态关键字,它属于类区域。

                【讨论】:

                • 请详细说明您的答案。
                【解决方案22】:

                因为如果您在类中使用任何静态成员或静态变量,它将在类加载时加载。

                【讨论】:

                • 为什么会是个问题?
                【解决方案23】:

                将方法声明为static意味着我们可以通过其类名调用该方法,如果该类也是abstract,那么调用它是没有意义的,因为它不包含任何主体,因此我们不能将方法声明为staticabstract

                【讨论】:

                • 但是我们希望在扩展类中有静态方法。例如,写一个类的名称而不是getSimpleName()。我们希望拥有abstract static String getClassName(); 并在所有子类中扩展它。
                【解决方案24】:

                因为抽象类是一个面向对象的概念,而静态成员不是面向对象的一部分......
                现在的事情是我们可以在接口中声明静态完整方法,我们可以通过在接口中声明主方法来执行接口

                interface Demo 
                {
                  public static void main(String [] args) {
                     System.out.println("I am from interface");
                  }
                }
                

                【讨论】:

                  【解决方案25】:

                  由于抽象方法属于类,不能被实现类覆盖。即使有相同签名的静态方法,它也会隐藏方法,不会覆盖它。 所以将抽象方法声明为静态是无关紧要的,因为它永远不会得到主体。因此,编译时错误。

                  【讨论】:

                    【解决方案26】:

                    因为抽象方法总是需要子类来实现。但是如果你将任何方法设置为静态,则此方法无法覆盖

                    例子

                    abstract class foo {
                        abstract static void bar2(); 
                    }
                    
                    
                    class Bar extends foo {
                        //in this if you override foo class static method then it will give error
                    }
                    

                    【讨论】:

                      【解决方案27】:

                      有一种情况是 static 和 abstract 可以一起使用,即这两个修饰符都放在嵌套类的前面。

                      【讨论】:

                        【解决方案28】:

                        静态方法 无需创建类的实例即可调用静态方法。静态方法属于类而不是类的对象。 静态方法可以访问静态数据成员,也可以更改它的值。 Abstract 关键字用于实现抽象。 静态方法不能在子类中被覆盖或实现。所以,把静态方法做抽象是没有用的。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2010-09-05
                          • 2012-12-03
                          • 2014-01-24
                          • 2010-12-25
                          • 2014-01-03
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-11-16
                          相关资源
                          最近更新 更多