The final qualifier specced out at https://github.com/openjdk/jdk/blob/jdk-16-ga/src/java.base/share/classes/java/lang/doc-files/ValueBased.html#L55 is:
<li>the class is final, and extends either <code>Object</code> or a hierarchy of
abstract classes that declare no instance fields or instance initializers
and whose constructors are empty.</li>
This means that a simple case:
public abstract class Base {
protected final int f1;
protected Base(int f1) { this.f1 = f1; }
}
public final class Child extends Base {
private final int f2;
public static Child create(int f1, int f2) { return new Child(f1, f2); }
private Child(int f1, int f2) { super(f1); this.f2 = f2; }
// equals, hashCode over f1, f2
}
while the "inlined" version would be VBC:
public final class Inlined {
private final int f1;
private final int f2;
public static Inlined create(int f1, int f2) { return new Inlined(f1, f2); }
private Inlined(int f1, int f2) { this.f1 = f1; this.f2 = f2; }
// equals, hashCode over f1, f2
}
What was the rationale for making such a harsh restriction to be a VBC, instead of relaxing it towards "all instance fields (including the ones from parent class) need to participate in equals/hashCode etc." ?