Java declare a class object from the string of that class? - java

I have a script provided from the client like this
segment-id Integer
segment-description String
Now I want to build a class with the following methods
Sample sample = new Sample();
// casting to the type specified in the script
(map.get("segment-id")) segmentId = sample.get("segment-id");
// Now it can be used as an Integer
Integer result = segmentId + 2;
Is it possible to do something like
Class<map.get("segment-id")> segmentId = new Class<map.get("segment-id")>();
Or any better solution...? I need a way create objects of specific type, which I don't know in advance.
My current solution is
public Integer getInteger(String key) {
return map.get(key);
}
but in this way I have to know in advanced segment-id is of type Integer.

You can use Class.forName() to get the class and .newInstance() to get a new instance:
Object createdObject = Class.forName("java.lang.String").newInstance();
or ...
Object createdObject = Class.forName("java.lang.Integer").newInstance();
If you need to know if it's a String:
if(createdObject instanceof String) {
String castValue = (String) createdObject;
...
}
if(createdObject instanceof Integer) {
Integer castValue = (Integer) createdObject;
...
}
But you could just test the incoming string:
if("java.lang.String".equals(nameOfClassToCreate)) {
....
}

Related

Get the data type of JSON element in Java

I get a JSON value from Kafka queue and I want to get the right data type to save it in the DB.
Value can be: String, int, double or array.
How can i detect automatically the right datatype and create a Java Object from it?
My first steps:
check if json is an array or not:
if (jsonValue.isJsonPrimitive()) {
// create new Object
//ToDo need to parse int, double not only to string
new ValueObject(time,jsonValue.getAsString);
} else if (jsonValue.isJsonArray()) {
//create new Object
//ToDo need to parse int, double string
new ValueObject(time,jsonValue.getAsJsonArray());
}
How can I design the ValueObject class to convert the value to the corresponding data type and return the right object?
Thanks for any ideas
have you tried:
//this instanciates an object of the getClass() method output
Object output = jsonValue.getClass().cast(jsonValue);
if that didn't work, you can try instanceof:
if(jsonValue instanceof int){
int output = (int) jsonValue;
}...
I hope that will do.
if you are using jackson lib, you can do like this:
JsonNode rootNode = objectMapper.readTree(json);
Iterator<String> fields = rootNode.fieldNames();
while(fields.hasNext()){
String field = fields.next();
JsonNode obj = rootNode.get(field);
System.out.println("value " + obj);
if (obj.isInt()) {
System.out.println("Integer");
}
if (obj.isDouble()) {
System.out.println("Double");
}
if (obj.isTextual()) {
System.out.println("String");
}
}

Java Reflection - get method without specific parameters type

I am trying to get the method by java reflection, but i don't want to be specific about the parameters classes in getMethod().
public Object prepareFilter(String filter, String sort) {
Class filterClass = this.filterClass;
try {
Method createCriteriaMethod = filterClass.getMethod(CREATE_CRITERIA_METHOD);
Method orderByClauseMethod = filterClass.getMethod(ORDER_BY_CLAUSE_METHOD, String.class);
Class criteriaClass = createCriteriaMethod.getReturnType();
Object filterObject = filterClass.newInstance();
Object criteriaObject = createCriteriaMethod.invoke(filterObject);
for (ExtFilterRequest extFilter : ExtFilterRequest.decodeJson(filter)) {
StringBuilder sb = new StringBuilder()
.append(AND)
.append(WordUtils.capitalize(extFilter.getProperty()))
.append(extFilter.getCondition());
Method criteriaConditionMethod = criteriaClass.getMethod(sb.toString(), ????); // earlier extFilter.getTransformedValue().getClass()
criteriaConditionMethod.invoke(criteriaObject, extFilter.getTransformedValue());
}
String orderByClause = ExtSortRequest.getOrderByString(sort);
if (orderByClause != null)
orderByClauseMethod.invoke(filterObject, orderByClause);
return filterObject;
} catch (Exception e) {
// later
}
return null;
}
I have the methods generated by MyBatis and I want to call them by reflection with the decoded json that comes from extjs client. It looks like: operator, value and property. Following code is working with string values but i dont know what to put in the place of question marks when I call for example method which get a Date value (decoded value is always a string).
Is it possible to call getMethod with some hmm.. generic type and get the specific method? Or should I do it in another way?
Summarizing - if I have method like this:
public Criteria andSomeReferenceIsEqualTo(String value) {
addCriterion("some_ref =", value, "someRef");
return (Criteria) this;
}
and this
public Criteria andPrimDateEqualTo(Date value) {
addCriterionForJDBCDate("prim_date =", value, "primDate");
return (Criteria) this;
}
I want to call them in the same way by method I specify earlier - even if its boolean, list of values, string or integer.

Using references like pointers in method call in Java

I encountered a problem while dealing with a call of a static method in another class.
So I have a function which is like follow, where I need to extract two values, a counter and an object :
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, DBObject result) {
int mergeCount = 1;
if (!cursorMap.isEmpty()) {
long ealiest = Long.MAX_VALUE;
for (DBObject o : cursorMap.keySet()) {
// do stuff to init tmp
...
if (tmp < ealiest) {
result = o;
ealiest = tmp;
}
// other stuff .....
}
return mergeCount;
}
here is how I call it in my other class :
DBObject result= null;
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result);
I checked in debug mod and result is set in getEarliestValue but when it's go out of the function call result is still null.
I thought that references where like pointers with the difference that we couldn't do arithmetic operation on the reference itself, but with this behavior it seems that even if we change the pointed value it still only in the local scope.
The only idea that I found was to put it in a List but this is neither elegant nor optimal.
Any suggestion ? Thanks in advance.
Passing result here is the same thing as passing null. You have to return this DBObject someway. For example, you can return something like Map.Entry<Integer, DBObject>. This could not be supposed to be a good solution, maybe you should create some class like BlahBlahResult, containing both int result and DBObject.
If you really-really want to pass it as a parameter, you may pass something like AtomicReference<DBObject> and set it inside the method:
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, AtomicReference<DBObject> result) {
int mergeCount = 1;
if (!cursorMap.isEmpty()) {
long ealiest = Long.MAX_VALUE;
for (DBObject o : cursorMap.keySet()) {
// do stuff to init tmp
...
if (tmp < ealiest) {
result.set(o);
ealiest = tmp;
}
// other stuff .....
}
return mergeCount;
}
...
...
AtomicReference<DBObject> resultReference = new AtomicReference<>(null);
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, resultReference);
DBObject result = resultReference.get();
In java "References to Objects are passed by value".
DBObject result= null;
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result); // here result --> null i.e, points to nothing
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, DBObject result) {
int mergeCount = 1;
if (!cursorMap.isEmpty()) {
long ealiest = Long.MAX_VALUE;
for (DBObject o : cursorMap.keySet()) {
// do stuff to init tmp
...
if (tmp < ealiest) {
result = o; // here (new)result --> o . (original)result-->null
ealiest = tmp;
}
// other stuff .....
}
return mergeCount;
}
the result parameter is a pointer. Java does not support pointer-to-pointer as in c/c++.
you can use a class contains a DBObject field, then pass this class to the method.
class Dummy {
DBObject result;
}
modify your getEarliestValue method, replace the argument DBObject result with Dummy dummy,
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, Dummy dummy)
and then replace code result = o with dummy.result = o
Dummy dummy = new Dummy();
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, dummy);
DBObject result = dummy.result;
this is a simulation of **ptr in c/c++
You can do the following:
DBObject result= new DBOBject() // or any initializing code;
/** don't try to change or re-initialize reference inside the method
because the result will still point to old one
*/
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result);
// use the result reference.
This is not specific for java also in the C++ or C pointer unless you use the & with pointer reference.
Note that it seems that the method cann't run alone with out DBObject instance so I think this method should be an instance method of Class DBObject and not a Util method,
For example:
int mergeCount = result.getEarliestValue(cursorList);

Get an existing object from a Map with a key

For an application written in java (Eclipse), I have created a Map where I save objects of a custom class.
This custom class is called Music and has this constructor:
public Music (String title, String autor, int code){
this.setTitle(title);
this.setAutor(autor);
this.setCode(code);
}
This class has 3 child classes: Vinyl, CD and cassette that extend it. Here is the CD class:
public CD(String title, String autor, String type, int code) {
super(title, autor, code);
this.setType(type);
}
Then, in other class called ManageMusic I have created some methods and the Map:
private final Map<Integer, Music> musicMap;
public ManageMusic() {
musicMap = new HashMap<Integer, Music>();
}
If I want to add an object to the Map, I have a method that basically in this example with the CD does:
musicItem = new CD(title, autor, format, newCode);
musicMap.put(newCode, musicItem);
The code in all theses cases is a number with which I refer to as a determined object to set it into the Map, delete it or get it from the Map.
Now, my question is: When I want to get an object from the Map and set it into a String, I am doing this:
String object = musicMap.get(code).toString();
This way I should be getting the object from the Map and casting it to a String.
How can I manage the case when the code passed doesn't exist in the Map?
How could I catch an exception or do something to tell the user that there is no element inside the Map with that code?
You can use Ternary operator ?:
String object = musicMap.get(code) != null ? musicMap.get(code).toString() : "No item found.";
Edit: (thanks to #user270349)
Even better approach
Music m = musicMap.get(code);
String object = (m != null) ? m.toString() : "No item found.";
You can check if the return value of get is null :
Music object = musicMap.get(code);
if (object == null) {
// do nothing
} else {
String str = object.toString();
}
You could also use containsKey() method :
if (musicMap.containsKey(code)) {
// your code
}
I am not sure if I understood but you can always do.
Music music = musicMap.get(code);
if( music != null )
String object = music.toString()
You can use containsKey method:
String str;
if(musicMap.containsKey(code)){
str = musicMap.get(code);
} else {
// do something
// str = "some string";
}
I would suggest to throw an exception when there is no element in map corresponding to key.
This exception can be caught somewhere in your application(depends on how exceptions are handled in your application) this type of implementation allows to easily display different types of error or warning messages to the user.
Music object = musicMap.get(code);
if (object != null) {
// do something
} else {
throw new NoCDFoundException("no.item.found");
}

Cannot find associated value in a hashmap from a passed in key

I am working with some existing code in my Eclipse project. In the method below called cardTypeForPbfValue(), I cannot find the key in the HashMap even though I can see it while debugging my the code. The pbfValueMap is populated as follows:
[1=ATM, 2=DEBIT, 3=CREDIT, 4=PAYROLL]
I'm not sure why I cannot get the associated value of CREDIT when I'm passing in a value of 3 in the cardTypeForPbfValue() below. I am actually getting a value of NULL.
Any help/direction would be appreciated.
Here is the code I'm working with:
public static enum CardType {
CREDIT(3),
ATM(1),
DEBIT(2),
PAYROLL(4);
CardType(int pbfValue) {
this.pbfValue = (short) pbfValue;
}
public static HashMap<Short, CardType> pbfValueMap = new HashMap<Short, CardType>();
static {
for (CardType cardType : CardType.values()) {
short value = cardType.pbfValue;
pbfValueMap.put(cardType.pbfValue, cardType);
}
}
public static CardType **cardTypeForPbfValue**(int pbfValue) {
CardType returnValue = pbfValueMap.get(pbfValue);
if (returnValue == null) {
returnValue = DEBIT;
}
return returnValue;
}
public short pbfValue;
}
You're looking up an Integer, but you put a Short into the map. Try this:
public static CardType cardTypeForPbfValue(int pbfValue) {
Short shortPbfValue = (short) pdbValue;
CardType returnValue = pbfValueMap.get(shortPbfValue);
...
}
Better yet, stop using int everywhere (or stop using short for the map) - just be consistent in the type that you want to use.
What I guess is that you are using Short as the key type whereas, you are looking for the value in HashMap with Integer key.That's why you are not getting the associated value for the entered key. To solve this your cardTypeForPbfValue method should be like this:
public static CardType cardTypeForPbfValue(short pbfValue)
And wherever, you call the method cardTypeForPbfValue pass the argument of type short to it. For example:
short s = 1;
CardType cType = cardTypeForPbfValue(s);

Categories