<div dir="ltr">Hello!<div><br></div><div>Using generic varargs in non-final (in particular, interface) methods is still painful in Java, as one cannot annotate them as @SafeVarargs, so every callsite has an unwanted warning about generic array creation.</div><div><br></div><div>Closed sealed hierarchies allow to control all the implementations and explicitly mark all of them with @SafeVarargs. In this case, we could improve the situation if we allow marking the parent method as well.</div><div><br></div><div>E.g., consider the following code:</div><div><br></div><div>import java.util.Optional;<br><br>public class Main {<br>  public sealed interface Service permits ServiceImpl {<br>    @SuppressWarnings("unchecked") // cannot use @SafeVarargs here<br>    <W> void process(Optional<W>... params);<br>  }<br><br>  public static final class ServiceImpl implements Service {<br>    @SafeVarargs<br>    @Override<br>    public final <W> void process(Optional<W>... params) {<br>      for (Optional<W> param : params) {<br>        param.ifPresent(System.out::println);<br>      }<br>    }<br>  }<br><br>  void test(Service service, ServiceImpl serviceImpl) {<br>    // Warning: warning: [unchecked] unchecked generic array creation<br>    service.process(Optional.of(1), Optional.of(2), Optional.empty());<br>    // No warning thanks to SafeVarargs<br>    serviceImpl.process(Optional.of(1), Optional.of(2), Optional.empty());<br>  }<br>}<br></div><div><br></div><div>Here, we cannot use the Service::process method without an unchecked warning about generic array creation. Which is bad, as we have closed hierarchy and explicitly marked all the implementations as safe.</div><div><br></div><div>To improve the situation, I suggest the following additions to the Java language specification:</div><div><br></div><div>1. Allow marking non-final, non-private methods (abstract or not) with @SafeVarargs if they are declared inside a sealed or final (*) class / interface</div><div>2. If a vararg method overrides / implements another vararg method marked with SafeVarargs, then the overriding method must be marked with SafeVarargs as well; otherwise a compilation error occurs.</div><div>3. If a non-sealed class / interface is declared, all its visible methods are examined. If any of them is overridable and marked with SafeVarargs, then a compilation error occurs.</div><div><br></div><div>(*) Extending this to final classes is not quite necessary, but it looks logical addition and allows to omit final method modifier inside final class.</div><div><br></div><div>With these rules, the code above could be rewritten as:</div><div><br></div><div>import java.util.Optional;<br><br>public class Main {<br>  public sealed interface Service permits ServiceImpl {<br>    @SafeVarargs // now allowed, as we are inside sealed interface<br>    <W> void process(Optional<W>... params);<br>  }<br><br>  public static final class ServiceImpl implements Service {<br>    @SafeVarargs // must be specified<br>    @Override<br>    public <W> void process(Optional<W>... params) { // possible to omit 'final' here<br>      for (Optional<W> param : params) {<br>        param.ifPresent(System.out::println);<br>      }<br>    }<br>  }<br><br>  void test(Service service, ServiceImpl serviceImpl) {<br>    // No warning anymore thanks to SafeVarargs<br>    service.process(Optional.of(1), Optional.of(2), Optional.empty());<br>    // No warning thanks to SafeVarargs<br>    serviceImpl.process(Optional.of(1), Optional.of(2), Optional.empty());<br>  }<br>}<br></div><div><br></div><div>What do you think?</div><div><br></div><div>With best regards,</div><div>Tagir Valeev</div></div>