Java, 102 95 89 88 78 byte
class A<T>{}class B<T>extends A<A<?super B<B<T>>>>{A<?super B<A>>a=new B<>();}
Questo termina con un StackOverflowError
che accade perché il sistema di risoluzione generico non può decidere una radice in base alla quale risolvere gli altri generici.
Crediti ove dovuti .
Che succede qui?
A<T>
è lì per avere un genitore di 1 lettera. È generico Avrei potuto usare List
, ma le importazioni e la ripetizione di 4 lettere sono troppo lunghe.
B<T>
dichiara un generico di base.
B extends A
è necessario disporre di una gerarchia tra B
e A
.
extends A<A>
crea un riferimento personale su A<T>
.
A<? super B>
attiva la ricerca di generici A<T>
B<B<T>>
crea un riferimento personale su B<T>
.
A<...> a=new B<>()
forza l'uso dei generici, anziché semplicemente la definizione di quelli, forzando la risoluzione durante la compilazione B
e non successivamente.
A<?super B
crea un auto-riferimento, quindi abbiamo sia un riferimento a un tipo che a un altro nei generici di A
.
B<A>
crea un auto-riferimento, quindi abbiamo sia un riferimento a un tipo che a un altro nei generici di B
.
Ora, il tipo A
ha tipo generici A
e B
, ma quale deve essere scelto? Dimentica te stesso, proviamo a risolvere B
. Ping.
Va bene, B
ha il tipo di generici A
e B
, ma quale deve essere scelto? Dimentica te stesso, proviamo a risolvere A
. Pong.
Questo tipo di ricorsione non può davvero essere evitato perché ci sono casi legittimi, come A<B<A<B<A<B<Object>>>>>>
ad esempio un oggetto JSON: List<Map<String,Map<String,List<Map<String,List<String>>>>>>
.
Risultato della compilazione
$ 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)
Sul mio sistema, la traccia dello stack si interrompe dopo aver mostrato 1024 linee, che in realtà sono le stesse 4 linee ripetute 256 volte, dimostrando così una ricorsione infinita. Ti risparmierò l'intera traccia.
risparmi
- 102 → 95 byte: sostituito
interface
+ implements
con class
+ extends
.
- 95 → 89 byte: sostituito
Long
con A
(due volte).
- 89 → 88 byte: operatore diamante usato (
new B<A>()
→ new B<>()
).
- 88 → 78 byte: ha spostato la dichiarazione della variabile in un membro della classe, grazie a VoteToClose .