CaTalyst.X
CaTalyst.X

Reputation: 1665

Java Generics: Build Parameterized Classes for every inner class

Say I have an interface:

public interface Authentication<T> {
   public void authenticate(T token);
}

I have a class called AuthenticationMethods that has several inner classes.

what I want to do is write a utility where I can get all the inner classes, and generate a class that implements the Authentication<T> interface with the Type T of the inner class, like so:

for (Class clazz : AuthenticationMethods.class.getDeclaredClasses()){
   createAuthenticationImplClass(clazz);
}

private <T> Authentication<T> createAuthenticationImplClass(Class clazz){
  return new Authentication<clazz>() {
     @Override
     public void authenticate(clazz token) throws Exception {
        //do something with the token
     }
   };
}

Obviously just using clazz in place of T does not work.

How can i get the type from the clazz in to the parameterized implementation of the Authentication interface?

Upvotes: 0

Views: 268

Answers (2)

hoaz
hoaz

Reputation: 10153

If I understand you correctly, you want to authenticate tokens of the clazz class. Then you need to parametrize your factory method parameter with generic Class type:

private <T> Authentication<T> createAuthenticationImplClass(Class<T> clazz){
    return new Authentication<T>() {
        @Override
        public void authenticate(T token) throws Exception {
            //do something with the token
        }
    };
}

Of course at the moment you do for loop for declared classes you lose generic types, so the only way to pass type-safe Class instance is explicit class name:

Authentication<TokenType> authForTokenType = createAuthenticationImplClass(TokenType.class);

Upvotes: 1

You can do something like this.

private <T extends Class<?>> Authentication<T> createAuthenticationImplClass(T clazz){
  return new Authentication<T>() {
     @Override
     public void authenticate(T token) throws Exception {
        //do something with the token
     }
   };
}

Example

Authentication<Class<String>> = createAuthenticationImplClass(String.class);

or this

private <T> Authentication<T> createAuthenticationImplClass(Class<T> clazz){
  return new Authentication<T>() {
     @Override
     public void authenticate(T token) throws Exception {
        //do something with the token
     }
   };
}

Example:

Authentication<String> = createAuthenticationImplClass(String.class);

The difference is that in first example your authenticate method will have in parameter the Class type. In the second the parameter will be type that class represent.

Upvotes: 3

Related Questions