Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

294
Views
Genéricos de Java: ¿"T2 extiende T1" implica "T1 super T2"?

Si tengo un <T2 extends T1> genérico, ¿el compilador infiere T1 super T2 ?

Tengo una colección más compleja, que reduje al MWE a continuación. La colección se podrá fusionar con cualquier colección con elementos de cualquier subtipo.

Ahora me pregunto por qué no se acepta la llamada a forEach en merge . falla con

java.util.function.Consumer<java.util.Optional> no se puede convertir a java.util.function.Consumer<java.util.Optional<? súper T2>>

He representado las relaciones de tipos en el siguiente diagrama. En merge , T2 extiende T1 . La llamada a forEach se aplica al other objeto, por lo que el T1 de this se convierte en ? de other.forEach y el T2 de this.merge es el T1 de other . Por lo tanto, this ' T1 debe aceptarse como superior al T1 de other .

También probé public void merge(Group<? extends T> other) con el mismo resultado. Y public void merge(Group<T> other) no acepta tales colecciones con elementos de ningún subtipo de T1 .

MWE:

 class Group<T1> { public <T2 extends T1> void merge(Group<T2> other) { Consumer<Optional<T1>> task = t -> t.ifPresentOrElse(this::foo, this::bar); other.forEach(task); } public Collection<Optional<T1>> values() { return List.of(); } public void forEach(Consumer<Optional<? super T1>> consumer) { values().forEach(consumer); } private void foo(T1 t) {} private void bar() {} }

Relaciones:

 this.T1 -becomes-> other.forEach.? ^ | | super extends | | v this.merge.T2 -is-> other.T1
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Si tiene un Consumer<Optional<? super T1>> consumer entonces puede pasarlo (al método accept(T) ) un Optional<Object> porque Object es un supertipo de T1 .

Por otro lado, no puede pasar una tarea Optional<Object> a Consumer<Optional<T1>> task porque es posible que T1 no sea Object .

¿Entonces no puede asignar la Consumer<Optional<T1>> task al Consumer<Optional<? super T1>> consumer para evitar que a su consumidor se le pasen objetos de tipos que no espera.

over 4 years ago · Santiago Trujillo Report

0

Puedes resolver tu problema usando

 class Group<T1> { public <T2 extends T1> void merge(Group<T2> other) { Consumer<Optional<? extends T1>> task=t->t.ifPresentOrElse(this::foo, this::bar); other.forEach(task); } public Collection<Optional<T1>> values() { return List.of(); } public void forEach(Consumer<? super Optional<T1>> consumer) { values().forEach(consumer); } private void foo(T1 t) {} private void bar() {} }

Esta es una aplicación de la regla PECS .

Su task tratará Optional como un productor , por lo tanto, tiene que declarar Optional<? extends T1> para permitir que el opcional produzca subtipos de T1 . Sabemos que opcional siempre actuará como productor, pero el sistema de tipos genéricos de Java no tiene el concepto de clases que siempre actúan como productor o consumidor y necesita un ? extends T1 aquí.

forEach recibe un consumidor, incluso literalmente en el nombre de la interfaz, ¿entonces ? super … es la forma correcta de declarar que este consumidor puede ser un consumidor de supertipos de Optional<T1> . Esto no solo incluye Object , la superclase de Optional , sino también Optional<? extends T1> cuando T1 := T2 , como en la invocación dentro de merge , como Optional<? extends T1> es un supertipo de Optional<T2> .


Por supuesto, también podría resolver el problema simplemente usando

 Consumer<Optional<T2>> task = t -> t.ifPresentOrElse(this::foo, this::bar);

ya que esto solo requiere que foo acepte un argumento T2 , lo cual siempre hace, ya que T2 es un subtipo de T1 . Pero cambiar la firma de forEach para aumentar la flexibilidad siempre es un buen movimiento. Dado que es un método public , es posible que otras personas que llamen se beneficien de él.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!