• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Devaka Cooray
  • Ron McLeod
  • Jeanne Boyarsky
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Piet Souris
  • Carey Brown
  • Tim Holloway
Bartenders:
  • Martijn Verburg
  • Frits Walraven
  • Himai Minh

Generics, Understanding Complex Expressions. Are they necessary to understand ?

 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


I'm trying to understand some complex generics expressions. For example, what does the expression above mean?
 
Saloon Keeper
Posts: 14514
325
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
These are not expressions but declarations. Expressions are parts of a statement that return a value. In programming, it's important to use the correct terminology.

First you declare an interface Foo with a generic type parameter T. We say "Foo of T".

Secondly you declare a class FooImpl with a generic type parameter U. U has an upper type boundary of Foo<? super U>. We say "FooImpl of U, where U is some subtype of a Foo that consumes U".

You are probably wondering about the "U is some subclass of a Foo that consumes U" part. I will be able to explain it a bit better using types that have more meaning than Foo and FooImpl:

SortedSequence maintains a sorted list of items. You can insert a new item and it will perform a binary search on the current list of items to find the index where the item will be inserted.

To make all of this work, the items need to be comparable to each other. That's why U extends Comparable. However, Comparable is also a generic type, so we need to specify type arguments: U extends Comparable<U> because the items need to be comparable to themselves.

So why does the actual declaration read U extends Comparable<? super U> ? That's because otherwise we'd be needlessly limiting the type of things we can make a sorted sequence of. Here's an example:

Why is it not possible to create a sequence of sheep, even though Sheep extends Animal and Animal is comparable to itself? Well, SortedSequence requires something that extends Comparable<Sheep>, and Sheep is not a Comparable<Sheep> but a Comparable<Animal>.

When instead we declare U as U extends Comparable<? super U>, we CAN create a SortedSequence<Sheep>, because the SortedSequence requires something that extends Comparable<? super Sheep>, and Comparable<Animal> does just that.

Finally, why do we say "consumes" in "SortedSequence of U, where U is some subtype of a Comparable that consumes U"? Well, the super keyword is used to specify a lower type bound on types that contain methods that only have the generic type in their method parameters, not in their return values. Comparable has T as a parameter in its compareTo method, and not in its return type. That's why we can use the super keyword, and that's why we say "Comparable that consumes U".
 
He was giving me directions and I was powerless to resist. I cannot resist this tiny ad:
the value of filler advertising in 2021
https://coderanch.com/t/730886/filler-advertising
reply
    Bookmark Topic Watch Topic
  • New Topic