1

I'm looking to understand all of the detailed reasons/motivations/uses for each of these, but there are so many combinations while it all seems the same to me, that I am confused about the nuances of what I think is called generics(wildcards, Object, T, E etc., don't know if all of that falls under generics)

If I have something like this I want to make an arraylist out of:

Media<T> //Baseclass
Book<T> //Subclass
Movie<T> //Subclass

Which of these would be most appropriate to make/use in this case, and why?(If necessary, let's assume I'll only use String and Integer for these Books, Movies) :

  • ArrayList<Media> = new ArrayList<Media>;
  • ArrayList<Media<T>> = new ArrayList<Media<T>>;
  • ArrayList<Media<?>> = new ArrayList<Media<?>>;
  • ArrayList<? extends Media> = new ArrayList<? extends Media>;
  • ArrayList<Object> = new ArrayList<Object>;
  • ArrayList<> = new ArrayList<>;
  • Some other one?

And if the baseclass was abstract, would that make a difference/impact the choice?

I know that Object is the super-super class and "can assume any form", I know wildcards signal that the next object may be any kind, but so do E and T, right? I know that ? extends Media means it will be a type of Media. It all seems the same to me otherwise, I wouldn't know how to justify a specific choice.

EDIT: Complete example below

import java.awt.*;
import java.util.ArrayList;

public class Something {

    public class Media<T>{
        T data;
        public T getData(){ return this.data; }
        public void setData(T data){ this.data = data; }
    }
    public class Book<T> extends Media<T>{
        T data;
        @Override
        public T getData(){ return this.data; }
        @Override
        public void setData(T data){ this.data = data; }
    }
    public class Movie<T> extends Media<T>{
        T data;
        @Override
        public T getData(){ return this.data; }
        @Override
        public void setData(T data){ this.data = data; }
    }

    ArrayList<Media> arrList;

    public Something() {
         this.arrList = new ArrayList<Media>();
         this.arrList.add(new Book<Integer>());
         this.arrList.add(new Movie<String>());

         this.arrList.get(0).setData(12);
         this.arrList.get(1).setData("Hello");

         System.out.println(this.arrList.get(0).getData()+10);
         System.out.println(this.arrList.get(1).getData()+10);
    }

    public static void main(String[] args) {
        Something s = new Something();
    }

}
Jack Of Blades
  • 495
  • 7
  • 16
  • `ArrayList>` would seem the most natural choice. But it's not clear what `T` is or what your actual use case is. – shmosel Mar 21 '17 at 18:38
  • Just adding various kinds to an array of baseclass, like so: `arrList.add(new Book); arrList.add(new Movie);` And maybe some function from baseclass with the return-type T that each overrides. – Jack Of Blades Mar 21 '17 at 18:42
  • It would help if you posted a more complete example. – shmosel Mar 21 '17 at 18:44
  • Added one just now. – Jack Of Blades Mar 21 '17 at 18:54
  • what does Book mean? what does Movie mean? seems to me your example doesnt need the bit at all – radai Mar 21 '17 at 18:56
  • Book would mean that the object will make its member "data" a String from thereon out. Movie means that that particular Movie-object's member var data will be an Integer from now on. I know I don't need the T, this is just an example, I'm wondering if it makes a difference or why I should use a certain combination in this ordinary, low-level case, why not the others. – Jack Of Blades Mar 21 '17 at 19:00
  • Like, what happens if I use ArrayList extends Media> instead? I don't see any difference nor reason to use it, so why would I ever use it? Surely they made all of these combinations for some advantage or detail that each of them solves. – Jack Of Blades Mar 21 '17 at 19:07

1 Answers1

2

This is not a complete answer, but see this question on the effects of using "super" or "extends" in generic type specifications. The short version is that Collection<? extends T> is read-only while Collection<? super T> is append-only.

For this reason I personally prefer to completely avoid both these qualifiers since they are generally more restrictive than a simple Collection<T>.

However, they are sometimes useful when designing APIs for purposes of contra and counter variance (see this question)

Collection<?> I only use when dealing with legacy code (that doesnt use generics) to avoid a compiler warning. Its effectively the same as Collection<Object>, but to me is clearer. I try never to write new code that requires <?>

Community
  • 1
  • 1
radai
  • 23,949
  • 10
  • 71
  • 115