0

Working on a specific need. Most of online tutorial talks about applying wildcard implementation with Collections. In below example, extends works OK but when I apply super with wildcard bounding getting error. I wish to restrict a method with it super type like said in the below example. Is there any limitation with super that I supposed to know.

class SuperClass3 {
            public void display() {
                System.out.println("This is display3 method");
            }

        }


        class SuperClass2 extends SuperClass3 {
            public void display() {
                System.out.println("This is display2 method");
            }

        }

        class SuperClass1 extends SuperClass2 {
            public void display() {
                System.out.println("This is display1 method");
            }
        }

Extends works well (with Type bounding NOT with wildcard bounding)...

public <T extends SuperClass2> void displayOutput(T obj) {
        obj.display();
    }

Try to do the same with Super not working. Throw compile error on method signature.

public <T super SuperClass2> void displayOutputWithSuper(T obj) {
        //obj.display();
    }

Complete Example ...

package com.tutorial.generic.bounds.wildcard;

import java.util.List;

public class UpperBoundWildcardExample {

    class SuperClass3 {
        public void display() {
            System.out.println("This is display3 method");
        }

    }

    class SuperClass2 extends SuperClass3 {
        public void display() {
            System.out.println("This is display2 method");
        }

    }

    class SuperClass1 extends SuperClass2 {
        public void display() {
            System.out.println("This is display1 method");
        }
    }

    public <T extends SuperClass2> void displayOutput(T obj) {
        obj.display();
    }

    public void addData(List<? extends SuperClass2> data) {

    }

    public <T super SuperClass1> void displayOutputWithSuper(T obj) {
        obj.toString();
    }

    /*
     * This wont work 
     * 
     * public void addData(<? extends SuperClass2> data){
     * 
     * }
     */

    public static void main(String[] args) {
        UpperBoundWildcardExample obj = new UpperBoundWildcardExample();
        // Oops!!! Error
        // obj.displayOutput(obj.new SuperClass3());
        // It suppports SuperClass2 & which extends SuperClass2
        obj.displayOutput(obj.new SuperClass2());
        obj.displayOutput(obj.new SuperClass1());
    }
}
Shaan
  • 588
  • 1
  • 4
  • 15
  • The issue here is that when you say `T super SuperClass2` the only methods you can call are those from `Object`, because you can't be certain that the object actually has a `display()` method implemented. – Tim Biegeleisen Feb 26 '18 at 01:56
  • Thanks for your comment. But I'm getting compile time error in the method signature even I try invoke Object's method. Actually, SuperClass2 extends from SuperClass3. I wish to restrict calling method from both SuperClass2 and 3 or Object's class. Can you please give me some example accomplish the need. – Shaan Feb 26 '18 at 02:03
  • Try using ` super SuperClass2>` – Tim Biegeleisen Feb 26 '18 at 02:05
  • Wildcard is not accepting either upper or lower bound in method signature. It does when we passed in Collection. – Shaan Feb 26 '18 at 02:08
  • The method `displayOutput()` looks totally out of place. What is the actual code containing this method? – Tim Biegeleisen Feb 26 '18 at 02:11
  • I attached the complete example. I'm getting compile time error in the method signature where I restricted with Super. – Shaan Feb 26 '18 at 02:20
  • This works: `public void displayOutput(SuperClass2 obj) { ... }` ... try to fix the other two method calls. – Tim Biegeleisen Feb 26 '18 at 02:25
  • In my example above extends with Type bounding is working. The same approach with super is not working – Shaan Feb 26 '18 at 03:04
  • It looks like [you can't use `super` in method signatures](https://stackoverflow.com/questions/8403489/java-generic-methods-super-cant-be-used), because it will always erase to just Object and it won't get you anywhere. – Tim Biegeleisen Feb 26 '18 at 03:17
  • In my opinion, providing such a mechanism (where you could call a method for only a specific set of sub-classes) would break the fundamental "every sub-class IS A super-class" guarantee that inheritance provides. The usual way to meet such a requirement is override the method (e.g. in SuperClass1) and throw an operation-not-supported exception. – Ashutosh A Feb 26 '18 at 04:44
  • Appreciated Ashutosh and Tim for your response. I was curious about Type Inference over Type Erasure. If Type Inference works well in these scenario, can easily predict what are legal type that method can take in? Right? – Shaan Feb 26 '18 at 14:46

1 Answers1

0

@Shaan This might be helpful

Bounding generics with 'super' keyword

let's say that you have this generic method declaration:

<T super Integer> void add(T number) // hypothetical! currently illegal in Java

And you have these variable declarations:

Integer anInteger
Number aNumber
Object anObject
String aString

Your intention with (if it's legal) is that it should allow add(anInteger), and add(aNumber), and of course add(anObject), but NOT add(aString). Well, String is an Object, so add(aString) would still compile anyway.

user3343658
  • 80
  • 1
  • 11
  • This didn’t talk about return type but it talks about parameter type. If you see clearly, my return type as void. Super is not working resulting compile time error whereas extends work well with above example. Question is Why super is not working? How can I restrict the same example with Super as method parameter ? – Shaan Feb 26 '18 at 03:46
  • @Shaan this might be helpful for your question. https://stackoverflow.com/questions/2800369/bounding-generics-with-super-keyword – user3343658 Feb 26 '18 at 07:36
  • Thank you for your time with this. My curious is, what role Type Erasure and Type Inference does. Since TypeErasure change to Object the listed operation are eligible. If Type Inference does their role very well then it should not allow our program to compile since String is incompatible type? Right? – Shaan Feb 26 '18 at 14:30