Search code examples
javagenericstype-parameter

generic method ] extends multiple type parameter in JAVA


Im making a generic method which get an object and string.

it works at first like this..

public static <K, V> V getValue(Pair<K,V> _pair, String k){ ... }

I thought maybe it works as in main class

GrandChildPair<String, Integer> tst = new GrandChildPair<>("dd", 1);
Integer result = Util.getValue(tst,"dd");

But I wanna bound type extends to childPair not Grand one.. To limit this ..access? till ChildPair lines and not woking that in GrandChildPair. so I've tried first in method definition,

public static <K extends ChildPair<K,V>, V extends ChildPair<K,V> V getValue (

but yes It was dumb so I've searched for maybe 3 hours about multiple type parameter extends in java but I couldn't found yet.. I found other single type pram extends examples but I could't find extend a whole generic type (maybe not good at searching..)

Is there any I can do?

public class Util { 

    ///define method
    ////          //Type parameters //return type// method name ( prams...) {
    public static (Pair extends ChildPair) V getValue (Pair<K,V> _pair, String k) {

        if (k != _pair.getK())  return null; 
        else return _pair.getV(); 
    }
}

public class Pair<K, V> {
    private K k;
    private V v;

    Pair(K k, V v) {
        this.k = k;
        this.v = v;
    }

    public K getK() {
        return k;
    }
    public V getV() {
        return v;
    }
}

public class ChildPair<K, V> extends Pair<K, V> {
    public ChildPair(K k, V v) {
    super(k, v);
    }
}

public class GrandChildPair<K, V> extends ChildPair<K, V> {

    public GrandChildPair(K k, V v) {
        super(k, v);
    }
}

public class Main {

    public static void main(String[] args) {
        Pair<String, Integer> pair = new Pair<>("someone", 35);
        Integer age = Util.getValue(pair, "someone");
        System.out.println(age);

        ChildPair<String, Integer> childPair = new ChildPair<>("gh", 20);
        Integer childAge = Util.getValue(childPair, "sss");
        System.out.println(childAge);

    }
}

Solution

  • EDIT updated the check on what classes are not allowed based on @OleV.V.'s comment

    I don't think you can cleanly force the method to not accept GrandChildPair as a parameter because java considers it as type of ChildPair and also Pair. I also think that if you have to do this then maybe these relationships have to be re-designed, because this is not the right way to go.

    There is a not very good way to go:

    Main

    public class Main {
    
        public static void main(String[] args) {
            try {
                // works
                Pair<String, Integer> pair = new Pair<>("someone", 35);
                Integer age = (Integer) Util.getValue(pair, "someone");
                System.out.println(age);
            } catch (Exception e) {
                System.out.println("error: " + e.getMessage());
            }
    
            try {
                // mismatch in K so returns null
                ChildPair<String, Integer> childPair = new ChildPair<>("ch", 20);
                Integer childAge = (Integer) Util.getValue(childPair, "sss");
                System.out.println(childAge);
            } catch (Exception e) {
                System.out.println("error: " + e.getMessage());
            }
    
            try {
                // error
                GrandChildPair<String, Integer> grandChildPair = new GrandChildPair<>("gh", 40);
                Integer grandChildAge = (Integer) Util.getValue(grandChildPair, "gh");
                System.out.println(grandChildAge);
            } catch (Exception e) {
                System.out.println("error: " + e.getMessage());
            }
    
            try {
                // error
                OtherChildPair<String, Integer> otherChildPair = new OtherChildPair<>("oh", 60);
                Integer otherChildAge = (Integer) Util.getValue(otherChildPair, "oh");
                System.out.println(otherChildAge);
            } catch (Exception e) {
                System.out.println("error: " + e.getMessage());
            }
        }
    }
    

    Util

    public class Util {
    
        public static Object getValue(Pair<?, ?> _pair, String k) throws Exception {
            // check specific class and return / throw error
            // if (_pair instanceof GrandChildPair) {
    
            // OR check if it extends ChildPair and return / throw error
            if (_pair.getClass().isAssignableFrom(ChildPair.class) == false) {
                throw new Exception("call not allowed");
            }
    
            if (_pair.getK().equals(k) == false) {
                return null;
            }
    
            return _pair.getV(); 
        }
    }
    

    OtherChildPair

    public class OtherChildPair<K, V> extends ChildPair<K, V> {
    
        public OtherChildPair(K k, V v) {
            super(k, v);
        }
    }
    

    Output

    35
    null
    error: call not allowed
    error: call not allowed