<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">This is a good example of a
"you can, but you probably shouldn't" language feature. The
power-to-weight ratio isn't favorable; it is a lot of new
machinery and concept to move the ball forward a small amount.
And as soon as the ball is moved forward by that amount, we will
immediately be confronted by the next thing we can't do, and the
solutions are likely to be an increasingly complex sequence of
worse power-to-weight ratio ideas. (Careful observers of Java
history might note that this phenomenon is especially evident in
any proposal surrounding annotations.)<br>
<br>
As Michael K pointed out, other languages have explored more
general, but more suitable, answers here; what you're looking
for is a witness to conformance to a type class. (Our friends
in C# have pursued something similar through abstract statics;
for various reasons, that's less of a good match for Java than
for C#.) This is not a small ask; its significant new
complexity, but the power gained is much greater. If we were to
choose to invest in solving problems like this one, that would
likely be the path, but this is a big lift and we have other big
things on our plate right now. <br>
<br>
As a general note, while it is fun to imagine new language
features, language design needs to be a holistic process. If we
did a hundred "point" features like this, what are the chances
that the whole would hold together? If we did this feature,
what other potential feature directions are we implicitly
foreclosing on? These are the questions we address ourselves to
when choosing what features to consider and not. <br>
<br>
</font></font><br>
<div class="moz-cite-prefix">On 1/25/2023 2:03 AM, Red IO wrote:<br>
</div>
<blockquote type="cite" cite="mid:CABKyW1sDWVmLMHiaWDcuY=RT1PZcupzcgPuB1fs3xKVvVC4x7A@mail.gmail.com">
<div dir="auto">
<div dir="auto">Summary</div>
<div dir="auto">-------</div>
<div dir="auto"><br>
</div>
<div dir="auto">Enable a parameterized class to constrain the
parameterized type to be constructible with a given list of
parameters.</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">Motivation</div>
<div dir="auto">----------</div>
<div dir="auto"><br>
</div>
<div dir="auto">It is possible since JDK 8 to get a constructor
(method) reference of an object. This allowed for the creation
of an unknown class with a known constructor reference. But
currently the only way to obtain such reference is at call
site like this:</div>
<div dir="auto"><span style="white-space:pre"> </span></div>
<div dir="auto"><span style="white-space:pre"> </span>Box<String>
stringBox = new Box<>(String::new);</div>
<div dir="auto"><br>
</div>
<div dir="auto">It is inconvenient for the user to supply the
the reference themselves and can confuse them as the type of
the parameter is something like Supplier<String> which
doesn't require the pased reference to be a constructor. </div>
<div dir="auto">It also clutters api's like "toArray" which
requires an IntFunction to be type safe. </div>
<div dir="auto"><br>
</div>
<div dir="auto">Description</div>
<div dir="auto">-----------</div>
<div dir="auto"><br>
</div>
<div dir="auto">ConstructorInterface</div>
<div dir="auto">A ConstructorInterface is a special kind of
interface similar to a FunctionalInterface. It also has
similar constraints. It only allows abstract constructors and
no other abstract methods. It can declare multiple
constructors though. The definition of such interface would
look similar to this:</div>
<div dir="auto"><br>
</div>
<div dir="auto"><span style="white-space:pre"> </span>@ConstructorInterface
//optional validation like FunctionalInterfaces</div>
<div dir="auto"><span style="white-space:pre"> </span>public
interface DefaultConstructible {</div>
<div dir="auto"><span style="white-space:pre"> </span>new();</div>
<div dir="auto"><span style="white-space:pre"> </span>new(char[]
chars);</div>
<div dir="auto"><span style="white-space:pre"> </span>}</div>
<div dir="auto"><br>
</div>
<div dir="auto">A parameterized type could declare this
interface as a type bound for its parameter and therefore
enabling it to be constructed safely. Like this:</div>
<div dir="auto"><span style="white-space:pre"> </span>public
class Box<E extends DefaultConstructible> {</div>
<div dir="auto"><span style="white-space:pre"> </span>public
Box() {</div>
<div dir="auto"><span style="white-space:pre"> </span>E
newElement = new E();</div>
<div dir="auto"><span style="white-space:pre"> </span>}</div>
<div dir="auto"><span style="white-space:pre"> </span>}</div>
<div dir="auto">The containing type is not forced to implement
the ContructorInterface explicitly. It is implicitly
implemented if the required constructor(s) is(are) present.</div>
<div dir="auto"><span style="white-space:pre"> </span>public
static void main(String[] args) {</div>
<div dir="auto"><span style="white-space:pre"> </span>Box<String>
stringBox = new Box<>(); //compiles because String has
the required constructors.</div>
<div dir="auto"><span style="white-space:pre"> </span>Box<java.sql.Date>
dateBox new Box<>(); error: java.sql.Data does not
satisfy the type bound DefaultConstructible</div>
<div dir="auto"><span style="white-space:pre"> </span>}</div>
<div dir="auto">The interface might not be implemented by any
class, since it doesn't follow the inheritance rule that
extending classes of those who implement it also implement it.
This requirement comes from the fact that extending classes do
not necessarily need to have the same constructor signature
and therefore don't qualify the requirements for the
interface. Another option would be that extending classes of
classes that implement a constructor interface explicitly are
also required to supply the necessary constructors.</div>
<div dir="auto"><br>
</div>
<div dir="auto">class Foo implements DefaultConstructable {</div>
<div dir="auto"><span style="white-space:pre"> </span>//both
required by the interface </div>
<div dir="auto"><span style="white-space:pre"> </span>public
Foo() {} </div>
<div dir="auto"><span style="white-space:pre"> </span>public
Foo(char[] chars) {} </div>
<div dir="auto">} </div>
<div dir="auto"><br>
</div>
<div dir="auto">class Bar extends Foo {</div>
<div dir="auto"><span style="white-space:pre"> </span>//the
requirement for the required constructors is passed down. </div>
<div dir="auto"><span style="white-space:pre"> </span>public
Bar() {} </div>
<div dir="auto"><span style="white-space:pre"> </span>public
Bar(char[] chars) {} </div>
<div dir="auto">} </div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">public static <T extends Foo> T createT()
{</div>
<div dir="auto"><span style="white-space:pre"> </span>return new
T();</div>
<div dir="auto">} </div>
<div dir="auto"><br>
</div>
<div dir="auto">public <T extends Foo> T wrapper() {</div>
<div dir="auto"><span style="white-space:pre"> </span>return
createT();</div>
<div dir="auto">} </div>
<div dir="auto">This would technically work but would require a
lot of static analysis to find the real type of T to call its
constructor. </div>
<div dir="auto">Restricting the use of "new T()" to type
parameters that specify a constructor interface directly and
only allow those to be resolved with a concrete type rather
than another type parameter. </div>
<div dir="auto"><br>
</div>
<div dir="auto">Alternatives</div>
<div dir="auto">------------</div>
<div dir="auto">An alternative would be to introduce new syntax
to restrict the ability of certain constructors on a parameter
type. Like c# does (but only for the default constructor) :</div>
<div dir="auto">public static T foo<T>() where T: new() {</div>
<div dir="auto"><span style="white-space:pre"> </span>return
new T();</div>
<div dir="auto">} </div>
<div dir="auto">In java:</div>
<div dir="auto">public static <T extends new()> T foo() {</div>
<div dir="auto"><span style="white-space:pre"> </span>return
new T();</div>
<div dir="auto">} </div>
<div dir="auto">The downside of this approach is obviously the
introduction of new syntax rather than reusing the
interface/inheritance syntax. </div>
<div dir="auto"><br>
</div>
<div dir="auto">Another alternative to this approach could be to
implement static abstract methods. This would allow an
interface to mandate a static Factory Method. The downside of
this approach is that it requires the parameter class to
actually implement the interface and the concept of type
erasure would need to be addressed for static abstract methods
to work. In contrast the ConstructorInterface enables every
class that matches its contract to pass the type bound.</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">Risks and Assumptions</div>
<div dir="auto">---------------------</div>
<div dir="auto"><br>
</div>
<div dir="auto">As mentioned before the restriction the
interface is giving on a type bound is different to normal
interfaces, it restricts by its containing abstract
constructors not by the type itself. It also makes use of the
new operator on type variables. </div>
<div dir="auto"><br>
</div>
</div>
</blockquote>
<br>
</body>
</html>