2

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);

    }
}
13
  • If I'm reading this correctly, you don't need any wildcard bounding fanciness. Just have your argument be ChildPair<K,V>. Commented May 4, 2017 at 6:54
  • I don't really understand your notation, Child < ChildPair means ChildPair extends Child or Child extends ChildPair? Commented May 4, 2017 at 6:55
  • Assuming you mean that Pair is a subclass of ChildPair, which is a subclass of GrandChildPair, and that you want method to require a ChildPair, then your method signature should be: public static <K, V> V getValue(ChildPair<K,V> _pair, String k) Commented May 4, 2017 at 7:02
  • 2
    You're really confusing the issue with your weird inheritance syntax. In your code it says Pair extends ChildPair, but in your comment you say ChildPair extends Pair, and the syntax Pair < ChildPair is non-standard and hence means nothing to us, so which is it? Don't answer with a comment. Edit the question and clarify it, e.g. by showing declaration such as class Pair<K, V> extends ChildPair<K, V>. Commented May 4, 2017 at 7:11
  • 2
    Now that you've shown all the code, it seems you want to be able to call Util.getValue() with a Pair, so declare the method with a Pair parameter, i.e. public static <K, V> V getValue(Pair<K, V> _pair, String k). Since ChildPair and GrandChildPair are both subclasses of Pair, the method can also be called with either of those. There is no way to prevent it from being called with GrandChildPair, if that was your question. If that wasn't your question, then I have no idea what you question is. Commented May 4, 2017 at 7:16

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

2 Comments

If you want to forbid all subclasses of ChildPair, I think you may use if (!_pair.getClass().isAssignableFrom(ChildPair.class)) (or someting like it).
oh now I understand ole's comment now maybe I would little exceptional process with if statement thanks
1

There are only a few things you need to make it work. This is the right getValue():

public static <K,V> V getValue (ChildPair<K,V> _pair, K k) {
    if (k != _pair.getK())  return null; 
    else return _pair.getV(); 
}
  • You need to specify only two type parameters, K and V in the beginning: static <K,V>.
  • The input parameter can be simply ChildPair<K,V> so it will accept ChildPair and GrandChildPair, however, it will reject Pair.
  • I believe you want to make sure that the second param of getValue(), k will be always the same type as the K of the pair. Thus I specified it as K k. You can make it more flexible with extends : public static <K,V,K2 extends K> V getValue (ChildPair<K,V> _pair, K2 k).

So this will be rejected, as designed:

Pair<String, Integer> pair = new Pair<>("someone", 35);
Integer age = Util.getValue(pair, "someone"); // compiler error

This will work:

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

This too:

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

And this too:

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

1 Comment

thanks its a little bit different but it's interesting flexible extending types and another bound way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.