20

In a class without generic types I want to declare a rather complex generic field similar to these:

public class Client {
    private Map<Class<T extends Serializable>, List<Consumer<S extends T>>> classToConsumerTry1;

    private <T extends Serializable, S extends T> Map<Class<T>, List<Consumer<S>>> classToConsumerTry2;
}

promblem is the java compiler won't let me :)

So my question is how do I correctly introduce T and S without adding types to my class Client.

My goal is to enforce the Class being a subtype of Serializable and the Consumer being a subtype of the class you chose for Class.

6
  • Why don't you want to extend your class declaration? Commented Aug 14, 2015 at 11:17
  • Because my Map should be able to contain different values for T and S not only the ones defined in the Client declaration. Commented Aug 14, 2015 at 11:23
  • Where are your Map members initialized? In a constructor? In some setter method? Commented Aug 14, 2015 at 11:26
  • 1
    I don't really understand your requirement - it is Java notion that you set generic field types on object creation, what do you want to achieve? Commented Aug 14, 2015 at 11:28
  • Im recieving Serializables over a Socket and want to process them nicely like this: classToConsumer.get(serial.getClass()).get(i).accept(serial); Commented Aug 14, 2015 at 11:37

5 Answers 5

12

You can't. Your only option is to declare the generic type parameters in your Client class declaration. If your Client class has no generic type parameters, its members can't be generic. You must use actual types in the declaration of your class members.

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

Comments

7

You have to somewhere introduce the type-parameter, so that you can use them in the definition for your class members.

Introducing a type-parameter can be done only on a class-level, or on a method-level. In your case, it should be on class-level:

public class Client<T extends Serializable, S extends T> {
    private Map<Class<T>, List<Consumer<S>>> classToConsumerTry1;

    private Map<Class<T>, List<Consumer<S>>> classToConsumerTry2;
}

This, however, implies that for both members (classToConsumerTry1 and classToConsumerTry2), T and S are the same. If you want them to be different, the you will have to get these two values from two different classes, both of which are parameterized with separate type-parameters.

1 Comment

Also, as additional step, this class can be declared as protected class ClientImpl and to hide generics, an exposed public class Client extends ClientImpl<Serializable, Serializable> can be declared
4

You can not do it directly on the field, but you can maintain your types policy by generic methods (they can exist even in non-generic class):

@SuppressWarnings("rawtypes")
private Map<Class, List> map;

public <T extends Serializable> void put(Class<T> key, List<Consumer<? extends T>> value) {
    map.put(key, value);
}

@SuppressWarnings("unchecked")
public <T extends Serializable> List<Consumer<? extends T>> get(Class<T> key) {
    return map.get(key);
}

Comments

3

As a note it is possible to declare a class type as a field (since google sends me here for this unrelated question...)

  Class<? extends MyInterface> myCurrentClass = MyImplementation.class;

1 Comment

Your answer helped my with a slightly different problem. The trick is not to use a generic type variable (like "<T>") but directly declare the required hierarchy.
1

You can't the way you want it done. But you can set as an Object and cast. Other hacky answers include using a List of <? extends Serializable> (but this only works for one extends) and then add() your item or an internal class that does something like:

private class Foo<T> {
        T obj;
}

so you can access/mutate obj internally.

Comments

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.