英文:
Modifiers used for Classes in Java
问题
我知道Java中的类只使用"public"和"default(没有修饰符)",当您尝试将类声明为"private"或"protected"时,它会产生编译错误,这对我来说是有道理的。
但是,为什么这个页面说"类可以有上述4个修饰符中的任何修饰符"呢?
有人可以解释一下吗?
英文:
I am aware that classes in Java only use "public" and "default (no modifier)" and when you try to declare a class as "private" or "protected", it gives out a compilation error and it makes sense to me.
But then, why does this page says "classes can have any modifiers out of the 4 mentioned above".
Can someone please explain this to me?
答案1
得分: 2
有更多合法的组合。只是为了好玩,我写了一个小脚本来生成所有可能的组合,然后我删除了导致编译错误的组合,这些是我剩下的合法组合:
class Test {
// ... 代码 ...
}
因此,如果包括 Java 14 的实验性 record
,总共有 112 种合法的组合;或者分开计算,record
有 32 种合法的修饰符组合,interface
也有 32 种,仅考虑类的话则有 48 种。
最明显的非法组合有:
abstract
和final
:abstract
表示“包含未实现的成员,必须由子类实现”,而final
表示“不能被子类化”,因此,一个需要子类化但又不能有子类的类是没有意义的。- 基于同样的原因,不能有被声明为
final
的interface
:一个interface
在本质上是完全抽象的,因为它应该由实现它的class
来实现。 - 相反地,
record
是隐式地final
,因此不能是abstract
的。
英文:
There are a lot more legal combinations. Just for fun, I wrote a little script which generates all possible combinations, then I deleted the ones that caused compilation errors, and these are the legal ones I was left with:
class Test {
class Default__ConcreteInstanceVirtualLoosefp_Class {}
interface Default__ConcreteInstanceVirtualLoosefp_Interface {}
record Default__ConcreteInstanceVirtualLoosefp_Record() {}
strictfp class Default__ConcreteInstanceVirtualStrictfpClass {}
strictfp interface Default__ConcreteInstanceVirtualStrictfpInterface {}
strictfp record Default__ConcreteInstanceVirtualStrictfpRecord() {}
final class Default__ConcreteInstanceFinal__Loosefp_Class {}
final record Default__ConcreteInstanceFinal__Loosefp_Record() {}
final strictfp class Default__ConcreteInstanceFinal__StrictfpClass {}
final strictfp record Default__ConcreteInstanceFinal__StrictfpRecord() {}
static class Default__ConcreteStatic__VirtualLoosefp_Class {}
static interface Default__ConcreteStatic__VirtualLoosefp_Interface {}
static record Default__ConcreteStatic__VirtualLoosefp_Record() {}
static strictfp class Default__ConcreteStatic__VirtualStrictfpClass {}
static strictfp interface Default__ConcreteStatic__VirtualStrictfpInterface {}
static strictfp record Default__ConcreteStatic__VirtualStrictfpRecord() {}
static final class Default__ConcreteStatic__Final__Loosefp_Class {}
static final record Default__ConcreteStatic__Final__Loosefp_Record() {}
static final strictfp class Default__ConcreteStatic__Final__StrictfpClass {}
static final strictfp record Default__ConcreteStatic__Final__StrictfpRecord() {}
abstract class Default__AbstractInstanceVirtualLoosefp_Class {}
abstract interface Default__AbstractInstanceVirtualLoosefp_Interface {}
abstract strictfp class Default__AbstractInstanceVirtualStrictfpClass {}
abstract strictfp interface Default__AbstractInstanceVirtualStrictfpInterface {}
abstract static class Default__AbstractStatic__VirtualLoosefp_Class {}
abstract static interface Default__AbstractStatic__VirtualLoosefp_Interface {}
abstract static strictfp class Default__AbstractStatic__VirtualStrictfpClass {}
abstract static strictfp interface Default__AbstractStatic__VirtualStrictfpInterface {}
public class Public___ConcreteInstanceVirtualLoosefp_Class {}
public interface Public___ConcreteInstanceVirtualLoosefp_Interface {}
public record Public___ConcreteInstanceVirtualLoosefp_Record() {}
public strictfp class Public___ConcreteInstanceVirtualStrictfpClass {}
public strictfp interface Public___ConcreteInstanceVirtualStrictfpInterface {}
public strictfp record Public___ConcreteInstanceVirtualStrictfpRecord() {}
public final class Public___ConcreteInstanceFinal__Loosefp_Class {}
public final record Public___ConcreteInstanceFinal__Loosefp_Record() {}
public final strictfp class Public___ConcreteInstanceFinal__StrictfpClass {}
public final strictfp record Public___ConcreteInstanceFinal__StrictfpRecord() {}
public static class Public___ConcreteStatic__VirtualLoosefp_Class {}
public static interface Public___ConcreteStatic__VirtualLoosefp_Interface {}
public static record Public___ConcreteStatic__VirtualLoosefp_Record() {}
public static strictfp class Public___ConcreteStatic__VirtualStrictfpClass {}
public static strictfp interface Public___ConcreteStatic__VirtualStrictfpInterface {}
public static strictfp record Public___ConcreteStatic__VirtualStrictfpRecord() {}
public static final class Public___ConcreteStatic__Final__Loosefp_Class {}
public static final record Public___ConcreteStatic__Final__Loosefp_Record() {}
public static final strictfp class Public___ConcreteStatic__Final__StrictfpClass {}
public static final strictfp record Public___ConcreteStatic__Final__StrictfpRecord() {}
public abstract class Public___AbstractInstanceVirtualLoosefp_Class {}
public abstract interface Public___AbstractInstanceVirtualLoosefp_Interface {}
public abstract strictfp class Public___AbstractInstanceVirtualStrictfpClass {}
public abstract strictfp interface Public___AbstractInstanceVirtualStrictfpInterface {}
public abstract static class Public___AbstractStatic__VirtualLoosefp_Class {}
public abstract static interface Public___AbstractStatic__VirtualLoosefp_Interface {}
public abstract static strictfp class Public___AbstractStatic__VirtualStrictfpClass {}
public abstract static strictfp interface Public___AbstractStatic__VirtualStrictfpInterface {}
private class Private__ConcreteInstanceVirtualLoosefp_Class {}
private interface Private__ConcreteInstanceVirtualLoosefp_Interface {}
private record Private__ConcreteInstanceVirtualLoosefp_Record() {}
private strictfp class Private__ConcreteInstanceVirtualStrictfpClass {}
private strictfp interface Private__ConcreteInstanceVirtualStrictfpInterface {}
private strictfp record Private__ConcreteInstanceVirtualStrictfpRecord() {}
private final class Private__ConcreteInstanceFinal__Loosefp_Class {}
private final record Private__ConcreteInstanceFinal__Loosefp_Record() {}
private final strictfp class Private__ConcreteInstanceFinal__StrictfpClass {}
private final strictfp record Private__ConcreteInstanceFinal__StrictfpRecord() {}
private static class Private__ConcreteStatic__VirtualLoosefp_Class {}
private static interface Private__ConcreteStatic__VirtualLoosefp_Interface {}
private static record Private__ConcreteStatic__VirtualLoosefp_Record() {}
private static strictfp class Private__ConcreteStatic__VirtualStrictfpClass {}
private static strictfp interface Private__ConcreteStatic__VirtualStrictfpInterface {}
private static strictfp record Private__ConcreteStatic__VirtualStrictfpRecord() {}
private static final class Private__ConcreteStatic__Final__Loosefp_Class {}
private static final record Private__ConcreteStatic__Final__Loosefp_Record() {}
private static final strictfp class Private__ConcreteStatic__Final__StrictfpClass {}
private static final strictfp record Private__ConcreteStatic__Final__StrictfpRecord() {}
private abstract class Private__AbstractInstanceVirtualLoosefp_Class {}
private abstract interface Private__AbstractInstanceVirtualLoosefp_Interface {}
private abstract strictfp class Private__AbstractInstanceVirtualStrictfpClass {}
private abstract strictfp interface Private__AbstractInstanceVirtualStrictfpInterface {}
private abstract static class Private__AbstractStatic__VirtualLoosefp_Class {}
private abstract static interface Private__AbstractStatic__VirtualLoosefp_Interface {}
private abstract static strictfp class Private__AbstractStatic__VirtualStrictfpClass {}
private abstract static strictfp interface Private__AbstractStatic__VirtualStrictfpInterface {}
protected class ProtectedConcreteInstanceVirtualLoosefp_Class {}
protected interface ProtectedConcreteInstanceVirtualLoosefp_Interface {}
protected record ProtectedConcreteInstanceVirtualLoosefp_Record() {}
protected strictfp class ProtectedConcreteInstanceVirtualStrictfpClass {}
protected strictfp interface ProtectedConcreteInstanceVirtualStrictfpInterface {}
protected strictfp record ProtectedConcreteInstanceVirtualStrictfpRecord() {}
protected final class ProtectedConcreteInstanceFinal__Loosefp_Class {}
protected final record ProtectedConcreteInstanceFinal__Loosefp_Record() {}
protected final strictfp class ProtectedConcreteInstanceFinal__StrictfpClass {}
protected final strictfp record ProtectedConcreteInstanceFinal__StrictfpRecord() {}
protected static class ProtectedConcreteStatic__VirtualLoosefp_Class {}
protected static interface ProtectedConcreteStatic__VirtualLoosefp_Interface {}
protected static record ProtectedConcreteStatic__VirtualLoosefp_Record() {}
protected static strictfp class ProtectedConcreteStatic__VirtualStrictfpClass {}
protected static strictfp interface ProtectedConcreteStatic__VirtualStrictfpInterface {}
protected static strictfp record ProtectedConcreteStatic__VirtualStrictfpRecord() {}
protected static final class ProtectedConcreteStatic__Final__Loosefp_Class {}
protected static final record ProtectedConcreteStatic__Final__Loosefp_Record() {}
protected static final strictfp class ProtectedConcreteStatic__Final__StrictfpClass {}
protected static final strictfp record ProtectedConcreteStatic__Final__StrictfpRecord() {}
protected abstract class ProtectedAbstractInstanceVirtualLoosefp_Class {}
protected abstract interface ProtectedAbstractInstanceVirtualLoosefp_Interface {}
protected abstract strictfp class ProtectedAbstractInstanceVirtualStrictfpClass {}
protected abstract strictfp interface ProtectedAbstractInstanceVirtualStrictfpInterface {}
protected abstract static class ProtectedAbstractStatic__VirtualLoosefp_Class {}
protected abstract static interface ProtectedAbstractStatic__VirtualLoosefp_Interface {}
protected abstract static strictfp class ProtectedAbstractStatic__VirtualStrictfpClass {}
protected abstract static strictfp interface ProtectedAbstractStatic__VirtualStrictfpInterface {}
}
So, there are a total of 112 legal combinations if you include Java 14 experimental record
s, or counted separately, 32 legal combinations of modifiers for record
s, 32 as well for interface
s, and 48 if you only count classes.
The most obvious illegal combinations are:
abstract
andfinal
:abstract
means "contains un-implemented members that must be implemented by subclasses" andfinal
means "cannot be subclassed", so clearly, a class that requires subclassing but cannot have subclasses doesn't make sense.- For the same reason, you can't have
interface
s that arefinal
: aninterface
is implicitly fullyabstract
, since it is supposed to be implemented by its implementingclass
es. - And conversely,
record
s are implicitlyfinal
, so they cannot beabstract
.
答案2
得分: 1
就像文本所说:
并非所有的修饰符都可以用在所有的类上。
但是,例如,内部类 可以是私有的/受保护的。
public class Foo {
private Bar bar = new Bar(42);
private static class Bar {
private int answer;
Bar(int theAnswer) {
this.answer = theAnswer;
}
}
}
这在某些持有数据的 POJO 或者某些内部实现细节上是有意义的,您可能希望对其进行封装,但不泄露出来(甚至可以在受保护的情况下进行重写)。
英文:
Like the text says:
> Not all modifiers are allowed on all classes
But, e.g., inner classes can be private/protected.
public class Foo {
private Bar bar = new Bar(42);
private static class Bar {
private int answer;
Bar(int theAnswer) {
this.answer = theAnswer;
}
}
}
This can make sense for some POJO holding data, or some internal implementation detail that you want to encapsulate, but not leak out (and you can even override if it's protected).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论