Get actual enum class of the Parameterized class T extends Enum<?> - java

I have a class:
public class MultipleSorting<T extends Enum<?>> {
private T criteriaType;
public Class<T> getCriteriaClass() {
Field field = ReflectionUtils.getField(getClass(),"criteriaType");
ReflectionUtils.makeAccessible(field);
return (Class<T>)field.getType();
}
}
This class is get instantiated as:
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?,?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController() {
super();
multipleSorting = new MultipleSorting<U>();
}
}
The actual value of U is passed from the child class of MultiSortPageableController which is:
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T,ArticleSortField> {
}
The ArticleSortField is an Enum.
I was expecting the method getCriteriaClass of MultipleSorting would return ArticleSortField from a method of MultiSortPageableController. But it is returning java.lang.Enum.
I am unable to figure it out why it is not returning the actual enum and how can I make it so. Any pointer would be very helpful to me. I need to get ArticleSortField.
Purpose:
I two requirement:
To get the actual class of enum type (say ArticleSortField.class)
To list enum value. If I have the enum class, then I could invoke class..getEnumConstants().

Java compiler removes information about generics, therefore when you use reflection you get no information about the declared type, other than Enum. This process is called type erasure.
How about passing the type down, via the constructor, like this:
public class MultipleSorting<T extends Enum<?>> {
private Class<T> criteriaType;
MultipleSorting(Class<T> criteriaType) {
this.criteriaType = criteriaType;
}
public Class<T> getCriteriaClass() {
return criteriaType;
}
}
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?, ?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController(Class<U> criteriaType) {
super();
multipleSorting = new MultipleSorting<U>(criteriaType);
}
}
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T, ArticleSortField> {
public AbstractArticleSearchController() {
super(ArticleSortField.class);
}
}

Related

Factory using CDI returning capture of type instead of concrete type

I want to create a processor factory that uses CDI to get all available processors. The factory should select the desired processor based on some parameter. So I have my parameter:
public abstract class Parameter { }
#CorrespondingProcessor(type = StringProcessor.class)
public class StringParameter extends Parameter { }
#CorrespondingProcessor(type = FileProcessor.class)
public class FileParameter extends Parameter { }
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface CorrespondingProcessor {
Class<? extends Processor<? extends Parameter>> type();
}
And for every parameter there is a processor:
public interface Processor<T extends Parameter> {
String work(T parameter);
}
public class StringProcessor implements Processor<StringParameter> {
#Override
public String work(StringParameter parameter) {
return "string";
}
}
public class FileProcessor implements Processor<FileParameter> {
#Override
public String work(FileParameter parameter) {
return "file";
}
}
Basically my factory looks like this:
public class ProcessorFactory {
private final Instance<Processor<? extends Parameter>> processors;
#Inject
public ProcessorFactory(#Any Instance<Processor<? extends Parameter>> processors) {
this.processors = processors;
}
public <T extends Parameter> Processor<T> getProcessor(T parameter) {
CorrespondingProcessor annotation = parameter.getClass().getAnnotation(CorrespondingProcessor.class);
CorrespondingProcessorLiteral correspondingProcessorLiteral = new CorrespondingProcessorLiteral(annotation.type());
Class<? extends Processor<? extends Parameter>> type = correspondingProcessorLiteral.type();
Processor<? extends Parameter> processor = processors.select(type).get();
return processor;
}
private class CorrespondingProcessorLiteral extends AnnotationLiteral<CorrespondingProcessor> implements CorrespondingProcessor {
private final Class<? extends Processor<? extends Parameter>> type;
public CorrespondingProcessorLiteral(Class<? extends Processor<? extends Parameter>> type) {
this.type = type;
}
#Override
public Class<? extends Processor<? extends Parameter>> type() {
return type;
}
}
}
This will not compile, because the defined return type of the getProcessor-method differs from the returned processor-variable. The compiler does not know if the selected processor is a processor of T. And at this point I am struggling. Is there a way to get this working? How can I enforce that the selected processor is a processor of T? Or is this approach wrong in the first place?
I don't want to inject all the available processors by their own. Because this would mean, I would have to change the factory every time I add a new processor.
The solution is using TypeLiteral instead of AnnotationLiteral. But as discussed in What type literal must I use to have CDI's Instance::select method work properly? one must provide the actual type at compile time.
processors.select(new TypeLiteral<Processor<T>>() {}).get()
This will not work since type T is erased due to type erasure.
So the getProcessor-method must be changed to:
public <T extends Parameter> Processor<T> getProcessor(TypeLiteral<Processor<T>> selector) {
return processors.select(selctor).get();
}
Calling this method like factory.getProcessor(new TypeLiteral<Processor<StringParameter>>() {}) will do the trick.

How can I change the generic type in child-classes in Java

How can I change the generic type in child-classes. I know, that i can override method load(); But i want to make the universal method for all children.
I have abstract super class
public abstract class Vehicle <T extends Human> {
T t;
private final int maxPassengers;
private Set<T> currentPassengers = new HashSet<>();
public Vehicle(int maxPassengers) {
this.maxPassengers = maxPassengers;
}
public void load (T human) throws ToManyPassangersExeption {
if (currentPassengers.size()<maxPassengers)
currentPassengers.add(human);
else
throw new ToManyPassangersExeption();
}
}
load() realize loading Human to vehicle. I have different types of Human. For example:
public class Policeman extends Human {
}
In my class PoliceCar, i what to load only Policemen.
public class PoliceCar <T extends Policeman> extends Vehicle {
T t;
public PoliceCar() {
super(5);
}
}
Using this code, i can load all instanceof Human to PoliceCar.
How can i load only Policeman in PoliceCar without Overriding method load()?
Declare the PoliceCar type with a non-raw superclass:
class PoliceCar<T extends Policeman> extends Vehicle<T>
Then the load method will require a T parameter, where T is a subclass of Policeman.
See What is a raw type and why shouldn't we use it?.

Generics: generic class based on generic class

I'm trying to create a generic service that is based on a class with a generics based collection
public class GenericClass<T> {
List<T> results;
public List<T> getResults() {
return results;
}
}
Im just not sure how to create a service that is based on this GenericClass and has a concrete implementation of T. I would expect something like
public class ServiceManagerImpl<GenericClass<T>> implements ServiceManager<GenericClass<T>> {
public GenericClass<T> getMyClass() {
...
}
}
But the compiler doesn't like this. Any ideas how to do this?
Marc
You are close... just pass the T through:
public class ServiceManagerImpl<T> implements ServiceManager<GenericClass<T>> {
public GenericClass<T> getMyClass() {
...
}
}
I can suggest the following implementation that doesn't break the rules of JLS:
// ServiceManager.java
public interface ServiceManager<E, T extends GenericClass<E>> {
}
// ServiceManagerImpl.java
public class ServiceManagerImpl<E, T extends GenericClass<E>> implements ServiceManager<E, T> {
public T getMyClass() {
return null;
}
}
The content between <> is called Type Parameters, and GenericClass<T> is not a valid Type Parameter in declaration.
Quote from java generic guide
A generic class is defined with the following format:
class name<T1, T2, ..., Tn> { /* ... */ }
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.
so, you need to use GenericClass<T> in implementation, not in declaration.
// declaration
public class ServiceManagerImpl<YourGenericType> implements ServiceManager<YourGenericType> {
public YourGenericType getMyClass() {
...
}
}
// implementation
ServiceManager<GenericClass<Object>> sm = new ServiceManagerImpl<GenericClass<Object>>();
public class ServiceManagerImpl<T extends GenericClass<T>> implements ServiceManager<T extends GenericClass<T>> {
public GenericClass<T> getMyClass() {
...
}
}
I am not sure my answer is legal , but it seems meet your requirement:
public class ServiceManagerImpl<T extends GenericClass> implements ServiceManager<T>
{
#Override
public T getMyclass() {
//do your work here;
}
}
Although it may have a unchecked warning when I declare this class , but this really does!
ServiceManager<GenericClass<Integer>> manager = new ServiceManagerImpl<GenericClass<Integer>>();//passed
You should try likes this;
public class ServiceManagerImpl<GenericClass<Object>> implements ServiceManager<GenericClass<Object>> {
public GenericClass<Object> getMyClass() {
...
}
}
You can replace Object with Integer or String or any data types as you likes.

How to convert implementors on one interface into another?

I'm having trouble finding a way to do this in a way that doesn't seem wrong, given the following
public interface IType {}
public interface IMode {}
public interface Factory<T extends IType> {
IMode get(T o);
Class<T> getIType();
}
I have the above interfaces and a large list on classes the implement both IType and IMode with corresponding factories.
I need to be able to convert from one to the other, for example,
public class A implements IType {}
public class One implements IMode {}
public class AToOne implements Factory<A> {
public IMode get(A o){
return new One();
}
public Class<A> getIType(){
return A.class;
}
}
Given that there is a 1 to 1 mapping of these classes, ie for every concrete IType there is one and only one concrete IMode with corresponding factory, how would I go about converting a list of ITypes to a list of IModes?
ie.
private List<Factory<? extends IType>> factoryList;
public List<IMode> getConversions(List<? extends IType> types){
???
}
My first try did not go so well,
//Fill this using the getIType() method from each factory
Map<Class<IType>, Factory<? extends IType>> factoryList = new HashMap<Class<IType>, Factory<? extends IType>>();
public List<IMode> getConversions(List<IType> types){
List<IMode> modes = new ArrayList<IMode>();
for(IType type : types){
//Derp
Factory<? extends IType> factory = factoryList.get(type.getClass());
//Error
factory.get(factory.getIType().cast(type));
}
}
Error:
The method get(capture#12-of ? extends IType) in the type
Factory<capture#12-of ? extends IType>
is not applicable for the arguments (capture#14-of ? extends IType)
Like I mentioned in my comment, you just need to use a generic helper method to access the map, which performs an unchecked cast from Factory<? extends IType> to a Factory<T> where T matches the type of what's passed in:
Map<Class<? extends IType>, Factory<? extends IType>> factoryList =
new HashMap<Class<? extends IType>, Factory<? extends IType>>();
private <T extends IType> IMode convert(T iType) {
//unchecked cast - implementation must guarantee map holds correct data
Factory<T> factory = (Factory<T>)factoryList.get(iType.getClass());
//then convert
return factory.get(iType);
}
You can call this helper method from the loop:
public List<IMode> getConversions(List<IType> types) {
List<IMode> modes = new ArrayList<IMode>(types.size());
for (IType type : types) {
IMode iMode = convert(type);
modes.add(iMode);
}
return modes;
}
The simple solution is the following:
interface IFoo {
}
interface IBar {
}
private static class Foo implements IFoo {
}
private static class Bar implements IBar {
}
interface IFoo2IBarConverter<B extends IBar, F extends IFoo> {
B convert(F foo);
}
private static class Foo2BarConverter implements IFoo2IBarConverter<Bar, Foo> {
public Bar convert(Foo foo) {
return new Bar();
}
}
private static class IFoo2IBarFactory {
private static HashMap<Class<? extends IFoo>, IFoo2IBarConverter<? extends IBar, ? extends IFoo>> converters = new HashMap<>();
static {
converters.put(Foo.class, new Foo2BarConverter());
}
public static<F extends IFoo, B extends IBar> B convert(F foo) {
// ugly unchecked cast here
IFoo2IBarConverter<B, F> converter = (IFoo2IBarConverter<B, F>) converters.get(foo.getClass());
return converter.convert(foo);
}
}
public static void main(String[] args) {
Foo foo = new Foo();
IBar bar = IFoo2IBarFactory.convert(foo);
}
You just take a HashMap that maps a specific class that's a subtype of IFoo to some converter interface. The converter takes the IFoo instance and converts it into a IBar.. actually into the specific classes we want. Sadly we get an ugly cast in IFoo2IBarFactory.convert() and I don't think there's any way to avoid that one. Still at least it's only in one localized position and with the right comment and a SuppressWarning you can live with it, I'd think

Constructing objects via reflection using object's class

Assuming code like below:
public interface Component<T>
{
}
public class ConcreteComponent<T> implements Component<T>
{
}
How would you solve such compilation problem:
#Override
public Class<? extends Component<?>> getComponentClass() {
// Does not compile!
return ConcreteComponent.class;
}
Basically, as you can see I'd like to able to construct object via reflection using component's class. Ommiting the details, method's declaration might look like this:
public <T extends Component<?>> void createComponent(Class<? extends T> clazz)
{
}
And finally:
ConcreteComponent<Integer> cmp = createComponent(getComponentClass());
Any help would be appreciated!
This compiles:
public Class<? extends Component> getComponent() {
// Compiles!
return ConcreteComponent.class;
}
Return (Class>) ConcreteComponent.class;
You can use either of the below code.
The return type you have mentioned should match the value you have returned so you need to cast it to the return type.
public class ConcreteComponent<T> implements Component<T> {
public Class<? extends Component<?>> getComponent() { // Does not compile!
return (Class<? extends Component<?>>) ConcreteComponent.class;
}
}
OR
public class ConcreteComponent<T> implements Component<T> {
public Class<? extends Component<?>> getComponent() {
return (Class<? extends Component<?>>) this.getClass();
}
}

Categories

Resources