Reputation: 27
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?
Upvotes: 0
Views: 203
Reputation: 369428
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
and final
: abstract
means "contains un-implemented members that must be implemented by subclasses" and final
means "cannot be subclassed", so clearly, a class that requires subclassing but cannot have subclasses doesn't make sense.interface
s that are final
: an interface
is implicitly fully abstract
, since it is supposed to be implemented by its implementing class
es.record
s are implicitly final
, so they cannot be abstract
.Upvotes: 2
Reputation: 3743
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).
Upvotes: 1