<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:"Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:"\@Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{mso-style-priority:34;
margin-top:0cm;
margin-right:0cm;
margin-bottom:0cm;
margin-left:36.0pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
span.E-MailFormatvorlage17
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
@list l0
{mso-list-id:133958392;
mso-list-type:hybrid;
mso-list-template-ids:1668602470 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l0:level1
{mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l0:level2
{mso-level-number-format:alpha-lower;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l0:level3
{mso-level-number-format:roman-lower;
mso-level-tab-stop:none;
mso-level-number-position:right;
text-indent:-9.0pt;}
@list l0:level4
{mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l0:level5
{mso-level-number-format:alpha-lower;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l0:level6
{mso-level-number-format:roman-lower;
mso-level-tab-stop:none;
mso-level-number-position:right;
text-indent:-9.0pt;}
@list l0:level7
{mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l0:level8
{mso-level-number-format:alpha-lower;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l0:level9
{mso-level-number-format:roman-lower;
mso-level-tab-stop:none;
mso-level-number-position:right;
text-indent:-9.0pt;}
@list l1
{mso-list-id:1616256020;
mso-list-type:hybrid;
mso-list-template-ids:-786016588 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l1:level1
{mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l1:level2
{mso-level-number-format:alpha-lower;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l1:level3
{mso-level-number-format:roman-lower;
mso-level-tab-stop:none;
mso-level-number-position:right;
text-indent:-9.0pt;}
@list l1:level4
{mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l1:level5
{mso-level-number-format:alpha-lower;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l1:level6
{mso-level-number-format:roman-lower;
mso-level-tab-stop:none;
mso-level-number-position:right;
text-indent:-9.0pt;}
@list l1:level7
{mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l1:level8
{mso-level-number-format:alpha-lower;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-18.0pt;}
@list l1:level9
{mso-level-number-format:roman-lower;
mso-level-tab-stop:none;
mso-level-number-position:right;
text-indent:-9.0pt;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link="#0563C1" vlink="#954F72" style='word-wrap:break-word'><div class=WordSection1><p class=MsoNormal>I was once again writing some generic Java class and suddenly I stand there again, I could not get the type of T.<o:p></o:p></p><p class=MsoNormal>I’m sure this scenario sound familiar to every Java developer out there.<o:p></o:p></p><p class=MsoNormal>If you first stumble across this problem type erasure comes up as the culprit: “Type T is not there at runtime it is replaced with Object”<o:p></o:p></p><p class=MsoNormal>There are many solutions to this problem some hacky some require braking change to the generic system.<o:p></o:p></p><p class=MsoNormal>Now my idea was why don’t we trace back the types at compile time? I mean every generic class is constructed somewhere in 6 possible ways:<o:p></o:p></p><ol style='margin-top:0cm' start=1 type=1><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo2'>Foo<String> foo = new Foo<>();<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo2'>Foo<T> foo2 = new Foo<>();<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo2'>Foo foo3 = new Foo();<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo2'>Foo<?> foo4 = new Foo<>(); <o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo2'>Foo<? extends String> foo5 = new Foo<>();<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo2'>Foo<? super String> foo6 = new Foo<>();<o:p></o:p></li></ol><p class=MsoNormal>In case 1 we are already at our destination. The code the compiler gets contains the information we want. Why don’t we attach the type written in plain sight to the generic constructor?<o:p></o:p></p><p class=MsoNormal>Like an implicit Foo<String> foo = new Foo<>(java.lang.String.class); (which explicitly is a current way of solving this. Which is in my opinion pretty ugly.)<o:p></o:p></p><p class=MsoNormal>It would be syntactic sugar for the syntax above which spares the developers of repeating themselves. (just like <> does)<o:p></o:p></p><p class=MsoNormal>If the compiler would just use the information he is erasing to fill it into the constructor. The only thing changing would be that the constructor would take 1 additional hidden argument and since the argument is filled at compile time it would not brake any code.<o:p></o:p></p><p class=MsoNormal>In case 2 we are in some generic context like a nested class or a generic method. In both cases the actual type of T will be available. Such situations might require multiple passes to solve all dependencies. Then we can proceed like in 1.<o:p></o:p></p><p class=MsoNormal>In case 3 we are dealing with legacy code and the type is always object. (Foo foo = new Foo(java.lang.Object))<o:p></o:p></p><p class=MsoNormal>In case 4 we are dealing with an open type bound. The type is not constrained so we can only assume Object (Foo<?> foo = new Foo<>(java.lang.Object))<o:p></o:p></p><p class=MsoNormal>In case 5 we have a upper constrained type bound. We can assume any Object passing that bound Is a subclass of String (Foo<? extends String> foo = new Foo<>(java.lang.String))<o:p></o:p></p><p class=MsoNormal>In case 6 we have a lower constrained type bound. The Object passing this type bound could be Object. (Foo<? super String> foo = new Foo<>(java.lang.Object))<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>We would store the types at constructor or Method Invocation as arguments and then map them to the accessor T.class. This would allow type checking of T at runtime by tracing the real type at compile time.<o:p></o:p></p><p class=MsoNormal>Since the type of T.class would be Class<T> or Class<?<span style='font-size:10.5pt'>> we would not need to create a method or a class for each different version of the method or class like other languages do. <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.5pt'>I’m not quite sure how reflection is implemented but I’m sure there is a central invocation where the compiler could add the T.class argument. Of course we would need a way for reflection to specify the type T for this to work. We would simply need a method that is designed for generic classes like “<T> Constructor<T> getGenericConstructor(Class<?>[] typeParameterTypes, Class<?>… parameterTypes)” (could have a better signature).<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.5pt'>If the “getConstructor” is used on a generic class there would be a warning and the parameters would be set to Object (resulting in a raw object like any Objects generated by reflection currently are).<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Risks:<o:p></o:p></p><p class=MsoNormal>It would require the addition of n fields to any generic class or method where n stands for the number of generic arguments, which could result in performance and memory issues when adding this many new fields to the heap and stack. This issue could be reduced by only adding this mechanism when T.class or instanceof T are actually used in the context and would be skiped if the field is not used in the first place. Resulting in unchanged field count in all class files if the feature is used nowhere.<o:p></o:p></p><p class=MsoNormal>Another rist would be the obvious change in class files, since the hidden arguments need to be stored at compile time near the invoke of the method/constructor.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>This is just an idea based on my knowledge on generics in java. <o:p></o:p></p><p class=MsoNormal>Please feel free to correct any misconceptions in this idea and tell me if I missed something.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Great regards<o:p></o:p></p><p class=MsoNormal>RedIODev<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p></div></body></html>