简体   繁体   中英

How can you use generics to make universal methods in Java?

I have two classes, classB and classC, that both extend classLetters. In a separate class, which classB and classC call to, there are two methods: getBType() and getCType(). The code within the two is near duplicate because they both do the same thing, except one grabs B types and one grabs C types. Is there a way to combine these two into a single method called getType(String className), for example, that can detect which class is calling it and get the correct type depending on who called the method? It is so I can call from either classB or from classC with just one method, getType(String className) instead of having to call getBType() from classB and getCType() from classC. This is important because I will be adding a lot more classes that will extend from this, and I would like to reduce the amount of duplicate code.

Collection<classB> bstuff = new Collection<classB>();
Collection<classC> cstuff = new Collection<classC>();

public Collection<classB> getBType() {
        ArrayList<classB> b = new ArrayList<classb>();  //this can just return bstuff instead
        b.addAll(bstuff);                               //but i would like to leave this here for the example
        return b;
}

public Collection<classC> getCType() {
        ArrayList<classC> c = new ArrayList<classc>();  //this can just return cstuff instead
        c.addAll(cstuff);                               //but i would like to leave this here for the example
        return c;
}

I have thought of something like this: Make a data structure that holds the collections indexed by their class:

static HashMap<String, Collection<? extends classLetters>> allLetters = new HashMa..... etc(); //just an example
//then here i would statically add each class type to the hashmap

public Collection<? extends classLetters> getType(className) {
    if (className == "classB") {
        ArrayList<classB> b = new ArrayList<classb>(); 
        b.addAll(bstuff);                              
        return b;
    }
    else if (className == "classC") {
        ArrayList<classC> c = new ArrayList<classc>(); 
        c.addAll(cstuff);                              
        return c;
    }
}

This still has duplicate code within itself though. Is it possbile to have something using generics?

public <T> Collection<T> getType() {
    ArrayList<T> anyLetter = new ArrayList<T>;
    anyLetter.addAll(/* somehow distingush which letter class to put here */);
    return anyLetter;
}

Instead of inheritance one can use "templating" like in Arrays, Collections.

List<String> ls = new ArrayList<>();
List<Integer> li = new ArrayList<>();

public static <T> List<T> copy(Collection<T> list) {
    List<T> result = new ArrayList<>();
    result.addAll(list);
    return result;
}

public List<String> getLS() {
    return copy(ls);
}

public List<Integer> getLI() {
    return copy(li);
}
class A{}
class B extends A{}
class C extends A{}

class Container{
     private Map<Class<? extends A>, Collection<? extends A>> things = new HashMap<Class<? extends A>, Collection<? extends A>>();

     <Athing extends A> Collection<Athing> get(Class<Athing> clazz)
     {
       return (Collection<Athing>)things.get(clazz);
     } 

     <Athing extends A> void put(Class<Athing> clazz, Athing thing)
     {
       Collection<Athing> coll = get(clazz);
       if(coll == null)
       {
         coll = new ArrayList<Athing>();
         things.put(clazz, coll);
       }

       coll.add(thing);
     }

     public static void main(String []args){
       Container con = new Container();
       con.put(B.class, new B());
       con.put(A.class, new A());
     }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM