2017-09-22 4 views
2

Comment utiliser une méthode par défaut Java 8 dans une interface pour extraire la classe d'un type paramétré au lieu d'utiliser une classe abstraite?Extraire la classe de l'interface paramétrée en utilisant la méthode par défaut

Option 1 (ABSENT):

public interface EpicCoolInterface<T> { 

default Class<T> getParameterizedTypeClass() { 
    return T.class; //doesn't work 
} 

Option 2 (ABSENT):

public interface EpicCoolInterface<T> { 

default Class<T> getParameterizedTypeClass() { 
    return (Class<T>) ((ParameterizedType) getClass().getGenericInterfaces()[0]) 
    .getActualTypeArguments()[0]; 
    //java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType 
} 

troisième tentative (réussie mais pas d'interface):

public abstract class CoolAbstractClass<T> { 

    private Class<T> clazz; 

    public CoolAbstractClass() { 
    try { 
     this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()) 
      .getActualTypeArguments()[0]; 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
    } 

    public Class<T> getType() { 
    return clazz; 
    } 
} 

Répondre

1

En fait, ce que vous le besoin est l'inférence de type générique.

Bien que votre troisième tentative fonctionne, elle s'applique uniquement pour spécifier la situation (la classe étend directement la classe abstraite).

Vous pouvez utiliser ma méthode de classe utilitaire GenericUtil

Type[] getGenericTypes(Type sourceType, Class<?> targetClass) 

Vous pouvez trouver le code source et javadoc sur github.

Pour votre question, vous pouvez définir votre inteerface comme ceci:

public static interface EpicCoolInterface<T> { 
    // Return Type rather than Class, because T not always be a class. 
    // You can do type check and return Class<T> with force typecast. 
    default Type getParameterizedTypeClass() { 
     return GenericUtil.getGenericTypes(getClass(), EpicCoolInterface.class)[0]; 
    } 
    } 

Et Testons notre code:

public static void main(String[] args) { 
    EpicCoolInterface<Integer> a = new EpicCoolInterface<Integer>() { 
    }; 
    System.out.println(a.getParameterizedTypeClass()); 
    EpicCoolInterface<EpicCoolInterface<Integer>> b = new EpicCoolInterface<EpicCoolInterface<Integer>>() { 
    }; 
    System.out.println(b.getParameterizedTypeClass()); 
    EpicCoolInterface<EpicCoolInterface<?>> c = new EpicCoolInterface<EpicCoolInterface<?>>() { 
    }; 
    System.out.println(c.getParameterizedTypeClass()); 
    } 

il sortie:

class java.lang.Integer 
xdean.stackoverflow.java.reflection.Q46360416.xdean.stackoverflow.java.reflection.Q46360416$EpicCoolInterface<java.lang.Integer> 
xdean.stackoverflow.java.reflection.Q46360416.xdean.stackoverflow.java.reflection.Q46360416$EpicCoolInterface<?>