Is there any way to get Class from reflection?
What i want to do is, I have implemented custom Serializer for hazelcast-3.2.3. and I don't want to write separate Serializer for each class(whom object I need to store in Hcast).
I want this
class TestSerializer<T> {
Class<T> classType;
Public Test(){
classType = T.someway() //if there is any method to get that;
}
}
Because I'm configuring my Serializer in hazelcast.xml i cant pass Class in constructor parameters.
I assume you're really asking how to get the class of the generic type T during runtime, not just a class.
The easiest way to do it is to pass it as an argument to the constructor but if you really, really want to do it with reflection, you can use a trick that eg. Jackson uses which relies on anonymous sub classes. To do this, read up on how TypeReference works, especially Super Type Tokens
I might, of course, be wildly off here on what you want to do. Please correct me if I am :)
Your TestSerializer cannot get that type internally due to type erasure. That information has to be provided externally.
This means you'll have to refactor how you do it through configuration.
Related
IMPORTANT:
the code I currently have Is working per my expectations. It does what I want it to do. My Question is about wether the WAY in which I have made it work is wrong. The reason I am asking this is because I've seen plenty of stack overflow results about raw types and how they should basically NEVER be used.
What I'm doing and Why I used raw types
Currently I am dynamically creating a concrete subclass of a generic interface where the interface takes in parameters when the class is constructed. When I make an instance of this class and use its returned object to call various methods, I use raw types because it works for what I'm trying to do. Here is an example in my functioning code where the raw types are used. This code is in top down order i.e. between code blocks there is no code.
Loading properties file
Properties prop = new Properties();
try {
prop.load(ObjectFactory.class.getResourceAsStream("config.properties"));
This is the File parser that implements FileParserImplementation and takes in the data and puts it into an array. This code gets the Class type and then makes an instance of that type dynamically.
Class<? extends FileParserImplementation> parser = null;
parser = Class.forName(prop.getProperty("FileParserImplementation")).asSubclass(FileParserImplementation.class);
FileParserImplementation ParserInstance = (FileParserImplementation) parser.getDeclaredConstructors()[0].newInstance();
These two classes and their instances are the two seperate DataParsers implementing DataParserImplementation. These take in the array of Strings that the FileParser gives and creates objects/manipulates the data into whatever is needed. It puts out a Collection of this data. The Fileparser dependency is passed in through constructor injection. This can be configured through the properties file at runtime.
Class<? extends DataParserImplementation> dataset1 = Class.forName(prop.getProperty("DataParserImplementation_1")).asSubclass(DataParserImplementation.class);
Class<? extends DataParserImplementation> dataset2 = Class.forName(prop.getProperty("DataParserImplementation_2")).asSubclass(DataParserImplementation.class);
DataParserImplementation Dataset1Instance = (DataParserImplementation) dataset1.getDeclaredConstructors()[0].newInstance(ParserInstance);
DataParserImplementation Dataset2Instance = (DataParserImplementation) dataset2.getDeclaredConstructors()[0].newInstance(ParserInstance);
This is the Crossreferencer class that implements CrossReferencerImplementation. It takes in the two datasets and Cross references them In whatever way is desired by the actual concrete reflected class. This also can be configured at runtime. It outputs a Map in this main.
The map serves as the final collection for the data (I might change that later).
Class<? extends CrossReferenceImplementation> crossreferencer = Class.forName(prop.getProperty("CrossReferenceImplementation")).asSubclass(CrossReferenceImplementation.class);
CrossReferenceImplementation crossReferencerInstance =
(CrossReferenceImplementation) crossreferencer.getDeclaredConstructors()[0].newInstance();
Getting the Map result from calling a method on our reflected instance. Then the contents of this map are printed out. currently it seems the map parameters are gotten as well because the Objects that are inside the map are properly using their toString methods when reflectiveFinalMap.get(key).toString() is called.
This leads me to believe it works as I intend.
Map reflectiveFinalMap = (Map)
crossReferencerInstance.CrossReference(Dataset1Instance.Parse(), Dataset2Instance.Parse());
for (Object key:reflectiveFinalMap.keySet()) {
System.out.println(key + " { " +
reflectiveFinalMap.get(key).toString() + " }");
}
return reflectiveFinalMap;
}
//catch block goes here
Notice that each time I reflectively create an instance of a class that implements one of my interfaces, I use the interface as the raw type. My Hope is that the reflection then sees the parameterized type of this raw type when it creates the concrete subclass, because thats where the parameter types are actually specified. The point is to let any class that implements those interfaces be generic to the point where they can take in just about anything and return just about anything.
Things I tried to not use raw types.
I've tried to actually obtain the parameterized type of CrossReferenceImplementation in the reflected crossreferencer Class that I get right now by calling
Class arrayparametertype = (Class)((ParameterizedType)crossreferencer.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
And then I tried to pass in that arrayparameter when creating an instance of crossreferencer like this:
CrossReferenceImplementation crossReferencer = (CrossReferenceImplementation<<arrayparametertype>>) crossreferencer.getDeclaredConstructors()[0].newInstance();
That didn't work since variable parameter types apparently aren't a thing.
I tried to manually specify the specific parameter of the concrete reflected class(I DON'T want this anyway because it breaks the whole point of reflection here, decoupling the Classes from each other by being able to use anythng that implements the appropriate interface). This caused this warning to appear and the code to not actually run the methods it was supposed to:
//how the parameters were specified. Messy and breaks the reflection.
CrossReferenceImplementation<Map<String, SalesRep>,Map<String, SalesRep>,Map<String, SalesRep>> crossReferencer = (CrossReferenceImplementation) crossreferencer.getDeclaredConstructors()[0].newInstance();
//where the warning occured
Map reflectiveFinalMap = (Map) crossReferencer.CrossReference(Dataset1.Parse(), Dataset2.Parse());
The Warning:
"Dataset1 has raw type so result of Parse is erased".
Note that SalesRep here is the object in which the data is held as fields of that object. This object gets manipulated and put into various collections. It too is accessed via reflection in the many methods of DataParserImplementations
A similar error message and problem occured when specifying the parameter type of the Map (AGAIN I DON'T want this because it makes the reflection pointless I want the map return result to be generic and be specified by the implementing class).
//where the parameterized type was specified
Map reflectiveFinalMap = (Map<String,SalesRep>) crossReferencer.CrossReference(Dataset1.Parse(), Dataset2.Parse());
When specifying the actual parameterized type of the map result the error message was:
"crossReferencer has raw type so result of CrossReference is erased".
Running the code did indeed confirm for me that .CrossReference method's results were erased while everything else ran fine.
What internet searches I tried before asking here
So I used the raw types for both operations As can be seen in the main code and everything worked fine. But I have seen so much "Don't use raw types". And this is why I ask: Is this an appropriate use of raw types? Should I do it a different way that DOESN'T break the reflection? It breaks the reflection because manually specifying the type parameter not only makes my code not run, it also means ONLY that concrete class can be used. I reflected so that I could use anything that implements the generic interface. I don't want to only be able to use specific concrete instances. I've tried searching stack overflow for whats in my title and other similar things. I think this might be related to type erasure but I'm honestly not sure of that. Nothing else really addressed this problem because nothing talked about generics, parameterized types and reflection all at once (the crux of my problem). I have been told generics and reflection don't play well together but this code works anyways and works the way I want it to. It works well. I just want to make sure I'm not doing something TERRIBLY wrong.
The Goal.
To gain an Understanding of my current usage of raw types so I know I'm doing it the right way. By 'Right' I mean the opposite of what I define as the 'Wrong' Way below. An example of what 'Understanding' I seek is:
To understand why puesdo code along the lines of:
ConcreteClass forname(myPropertiesFileObject.get(ConcreteClassname)) as subClass of (MyGenericInterface);
MyRAWGenericInterfaceType ConcreteClassInstance = (MyRAWGenericInterfaceType) ConcreteClass.newInstance( Insert generic Type constructor arguments here);
RAWCollectionType someCollection = RAWCollectionType concreteClassInstance.CallingAMethod(Insert generic Type method arguments here);
Uses Raw types where RAW is contained in the Interface or collection type name. This is as opposed to doing it in some way that doesn't use raw types but doesn't break the point of the reflection, to decouple the interactions between these classes. Specifying the parameters with hard code would 'break the reflection' in this case. Additionally I'd like to understand Why specifying parameters (even if I know thats not what I'm going to do) for these RAW types in the pusedocode above causes the errors listed above in the question, Namely why is the result of CallingAMethod erased when supplying the actual parameters to the RAWCollectionType that the method returns? The root problem is that when I supply type parameters to RAWCollectionType when I declare it, it refuses to be updated by what CallingAMethod returns and I Don't Understand Why. It takes the return value, but if the body of the method CallingAMethod has the returned value passed in as an argument, updated inside the method and then returned, the return that I receive doesn't have the updates. CallingAMethod in this example would be like if I hada list like:
[1,2,3]
and inside the method I had something like:
foreach(thing in list){
thing += 1
}
and then I returned the list, the return I'd get when specifying parameters would be [1,2,3] and when using raw types it would be [2,3,4] like I desire. I'm asking this because I've heard bad things about using raw types.
Additionally I want to make sure that my use of raw types is not horribly wrong and that it works because it's SUPPOSED to work. Maybe I've just gotten good at the whole reflection and generics thing and found a valid use for raw types, or I could be doing something so horrible it warrants my arrest. Thats what i intend to find out. To clarify, by wrong I mean:
bad design (should use a different way to call my methods reflectively and also use reflective classes that use generic interfaces)
inefficient design(time complexity wise, code line wise or maintainability wise)
there is a better way, you shouldn't even be doing this in the first place
If any of those reasons or something I missed popped out when you read this code then TELL ME. Otherwise please explain then why my use of raw types is Valid and isn't a violation of this question:[link]What is a raw type and why shouldn't we use it?
Java have type erasure, so your Map<A,B> in runtime is just a Map, same for CrossReferenceImplementation<Map<String, SalesRep>,Map<String, SalesRep>,Map<String, SalesRep>> is just a CrossReferenceImplementation.
This also means that you can cast any map to Map and just put any objects you want in it, so you can have Map<String, Long> that is actually storing objects of Map<Cookie, Fish> type, and this is why you need to be careful with raw types and reflections.
You can't really use reflection and generics normally - you will always have some unchecked code then, but you can limit it to minimum and make it kind of type-safe anyways.
Like you can create own method to get field: (this is a bit of pseudocode, I will skip all possible exceptions, etc)
public class FieldAccessor<O, T> {
final Field field; // + private constructor
public T get(O object) { return (T) field.get(object); } // unsafe, bu we validated this before constructing this accessor
public static <O, T> FieldAccessor<O, T> create(Class<? super O> definingClass, Class<? super T> fieldClass, String fieldName) {
Field field = definingClass.getDeclaredField(fieldName);
if (field.getType() != fieldClass) {
throw some exception;
}
return new FieldAccessor<>(field);
}
Then you have all the needed validation before you need to use that field, and it will already return valid type. So you can get some value of valid type and add it to normal generic Map instance.
FieldAccessor<X, A> keyAccessor = FieldAccessor.create(X.class, A.class, "someProperty");
FieldAccessor<Y, B> valueAccessor = FieldAccessor.create(Y.class, B.class, "someOtherProperty");
Map<A, B> myMap = new HashMap<>();
mapMap.put(keyAccessor.get(myXValue), valueAccessor.get(myYValue));
This way you have type safe code that still works on reflections - it might still fail at runtime if you will provide invalid types, but at least you always know where it will fail - as here FieldAccessor is already checking all the types in runtime to ensure that you will not do something stupid like add Integer to Map<String, Long> as this might be hard to debug later. (unless someone will use this accessor as raw type, as .get isn't validated - but you can add that by passing definingClass to constructor and checking object instance in get methods)
You can do similar stuff for methods and fields that use generic types (like field of Map<X, Y> type, this FieldAccessor would only allow you to check if it is some kind of Map) - but it would be much harder as API for generics is still a bit "empty" - there is no build in way to create own instances of generic types or to check if they are assignable. (libraries like gson does that so they can deserialize maps and other generic types, they have own implementation of java generic type representation interfaces, like that ParameterizedType and implemented own method to check if given types are assignable)
Just when you are using reflections you need to always remember and understand that you are the one responsible for validating types, as compiler can't help you here, so that unsafe and raw typed code is fine as long as you have logic that validates if this code will never do something really unsafe (like that passing wrong type to generic method, like Integer to map of Long).
Just don't throw raw types and reflections in the middle of some normal code, add some abstraction to it, so it will be easier to maintain such code and project.
I hope this somewhat answers your question.
I'm parsing JSON strings sent from my WLAN speakers using Java/Jackson, whose format is unfortunately varying. While there's some static and not so important part of the response which is quite easy to parse, the really essential stuff may have many different structures, depending on the command sent to the speaker.
For that purpose, I think jackson's TypeReference() is best to map the current structure to key/value pairs and then see what we have. Problem is that I don't really understand how TypeReference works, and I don't want to blindly use "magic" functions where I have no clue what's actually happening.
The reference states that sub classing is used, but the following syntax is not really clear to me, especially and foremost the empty curly brackets at the end:
TypeReference ref = new TypeReference<List<Integer>>() { };
Can someone explain to me how this class works? Many thanks in advance!
Type Reference / TypeToken / ParameterizedTypeReference
TypeReference is from Jackson, there's also Gson's TypeToken and Spring's ParameterizedTypeReference.
Why we need it?
The purpose is to capture the generic type and retain it at runtime, because generics only works at compile-time (type erasure), so at runtime, in your example, this List<Integer> has been erased.
Instantiate a direct subclass of an abstract class i.e TypeReference
The ending class body {} is part of a class instance creation expression to create an anonymous class. The reference is JLS - Section # 15.9.1.
15.9.1. Determining the Class being Instantiated If the class instance creation expression ends in a class body, then the class being
instantiated is an anonymous class. Then:
If T denotes a class, then an anonymous direct subclass of the class
named by T is declared. It is a compile-time error if the class
denoted by T is a final class.
In either case, the body of the subclass is the ClassBody given in the
class instance creation expression.
The class being instantiated is the anonymous subclass.
You use a CustomFieldSerializer to define custom serialisation and deserialisation for an object.
It's ostensibly easy to define custom serialization for your class Xxx:
create a class called Xxx_CustomFieldSerializer that extends CustomFieldSerializer<Xxx>,
implement abstract methods serializeInstance and deserializeInstance, and optionally instantiateInstance.
This generates a gazillion compile errors that boil down to the following:
subtype Custom Field Serializer 'Xxx_CustomFieldSerializer' does not define a deserialize method: 'public static void deserialize(SerializationStreamReader reader,Xxx instance)' (reached via Xxx)'
It wants you to create static methods that do exactly what the implemented methods do. Obviously one delegates to the other, but it means you can't extract out all of this boilerplate for similar types Xxx.
Why? Is this just left over from an old version of GWT or something? Is there a way to avoid having to write all the extra stuff?
Thanks to Thomas Broyer for finding this. It's just a limitation in GWT.
See: com.google.gwt.user.rebind.rpc.CustomFieldSerializerValidator
See: http://code.google.com/p/google-web-toolkit/issues/detail?id=7331&thanks=7331&ts=1335182609
I have a need to have XYZIdentifier object which will be used in composition in other class to identify the object.
However, Depending on the use-case (a variable in the client object), the identifier can be either a String, long, or even a Class.
Something like IntegerIdentifier, StringIdentifier, FooIdentifier and some interface defined which can be generic.
How can I create this design?
Not sure what your full context is, but part of the solution may involve generics to fetch the kind of result you need, like:
public <T extends IdentifierBase> T getIdentifier(Class<T> kindYouWant) { ... }
The idea being you tell it which flavor you need, and it could either convert with best-effort, or return Null if that kind isn's available.
Like I said, not sure of your whole question...
I've got an interface MigrateScenario with its methods. I also have its implementation MigrateScenarioImpl. The instance of MigrateScenarioImpl is being serialized and then passed as a byte[] to some web-service. On the service side, when I try to do this:
Object obj = (new ObjectInputStream(digitalObject.getContent().getInputStream())).readObject();
MigrateScenario mgrScenario = (MigrateScenario) obj;
and what I get is that MigrateScenarioImpl class is missing in the classpath. The obj variable contains that object and the interface should blindly ask for the corresponding methods, since the object "knows itself" how to execute them. However, when I add the MigrateScenarioImpl to the classpath, then all works fine. Am I missing something here?
Would appreciate any help, thanks!
Knowing just the interface doesn't help the JVM know what to do. It needs the Impl to know what to actually do, not just what methods are available.
You can't deserialize a class without having that class known to the classloader (e.g. by being on the classpath). The code for the class itself is not serialized, it is expected to be known on the other end.
When you deserialize the object, Java needs to instantiate and initialize in an instance of the class. Interfaces cannot be instantiated, so Java must instantiate the implementation class. The serialization of a class contains instance data (the values of non transient instance variables), not the code of implemented methods, so there are no methods for the interface to point to.