1

I am trying to understand "super" and "extends" with respect to Java Generics. For this, I made following example / code:

package com.example.generics;

public class Generics1 {
    
    static <T super Animal> void superDemo() {
        
        
    } 
    
    // "extends" acts like UPPER bound
    // in Hierarchy tree up-to that "class"
    // we can pass on the objects
    
    static <T extends Dog> void  extendsDemoUptoDog(T t) {
        System.out.println("received is --> "+t);
        
    }
    
    static <T extends Cat> void  extendsDemoUptoCat(T t) {
        System.out.println("received is --> "+t);
        
    }
    
    static <T extends Animal> void  extendsDemo(T t) {
        System.out.println("received is --> "+t);
        
    }

    public static void main(String[] args) {
        
    
        Dog dog = new Dog();
        Generics1.extendsDemoUptoDog(dog);
        
        Dog dog1 = new Dog1();
        Generics1.extendsDemoUptoDog(dog1);
        
        
        Dog dog2 = new Dog2();
        Generics1.extendsDemoUptoDog(dog2);
        
        
        Cat cat = new Cat();
        Generics1.extendsDemoUptoCat(cat);
        
        Cat1 cat1 = new Cat1();
        Generics1.extendsDemoUptoCat(cat1);
        
        Cat2 cat2 = new Cat2();
        Generics1.extendsDemoUptoCat(cat2);
        
            
        Animal animal = new Animal();
        Generics1.extendsDemo(animal);
        
        
        // Doesn't work ... we have violated the UPPER BOUND
        // even though "animal" is INHERITED from FatherOfAllAnimal
        FatherOfAllAnimal foal = new FatherOfAllAnimal();
        //Generics1.extendsDemo(foal);
        
    }

}

class FatherOfAllAnimal{}
class Animal extends FatherOfAllAnimal{}
class Dog extends Animal {}
class Cat extends Animal {}
class Tiger extends Animal {}
class Lion extends Animal {}

class Dog1 extends Dog{}
class Dog2 extends Dog1{}
class Dog3 extends Dog2{}


class Cat1 extends Cat{}
class Cat2 extends Cat1{}
class Cat3 extends Cat2{}

The following is acceptable in method T extends Animal, as in method extendsDemo.

But why T super Animal is not valid, as in method superDemo? What is the correct way to express this?

halfer
  • 19,824
  • 17
  • 99
  • 186
CuriousMind
  • 8,301
  • 22
  • 65
  • 134
  • 1
    "But why T super Animal NOT valid" related: [Java generic methods: super can't be used?](https://stackoverflow.com/q/8403489). – Pshemo Apr 16 '23 at 14:57

1 Answers1

3

A super generic constraint wouldn't be very useful. If you had a method like this:

static <T super Animal> void superDemo(T t) { }

you only know that T is some super type of Animal, which doesn't help very much. You cannot call any of the Animal-specific methods on t, because T could be Object (which is a superclass of Animal). All you can safely do is call methods declared in Object, which isn't much different from

static void superDemo(Object o) { }

Even if T was used in the return type:

static <T super Animal> T superDemo() { }

You only know that you can at least return an instance of Animal, or any of its subclasses, like Cat. Again, this isn't much different from:

static Animal superDemo() { }

That said, a super bound is possible when you use it as a wildcard:

static void superDemo(List<? super Animal> list) { 
    // this is possible, because of the super bound
    list.add(new Cat());
}

This allows the caller to pass any list to which an instance of Animal, or any of its subclasses, can be added to the list. e.g. List<Object>, List<LivingThing>.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Thanks for the answer; but why does compiler give error ? I agree it may narrow down the choices, why does it even doesn't compile the code? – CuriousMind Apr 16 '23 at 16:13
  • 1
    @CuriousMind since this is not very useful, why should they spend time, and money to implement this into the compiler at all? – Sweeper Apr 16 '23 at 22:59