I have a set of classes that implement a certain interface. I have put all those classes in a Hashtable ht like this:
ht.put(str,backend.instructions.ADC.class);
But when I call the get() function of the hashtable and try to cast the object as the Interface's object, I am getting a ClassCastException:
InsInterface4 obj=(InsInterface4) ht.get(str);
How can I resolve the same? I have to call functions of the class but, I am not even able to cast properly? What is wrong in this?
Because you are putting a Class and you try to get an Interface4. If you want to have instances, rather than definitions inside the map, use: t.put(str, new ADC()). A few notes:
You can also use generics to guarantee that you put the correct things at compile time: Hashtable<String, Interface4>.
Prefer HashMap to Hashtable
backend.instructions.ADC.class is a Class, not an instance of that class.
You can do
Class<InsInterface4> clazz = (Class<InsInterface4>) ht.get(str);
// if there is a default constructor
InsInterface4 obj = (InsInterface4_ clazz.newInstance();
You have put the definition of the class in the table. You need to put actual instances of the class.
backend.instructions.ADC anAdc = new backend.instructions.ADC();
someOther.instructions.OTH anOth = new someOther.instructions.OTH();
ht.put("adc", anAdc);
ht.put("oth", anOth);
InsInterface4 obj=(InsInterface4) ht.get("adc");
Related
I am working on ES5 through java, and am trying to add context to a CompletionSuggestionBuilder. I have a map of String objects that need to be added. The code I have so far is -
Map<String, String> context = ...
CompletionSuggestionBuilder csb = SuggestBuilders.completionSuggestion(field).text(value).size(count);
How do I add context objects to csb? I think the method to use is -
csb.contexts(Map<String, List<? extends ToXContent>> queryContexts)
But I don't know how to get from my map to the map to pass as arguments to the contexts method.
You can create Map<String, List<? extends ToXContent>> like this;
Collections.singletonMap("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build()))
I think currently supported types that extend ToXContext are CategoryQueryContext and GeoQueryContext
The strange thing here is that if I create a local variable and pass it to the contexts it does not work. So, I just passed it directly to the contexts it does work.
Full example would be like this:
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg").contexts(Collections.singletonMap("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").setBoost(3).build(), CategoryQueryContext.builder().setCategory("cat1").build())));
It is all written in their test cases. You can take a look at it:
https://github.com/elastic/elasticsearch/blob/master/core/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java#L290
Hope it helps.
I wish to instantiate a java class that I have defined in my domain and I want to use it from my FTL code in this way, but I'm getting an error.
<#assign myClassInstance = "com.domain.MyClass"?new())>
Is it possible? What I should change to do it?
MyClass doesn't implements the TemplateModel
Thanks!
There's no built-in function for instantiating arbitrary non-TemplateModel classes... maybe there should be a setting to allow that for ?new. Anyway, for now you can write a TemplateMethodModelEx that does that, and then you can pull that into some of your commonly included/imported templates like <#assign unrestrictedNew = "com.example.UnrestrictedNewMethodModel"?new()> (or just put the instance into the data-model or into the Configuration as a shared variable) and then you can do <#assign myClassInstance = unrestrictedNew("com.domain.MyClass")(arg1, arg2, argN)> in your templates. There are two tricky parts in implementing such a TemplateMethodModel. One is resolving the class name to a Class, for which I recommend env.getNewBuiltinClassResolver().resolve(className, env, null), where env is the current freemarker.core.Environment object. The other is calling the constructor, as then you have to convert parameter values and possibly chose an overloaded constructor. For that I recommend calling ow = env.getObjectWrapper(), see if ow instanceof BeansWrapper (throw exception if it isn't), then do return ((BeansWrapper) ow).newInstance(cl, arguments).
I'm having trouble to find how to typecast the dynamically created class while using reflection.
String s;
...
Class unknownClass = Class.forName(s);
Constructor defaultConstructor = unknownClass.getConstructor(null);
Object retobj = defaultConstructor.newInstance(null);
retobj.Writeout(); // This won't work since;
The object class does not have a method called Writeout, but that is the name of the method which is shared by nine other possible classes that is dynamically created here (needless to say every Writeout method does a seperate thing). Any suggestions ? Thx in advance for your time.
Use reflection Luke...
Method writeOutMethod = unknownClass.getMethod("Writeout", new Class[]{});
writeOutMethod.invoke(retobj, new Object[]{});
Or, ensure that your objects implement a well known interface (the clean approach).
The 9 classes should all implement a single interface (let's call it Output) which declares the writeOut() method. The code would thus be:
Output retobj = (Output) defaultConstructor.newInstance(null);
retobj.writeOut();
Note that you could just use unknownClass.newInstance() to invoke the no-arg constructor.
Side note: please respect tha Java naming conventions: methods start with a lower-case letter.
Cast it:
((YourObjectWithThatMethod) retobj).Writeout();
EDIT (see the comment from Kevin Welker):
If all of your 9 classes implement the same interface, you can cast every class to that interface:
((YourInterface) retobj).Writeout();
If all nine classes share a super-class or an interface which declares/implements writeOut then you can cast retobj to that interface and then call it.
public interface Writable {
public void writeOut();
}
Then each class needs to have in the class declaration.
class MyClass implements Writable {
}
Then you can say
((Writable) retobj).writeOut();
In java i have a bean object(type unknown) i want to put the values of members of that bean into one HashMap with class members as key.Without using reflection can i do that if so how ? otherwise tell me a good way to do it using reflection
beanObject = { name="raja",age="20"} to haspMapObj = {name="raja",age="20"}
As peoples you said i tried introspector:
thank you for your answer and advise friends.
Class myClass =myObj.getClass();
info = Introspector.getBeanInfo(myClass);
for ( PropertyDescriptor pd : info.getPropertyDescriptors() ){
String name = pd.getName();
System.out.println("*************"+name+","+ pd.getValue(name));
}
but the above is print only the name the value's is coming as null. bcoz we are passing only the class type not the object reference. how do we do to get the value?
You can use the Introspector to get all the fields of a bean and their values. (This wraps reflection)
I think you can't do it without reflection. With reflection you can do something like this:
Map<String, Field> map = new HashMap<String, Field>();
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
map.put(field.getName(), field);
}
I do not see any possibility without using reflection at least indirectly via frameworks.
If you take a look at the Apache Commons Beanutils you might find some helpful methods:
http://commons.apache.org/beanutils/
More specified:
http://commons.apache.org/beanutils/v1.8.3/apidocs/org/apache/commons/beanutils/BeanMap.html
Best regards!
You can use introspection, which is based on reflection:
http://download.oracle.com/javase/6/docs/api/java/beans/Introspector.html
But what exactly do want to do in the end? Maybe there is a better way...
To get the value from a PropertyDescriptor pd:
Object value = pd.getReadMethod().invoke(myObj, new Object[]{});
Note, some time ago I wrote a utility class, which you might find useful:
http://softsmithy.sourceforge.net/lib/docs/api/org/softsmithy/lib/beans/BeanIntrospector.html
I have a string with the name of a class, is there a way (writing in Java) to use that string when creating a new instance of that class, to do something like this:
object obj = new dataInString.
So the dataInString is parsed from the string.
Do you mean something like Class.forName(String)? Quoting the javadoc of the method:
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.
For example, the following code fragment returns the runtime Class descriptor for the class named java.lang.Thread:
Class t = Class.forName("java.lang.Thread")
A call to forName("X") causes the class named X to be initialized.
And then, call Class#newInstance() on the returned Class (it must have an empty constructor).
Creates a new instance of the class represented by this Class object. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized.
Assuming that the class has a no-args constructor, then the following should do the trick
Class<?> clazz = Class.forName("someclass");
Object obj = clazz.newInstance();
If you need to create the object using a different constructor, then you will need to do something like this:
Constructor<?> ctor = clazz.getConstructor(ArgClass.class, Integer.TYPE);
Object obj = ctor.newInstance(arg, Integer.valueOf(42));
There are a number of checked exceptions that need to be handled in either case ...
You can use reflection.
Use reflections to instantiate objects. A simple class.forName("com.blah.blah") should be a good starting point to look for more information on reflections.