简体   繁体   中英

Why is public abstract final class syntactically invalid?

I have a class foo that is no more than a placeholder for a few static functions and variables. A bit like a namespace in C++.

Creating an instance of foo and inheriting from foo are therefore meaningless.

So I'm tempted to write public abstract final class foo . But Java dislikes that. I can do it in C++ with a pure virtual function and final , but why can't I do the equivalent in Java? What's so wrong with my design?

Update: I'm getting heavily downvoted on this (-4 at the time of writing) so I obviously haven't been clear enough. Here's the specific use case. It's a load of severity level codes for error logging that's used in a JNI and supporting C library:

public abstract class Severity
{ 
    public static final int TRACE = 0x00000001;

    public static final int INFORMATION = 0x00000002;

    public static final int WARNING = 0x00000003;

    public static final int ERROR = 0x00000004;

    public static final int CRITICAL_ERROR = 0x00000005;

    public static final int OFF = 0x00000006;
}

So it's almost like an enumerator but the JNI and C library restrictions mean that would be suboptimal. Making this abstract and final seems perfectly reasonable to me, and, as I've said, the equivalent is permissible in C++.

Because abstract says that is has some unimplemented methods and final states that it cannot be inherited from. That means this class can never be useful. If your class does not contain any instance methods, just make it final and you're done :). No need to mark it abstract because it isn't. You probably also want to make the constructor private so no one can instantiate it.

See for example the JLS 8.1.1.1 :

8.1.1.1. abstract Classes

An abstract class is a class that is incomplete, or to be considered incomplete.

[...]

and JLS 8.1.1.2

8.1.1.2. final Classes

[...]

It is a compile-time error if a class is declared both final and abstract, because the implementation of such a class could never be completed (§8.1.1.1).

You could use empty enum instead class

public enum Severity
{ ;
    public static final int TRACE = 0x00000001;

    public static final int INFORMATION = 0x00000002;

    public static final int WARNING = 0x00000003;

    public static final int ERROR = 0x00000004;

    public static final int CRITICAL_ERROR = 0x00000005;

    public static final int OFF = 0x00000006;
}

you cant instantiate enum, you can't extend enum. hence it gives you all what you want

In Java, if you want to write a class that can neither be instantiated nor extended, use a private constructor

private MyClass() {}

Arguably there should be a way of specifying this in the class declaration, but there isn't.

In a one liner when you say a class as final then it means that class can't be extended, an abstract class needs to be extended. So its a logical contradiction.

EDIT:

The edit seems fine and your code looks good. You cannot instantiate Severity because of it abstract so you can have the variables as final.

abstract and final are mutually-exclusive concepts in Java. When you declare a class to be abstract , you are saying "I intend for this class to be subclassed by one or more other classes". When you declare it final , you're saying "I intend that this class cannot be extended by any class". As such, an abstract final class makes no sense from a Java perspective - so the language doesn't permit you to do it in the first place.

For your specific use-case, why not simply use an enum ?

public enum Severity {
    TRACE,
    INFORMATION,
    WARNING,
    ERROR,
    CRITICAL_ERROR,
    OFF;
}

You can always include numeric values for each enum element if you wish.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM