为什么一个Java类不能同时被声明为抽象和最终的?

10
假设我有一个实用类,其中只包含静态方法和变量。例如:
public abstract final class StringUtils
{
    public static final String NEW_LINE = System.getProperty("line.separator");

    public static boolean isNotNullOrSpace(final String string)
    {
        return !(string == null || string.length() < 1 || string.trim().length() < 1);
    }
}

在这种情况下,将该类设置为抽象且final是有意义的。抽象是因为创建此类的对象将毫无用处,因为所有方法都是静态可访问的。final是因为派生类不能从该类继承任何内容,因为它没有任何非静态成员。
C#允许对这些类使用static修饰符。为什么Java不支持这样做呢?

2
由于语言规范不同,所以结果为 true - Suresh Atta
阅读此内容:https://dev59.com/7nA65IYBdhLWcg3w4CwL - Bart Friederichs
谢谢Bart。你提供了正确的答案。我可以拥有一个带有私有构造函数的最终类。 - PC.
你混淆了 final 的含义;final 相当于 C# 中的 sealed,而不是 static - Pharap
public final abstract class ChuckNorris extends ChuckNorris {} - tar
你可能会喜欢Scala: https://www.scala-lang.org/api/2.12.1/scala/Double.html - Alonso del Arte
7个回答

19
无法实现,因为Java编程语言规范说明:
声明抽象类类型时,如果无法创建子类实现其所有抽象方法,则会导致编译时错误 [1]
除此之外,抽象 final 类型没有本质上的不合逻辑性——单词“abstract”通常与“concrete”相对应,意味着不能直接存在某个类型的实例。

同时:如果一个类被声明为final和abstract,那么在编译时会产生错误,因为这样的类的实现永远无法完成(8.1.1.2)。 - Turkhan Badalov

13

一个final类无法被扩展,而一个abstract类需要被扩展后才能实例化。因此,final abstract类将是一个逻辑矛盾。

如果你的类只有static方法,也许你应该将构造函数定义为private,从而隐藏它。

private StringUtils() {
}

10
“抽象类”不需要被继承,它只是无法实例化。 - Bart Friederichs
8
我知道这是面向对象语言的基本概念。但在我的例子中并没有矛盾之处。我不想扩展或实例化我的类。 - PC.
2
对我而言,抽象类只有在添加了一些抽象方法时才有意义。如果你不想让你的类被实例化,应该考虑将其默认构造函数定义为私有。 - ssantos
或者,如果将类定义为抽象和最终的唯一需求是为了防止任何人覆盖您的方法实现,那么您可以尝试仅将该方法标记为final。 - Praba
3
为什么一个既不能被实例化(抽象类),又不能被扩展(final类)是矛盾的,请详细阐述。Java不允许使用一个关键字同时声明这两个特性,但这并不意味着它不可能存在!通过使用私有构造函数和纪律来绕过这一限制在现实中仍然是常见的做法。 - Deduplicator

1

除了主观原因外,您可以通过使类抽象并使所有方法最终来实现相同的目标。例如:

public abstract class MyClass {
    …
    public final static void myMethod1() {
        …
    }

    public final static void myMethod2() {
        …
    }
}

编译器会检查这个并在你试图实例化MyClass对象时给出错误,同时当任何子类扩展MyClass时也不可能覆盖final方法。

0

当我们将一个类声明为抽象类时,它不能被实例化。当我们将一个类声明为final时,它不能被继承。要实现抽象类中的方法,需要继承该类。但是如果我们将一个类声明为final,则该类无法被继承。因此,我们不能将一个类同时声明为抽象类和final。


0
由于某些特定原因,我们无法在抽象类中使用 final 关键字。
  1. 如果我们定义了 abstract final,则无法扩展它。
  2. 抽象类的意思是要被其他类继承,并提供非具体方法的实现。
  3. 如果我们将抽象类定义为 final,则会在编译时出现错误。

-1
一个方法永远不能同时被标记为抽象和最终,或者抽象和私有。想想看——抽象方法必须被实现(这基本上意味着被子类覆盖),而最终和私有方法永远不能被子类覆盖。或者换句话说,抽象标记意味着超类不知道子类在该方法中应该如何行事,而最终标记意味着超类了解所有子类(无论它们在继承树上多远)在该方法中应该如何行事。 抽象和最终修饰符几乎是相反的。因为私有方法甚至不能被子类看到(更不用说继承了),所以它们也不能被覆盖,因此它们也不能被标记为抽象。

1
问题是指一个最终的抽象类,而不是一个方法。 - White_King

-1
在Java中,无法创建抽象类的实例,我们只能拥有抽象类类型的引用。因此,如果我们将抽象类定义为final,则无法对其进行扩展。 抽象和final是互斥的概念。 这就是为什么当您尝试在Java中将抽象类定义为final时,Java编译器会抛出编译时错误的原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接