Java, 102 95 89 88 78 octets
class A<T>{}class B<T>extends A<A<?super B<B<T>>>>{A<?super B<A>>a=new B<>();}
Cela se termine par un StackOverflowError
qui se produit car le système de résolution générique ne peut pas décider d'une racine contre laquelle résoudre les autres génériques.
Crédits dus .
Que se passe t-il ici?
A<T>
est juste là pour avoir un parent d'une lettre. C'est générique. J'aurais pu l'utiliser List
, mais l'importation et la répétition de 4 lettres sont trop longues.
B<T>
déclare un générique de base.
B extends A
est nécessaire d'avoir une hiérarchie entre B
et A
.
extends A<A>
crée une auto référence sur A<T>
.
A<? super B>
déclenche la recherche de génériques sur A<T>
B<B<T>>
crée une auto-référence sur B<T>
.
A<...> a=new B<>()
force l'utilisation des génériques, au lieu de simplement la définition de ceux-ci, forçant la résolution lors de la compilation B
, et non après.
A<?super B
crée une non-référence de soi, nous avons donc à la fois une référence à un type et à un autre dans les génériques de A
.
B<A>
crée une non-référence de soi, nous avons donc à la fois une référence à un type et à un autre dans les génériques de B
.
Maintenant, le type A
a le type générique A
et B
, mais lequel doit être choisi? Oubliez vous-même, essayons de résoudre B
. Ping
D'accord, les B
génériques sont-ils de type A
et B
, mais lequel doit être choisi? Oubliez vous-même, essayons de résoudre A
. Pong
Ce genre de récursion ne peut pas vraiment être évité car il y a des cas légitimes comme A<B<A<B<A<B<Object>>>>>>
: par exemple un objet JSON: List<Map<String,Map<String,List<Map<String,List<String>>>>>>
.
Résultat de la compilation
$ javac NoCompile.java
The system is out of resources.
Consult the following stack trace for details.
java.lang.StackOverflowError
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3260)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2587)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2579)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:554)
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3260)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2592)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2579)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:554)
Sur mon système, la trace de la pile s’arrête après avoir affiché 1024 lignes, qui sont en fait les 4 mêmes lignes répétées 256 fois, ce qui prouve une récursion infinie. Je vous épargne toute cette trace.
Des économies
- 102 → 95 octets: remplacé
interface
+ implements
par class
+ extends
.
- 95 → 89 octets: remplacé
Long
par A
(deux fois).
- 89 → 88 octets: opérateur diamant utilisé (
new B<A>()
→ new B<>()
).
- 88 → 78 octets: déplacé la déclaration de variable vers un membre de la classe, grâce à VoteToClose .