Java: note that classes with entirely private constructors can't be subclassed

This commit is contained in:
Chris Smowton
2025-09-30 13:56:27 +01:00
parent fa8cbeeb44
commit f88daff45f
2 changed files with 24 additions and 2 deletions

View File

@@ -15,6 +15,10 @@
import java
private predicate hasASubclass(RefType t) {
exists(RefType sub | sub != t | sub.getAnAncestor() = t)
}
/**
* Holds if this type is either `final` or
* `private` and without subtypes.
@@ -24,7 +28,11 @@ private predicate cannotBeExtended(RefType t) {
or
// If the class is private, all possible subclasses are known.
t.isPrivate() and
not exists(RefType sub | sub != t | sub.getAnAncestor() = t)
not hasASubclass(t)
or
// If the class only has private constructors, all possible subclasses are known.
forex(Constructor c | c.getDeclaringType() = t | c.isPrivate()) and
not hasASubclass(t)
}
from MethodCall m, Constructor c, Class clazz

View File

@@ -30,4 +30,18 @@ public class Test {
}
}
}
public static class AllPrivateConstructors {
Thread myThread;
private AllPrivateConstructors() {
myThread = new Thread("myThread");
// OK - class cannot be extended outside this file, and is not in fact extended
myThread.start();
}
public static AllPrivateConstructors create() {
return new AllPrivateConstructors();
}
}
}