I think that, for the most part, I understand bounded types, and the differences between, for example, List<? extends MyClass>, List<? super MyClass> and List<MyClass>. But when it comes to the implementation of classes and generic methods, I do not understand what <T extends MyClass> brings to the table.
Taken from the docs in Oracle:
[...] a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
public class Box<T> { private T t; public void set(T t) { this.t = t; } public T get() { return t; } public <U extends Number> void inspect(U u){ System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); integerBox.set(new Integer(10)); integerBox.inspect("some text"); // error: this is still String! } }
This doesn't make much sense to me. If I removed the generic from the method and made the parameter type just Number...
    public void inspect(Number u){
        System.out.println("T: " + t.getClass().getName());
        System.out.println("Second: " + u.getClass().getName());
    }
it would still work just fine. I don't see where I'm gaining or losing type safety, although maybe that's not the point?
Same in something like this:
class A { void foo() { } }
class B extends A { void bar() { } }
class Generic<T extends B> {
    void baz(T obj) {
        obj.foo();
        obj.bar();
    }
}
// vs
class NonGeneric {
    void baz(B obj) {
        obj.foo();
        obj.bar();
    }
}
What's the difference between these?
In your examples there is no practical difference.
The main practical difference is when you have return types using the generic.
But even without that, Generic<T extends B> and NonGeneric are not the same, because if we have class C extends B, then Generic<C> is not the same as NonGeneric, since the NonGeneric would allow non-C objects in the call to baz, and that's wrong.
In Generic class baz function only accept T type value but in NonGeneric class you can give any object those can cast to B.
Example:
public class Main {
    public static void main(String[] args) throws Exception {
        Generic<C> generic = new Generic<C>();
        generic.baz(new B()); // error
        generic.baz(new C()); // works fine
        generic.baz(new D()); // error
        NonGeneric nonGeneric = new NonGeneric();
        nonGeneric.baz(new B()); // works fine
        nonGeneric.baz(new C()); // works fine
        nonGeneric.baz(new D()); // works fine
    }
    static class A {
        void foo() {}
    }
    static class B extends A {
        void bar() {}
    }
    static class C extends B {}
    static class D extends B {}
    static class Generic<T extends B> {
        void baz(T obj) {
            obj.foo();
            obj.bar();
        }
    }
    static class NonGeneric {
        void baz(B obj) {
            obj.foo();
            obj.bar();
        }
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With