18

I know it's possible to add multiple constraints to a Generic class definition, e.g.:

class Example<I extends Object & Comparable<Object>>{}

But I want a generic (MyGeneric) that takes another generic (SomeGeneric<T>) as its type parameter, and to constrain the type parameter (T) of that generic (e.g. T extends SomeClass).

Important, I need to know the types of both SomeGeneric and SomeClass from inside the class (G and T need to both be bound). For example, imagine something like this:

class MyGeneric<G extends SomeGeneric<T>, T extends SomeClass>
{
   public G returnSomeGenericImpl(){}
   public T returnSomeClassImpl(){}
}

Question: The above works, but I would prefer if my class had only one type parameter, to make life easier for implementers of my class. Is there a way of doing this?

Something like this would be nice (but this particular code is incorrect):

class MyGeneric<G extends SomeGeneric<T extends SomeClass>>
{
   public G returnSomeGenericImpl(){}
   public T returnSomeClassImpl(){}
}

If I wasn't clear, I'll gladly try to clarify my intent.

7
  • 6
    I don't see how this could possibly work. If you never specify the concrete type T, how should the compiler guess it? If there's only a single option, then it's easy, but there usually isn't. And if you don't care about the specific type, then why not use a bounded wildcard type (or a local type parameter on the method). Commented May 15, 2013 at 12:03
  • @JoachimSauer are you saying that due to type erasure the compiler could enforce the constraint I want, but could not extract/know the type of the generic? for example, it can do <G extends SomeGeneric<SomeClass>> or even <G extends SomeGeneric<? extends SomeClass>>, but the type of T (? in this case) is not known. Commented May 15, 2013 at 12:14
  • @JoachimSauer regarding the second part of your comment, obviously I do care about the specific type as I would like to return an instance of it from public T returnSomeClassImpl(){} Commented May 15, 2013 at 12:17
  • @Bohemian specifying two types is generally no problem, but in this case it feels redundant to write new Whatever<SomeGeneric<T>,T>(), we're just repeating T. if it's not possible it's not possible, that was the point of the question Commented May 15, 2013 at 12:20
  • Well, if you want to bind G extends SomeGeneric<T> to SomeGeneric<T>, then maybe you can get rid of G altogether? Commented May 15, 2013 at 12:38

3 Answers 3

1

It looks impossible to achieve.

After reducing your type definition by one order by removing one type variable and trying to define it,

class G extends SomeGeneric<T extends SomeClass>{}

does not compile because the type parameter T is not bound with respect to an already defined type parameter. But, this works -

class G<T extends SomeClass> extends SomeGeneric<T>{}

So, I infer that the only way of parameterizing with two types is by declaring them up front.

Sign up to request clarification or add additional context in comments.

5 Comments

@seeta when you write "So, I infer that the only way of parameterizing with two types is by declaring them up front." what do you mean by "up front"? the problem with defining a class up front is I would need to enforce that all necessary classes extend this class... which is not a solution. however "It looks impossible to achieve" sadly, I think I agree with
@nakosspy regarding "The class has two type parameters T and G. Both must be declared upfront", of course, nobody ever debated that. the question was about how java allows them to be declared.
@AlexAverbuch By up front, I meant declaring the parameters with the class name. As you wrote - MyGeneric<G extends SomeGeneric<T>, T extends SomeClass>
@AlexAverbuch Would you want to accept the answer for closure?
I've (hesitantly) accepted your answer but mostly - as you say - for closure. I was hoping someone would have a better answer, along the lines of "no, it's not possible, and here's a detailed explanation of why" or "yes, here's a pattern you can use to achieve what you want"
1

try this

class Test1<T extends List<? extends Number>> {

    public static void main(String[] args) throws Exception {
        new Test1<ArrayList<Number>>();  
        new Test1<ArrayList<Integer>>(); 
        new Test1<ArrayList<Object>>();  // compile error
    } 
}

4 Comments

could you please add some more explanation in this?So it'll be more helpful for me to follow this discussion
it says "allowed type is a List of Numbers"
please reread question: "Important, I need to know the types of both SomeGeneric and SomeClass from inside the class (G and T need to both be bound)"
If you need bindings for both, then they both have to be parameters. If the inner type isn't a parameter, then you can't bind it.
0

Imagine this:

Type t = someClass();
Type g = someGeneric(t);

foobar(g,t)

compared to this

Type g = someGeneric(someClass());
foobar(g,?)

the second one is Evgeniy Dorofeev's solution. You see the problem? You can't bind to a variable within an argument. Same with generics. What you want to do is this

Type g = someGeneric(Type t = someClass());
foobar(g,t)

1 Comment

thanks for the explanation, but I don't think this qualifies as an answer. perhaps it's better to respond to @EvgeniyDorofeev as a comment on his answer..?

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.