简体   繁体   中英

Is there a way in Java to hand over HashSet<Class> arguments to a method so that the method will accept HashSets of subclasses of Class?

Question & Explanation

Is there a way in Java to hand over HashSet<Class> arguments to a method so that the method will accept HashSets of subclasses of Class ?

This would be useful if there are several subclasses of a class the differences of which are not relevant to the method in question. If this is not possible, the only options to handle this seem to be

  • to write as many methods as there are subclasses
  • to loop through the HashSet in the calling function and call a similar method with the individual class instances as argument instead of the HashSets

... both are not very practical.

The version is Java 8 (openjdk 1.8.0).

Example

All files are assumed to be in the same directory so that we do not have to worry about packages and files importing each other. Consider a classes NNB and a subclass NNC (subclass of NNB).

NNB.java :

import java.util.HashMap;
import java.util.Map;


public class NNB {

    public final Map<Long, Double> dict;

    public NNB () {
        this.dict = new HashMap<Long, Double>();
        int c = 0;
        while (c<10) {
            Long XX = (long)10;
            Double YY = 2.0;
            this.dict.merge(XX, YY, Double::sum); 
            System.out.println(dict);
            c++;
        }
    }
}

NNC.java :

import java.util.HashMap;
import java.util.Map;


public class NNC extends NNB {

    private Map<Long, Double> dict2;

    public NNC () {
        super();
        this.dict2 = new HashMap<Long, Double>();
    }
}

Now assume, we want to call a method over a list of instances of NNB and NNC (say, to print NNB.dict and NNC.dict ).

This does not work: NNA2.java :

import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

public class NNA2 {

    public void printDict(HashSet<NNB> nnbs) {
        for (NNB nnb : nnbs) {
            System.out.println(nnb.dict);
        }
    }

    public static void main(String args[]) {
        NNA2 inst = new NNA2();
        HashSet<NNB> x = new HashSet<NNB>(Arrays.asList(new NNB()));
        HashSet<NNC> y = new HashSet<NNC>(Arrays.asList(new NNC()));

        inst.printDict(x);
        inst.printDict(y); //here it fails
        System.exit(0);
    }
}

Error:

NNA2.java:26: error: incompatible types: HashSet<NNC> cannot be converted to HashSet<NNB>
        inst.printDict(y);

This works (but is not quite what we wanted and would be unpractical if we wanted to perform more complex operations): NNA1.java :

import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

public class NNA1 {

    public void printOneDict(NNB nnb) {
        System.out.println(nnb.dict);
    }

    public static void main(String args[]) {
        NNA1 inst = new NNA1();
        HashSet<NNB> x = new HashSet<NNB>(Arrays.asList(new NNB()));
        HashSet<NNC> y = new HashSet<NNC>(Arrays.asList(new NNC()));

        for (NNB nnb : x) {
            inst.printOneDict(nnb);
        }

        for (NNC nnb : y) {
            inst.printOneDict(nnb);
        }

        System.exit(0);
    }
}

If I understand you correctly, you're looking for this:

public void printDict(HashSet<? extends NNB> nnbs) {
    // ...
}

See also Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic? and What is PECS (Producer Extends Consumer Super)?

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