简体   繁体   中英

Instantiate a Java Generic class in a generic class

Here is a minimal code example. The interface:

interface Individual<T>  {
    public T getVariableValue(int index) ;
    public void setVariableValue(int index, T value) ;

    public int getNumberOfVariables() ;
    public int getNumberOfObjectives() ;

    public Individual<T> copy() ;
}

And the class:

public class  minimalExample<S extends Individual> {

    private List<S> doCrossover(List<S> s){
        S mom = s.get(0);
        S dad = s.get(1);

        int crossoverPoint = 5;

        S girl = mom.copy();
        S boy = dad.copy();
        for (int i = 0; i < mom.getNumberOfVariables(); i++) {
            if(i > crossoverPoint){
                boy.setVariableValue(i, mom.getVariableValue(i));
                girl.setVariableValue(i,dad.getVariableValue(i));
            }
        }
        return s;
    }
}

If i try to compile this i get:

java: incompatible types: Individual cannot be converted to S

Which seems confusing. Doesn' the extends keyword mean that S has to be of type Individual or a subtype?

The method copy() returns an object of type "Individual", which cannot be assigned to the type "S" since S is a subtype.

Why are girl and boy declared to be of type "S" and not Individual?

Which seems confusing. Doesn' the extends keyword mean that S has to be of type Individual or a subtype?

Yes, but that does not mean that the type returned by an S 's copy() method is also an S . The Individual interface requires only that it be an Individual .

Moreover, I observe that your class minimalExample is using the raw type Individual , whereas it ought to use a properly parameterized version (or else Individual should be made non-generic).

You may be over-parameterizing here. Does minimalExample really need to use S instead of directly using Individual ? Obviously, this example class does not, but perhaps the one that inspired the question doesn't, either.

On the other hand, if you do need a parameter for the specific type of Individual , then perhaps you need to further parameterize that interface to describe the kind of object its copy() method returns:

interface Individual<T,I extends Individual<T, I>>  {
    public T getVariableValue(int index) ;
    public void setVariableValue(int index, T value) ;

    public int getNumberOfVariables() ;
    public int getNumberOfObjectives() ;

    public I copy() ;
}

You could then declare your class MinimalExample with the needed additional information:

public class MinimalExample<T, S extends Individual<T, S>> {
    // ...
}

And here is a dummy implementation of Individual that you could use with that:

public class ExampleIndividual<T> implements Individual<T, ExampleIndividual<T>> {

    public T getVariableValue(int index) { return null; }
    public void setVariableValue(int index, T value) {}

    public int getNumberOfVariables() { return 0; }
    public int getNumberOfObjectives() { return 0; }

    public ExampleIndividual<T> copy() { return new ExampleIndividual<T>(); }

}

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