how to relate string to object instances in java - java

I have a code block where i deserialize incoming data and then i have to cast this into some known class object, so for that reason i do something like this:
if (object instanceof MyClass) {
Myclass data = (MyClass)object;
}
it works fine, however now i have a situation where there could be different type of calsses. So is there a way to do the comparison based on "String":
if (object instanceof "String") {
String data = (String)object;
}
the problem is in this case, the user will specify the class object name, so how can i do that?
Should i force user to initiate a dummy object and then pass to my method or is there a way to initialize null object with String, any ideas?

It's smelly, ugly, and I don't like it, but you can use Class#forName() and Class#isInstance(Object).
if (Class.forName("java.lang.String").isInstance(object)) {
String data = (String)object;
}
You're still going to have problems with the cast, though. Class#cast() only gets you compile-time type safety when you've got a Class<T> – but you can only get a Class<?> from Class#forName().

you can use Class#forName() and Class#isInstance(Object). to accomplish this
Heres a sample code
FileDemo dd = new FileDemo();
Class object = Class.forName("com.FileDemo");
if(object.isInstance(object)){
//do your conversion
}

You can always do this:
if(object instanceof MyClass)
{
Myclass data = (MyClass)object;
} else
{
String data = object.toString();
}
By default every Object in java has a toString function that can be invoked. There is no need to cast to a String

See the "forname" method here: http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

Related

Dynamic Class to a Variable in Java : Converting JSON to Object based on type of JSON

I have different types of fields for an object which is stored as JSONB in the Database Table. I can load the whole table into an Object and need to convert them to POJO Objects.
My JSON to POJO method is
public static <T> T fromJson(String json, Class<T> clazz) {
try {
return OBJECT_MAPPER.readValue(json, clazz);
} catch (JsonProcessingException ex) {
throw new BadJsonException(ex);
}
}
Since I need to pass in the class, I am trying to write an elegant maintainable way to do this.
So, if I need to compare two values this works
public static Integer compareFieldValue(
String valueA,
String valueB,
ProjectFieldType fieldType
) {
FieldValue objA;
FieldValue objB;
switch (fieldType) {
case CURRENCY:
objA = JsonHelper.fromJson(valueA, CurrencyField.class);
objB = JsonHelper.fromJson(valueB, CurrencyField.class);
break;
case DATETIME:
objA = JsonHelper.fromJson(valueA, DateTimeField.class);
objB = JsonHelper.fromJson(valueB, DateTimeField.class);
break;
But a long Switch Case Statement doesn't look good. I am trying to have it in an Enum and return it but then I am getting Incompatible Types error
ProjectFieldType.java:[25,44] incompatible types: java.lang.Class<com.foo.model.projectfield.DateTimeField> cannot be converted to java.lang.Class<com.foo.model.projectfield.FieldValue>
In the enum the field class is defined as
private final Class<FieldValue> fieldClazz;
Every Enum value would have a Field Type associated with it.
DateTimeField implements FieldValue interface.
Not sure how to go about it. Java is not my first Language, Python is. So, its kinda confusing to me to figure out best ways to do these kinda things in Java World.
Thanks for the help
-Shaurya
ProjectFieldType.java:[25,44] incompatible types: java.lang.Class<com.foo.model.projectfield.DateTimeField> cannot be converted to java.lang.Class<com.foo.model.projectfield.FieldValue>
This just means that DateTimeField cannot be converted to FieldValue, because DateTimeField objects are not an instanceof FieldValue.
This method can be simplified by far. The approach is fine, but instead of passing an enum, you can pass in the class directly as below.
Make sure all the classes you are comparing implements Comparable Interface so that compareTo() method is overridden.
public static <T extends Comparable<T>> Integer convert(String a, String b,Class<T> co) {
T obj1 = JsonHelper.fromJson(a, co);
T obj2 = JsonHelper.fromJson(b, co);
return obj1.compareTo(obj2);
}
This can be invoked as
convert("Hello", "Anees",String.class);
String.class is taken as an example because it implements Comparable<String>

How to convert String to enum value when enum type reference is a Class<?>?

I have code which is setting values on an object using its setter methods. One of the setters takes an Enum type as the method parameter. The code looks something like this:
String value = "EnumValue1";
Method setter = getBeanWriteMethod("setMyEnumValue");
Class<?> type = setter.getParameterTypes()[0];
Object convertedValue = null;
if (type.isEnum()) {
convertedValue = convertToEnum(value, type);
} else {
convertedValue = ClassUtils.convertType(value, type);
}
return convertedValue;
The question is what to put in the convertToEnum method. I know I could "brute force it" by iterating the enum constants (or the fields) of the type object, matching the value. Am I overlooking a simpler way to do it using Reflection? (I looked at several examples, but didn't find any where the enum was only know via Class).
Off the top of my head:
Enum<?> convertedValue = Enum.valueOf((Class<Enum>)type, value);
This will convert a string to an enum constant of the Enum class of type
Edit: Now that I have a computer handy, I can see what actually works. Either of the below cases ran correctly without compiler warnings:
Enum<?> convertedValueA = Enum.valueOf(type, value);
Enum<?> convertedValueB = Enum.valueOf(type.asSubclass(Enum.class), value);
The second one calls asSubClass() which would do a runtime check to ensure that type is some enum class, but the valueOf() method has to make that check anyway in order to work correctly.
The following gave me a compile error:
Enum<?> convertedValueC = Enum.valueOf((Class<? extends Enum <?>>)type, value);
java: Foo.java:22: <T>valueOf(java.lang.Class<T>,java.lang.String) in java.lang.Enum cannot be applied to (java.lang.Class<capture#134 of ? extends java.lang.Enum<?>>,java.lang.String)
The intricacies of casting to wildcard types confuses me so I've probably tried the wrong cast. Plus the fact that it has no runtime effect means that it's easy to get it wrong and never find out.
You can use
Class enumType = ....
String name = ....
Enum e = Enum.valueOf(enumType, name);
e.g.
import java.lang.annotation.*;
public class Main {
public static void main(String[] args) {
Class enumType = RetentionPolicy.class;
String name = "SOURCE";
Enum e = Enum.valueOf(enumType, name);
System.out.println(e);
}
}
prints
SOURCE
Enum.valueOf(yrEnum, myString)
Returns the enum where myString is the name of the enum instance you want.
And yrEnum.values() returns an array of all the different possible Enums instances.

How to check Type in android

One of my function getting Type variable. sometimes it can be java.util.List<Test$MyClass> or java.util.List<java.lang.String> so how can I identify them?
if (type instanceof List) {
}
Both are List type but different type. So that above code does not work.
I want to distinguish between the two list types.
my main issue is https://stackoverflow.com/questions/15596112/implement-jsondeserializer-more-than-one-in-gson-in-android
I am using deserializer for that..
public class Data implements JsonDeserializer<ArrayList<MyClass1>> {
public ArrayList<MyClass1> myList1 = new ArrayList<MyClass1>();
public ArrayList<MyClass2> myList2 = new ArrayList<MyClass2>();
#Override
public ArrayList<MyClass1> deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
Debug.e("", type.toString());
ArrayList<Layoutmap> data = new ArrayList<Layoutmap>();
try {
if (json.isJsonObject()) {
// my stuff
return data;
} else {
return new Gson().fromJson(json, type);
}
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
}
above code works for public ArrayList<MyClass2> myList2 = new ArrayList<MyClass2>(); and myList2 is also i want to deserialize..
It's part of google Gson.
Yeah, the problem is that in Java an instance test against a type that is not reifiable is always an error.
For example:
if(o instance of List<E>)
where E is any type, will not compile.
You simply have to check that what's contained in the Lists are the same type, e.g.
if(list1.get(0) instance of String && list2.get(0) instance of String)
EDIT:
Not sure if there's a language barrier issue here (your question is hard to fully understand), but you should not need to make your method take an argument of type Type. As someone else mentioned, you have a bad design here. What you should be doing is simply defining how to deserialize each of your classes (if custom deserialization needs to be defined at all; that is, if the defaults won't work) and then get a list of those in the regular way with Gson.
I'm not super familiar with Gson, but it should be something like:
List<Class1> stuff = gson.fromJson(json, new TypeToken<List<Class1>>(){}.getType());
So, in other words, if each class has peculiarities that will make default deserialization not work, then there's no way (without a lot of gymnastics) to make a deserialize method work for every single type.
Also, don't combine all functionality into one. Getting an ArrayList<LayoutMap> should be separated from the functionality of deserializing each class.
try to use getClass() function on your type to find the class of an object on runtime.
for eg..
type.getClass().equals(java.lang.string)
You can just try something like :
for (int i=0; i<type.size(); ++i) {
if (type.get(i) instanceof String) {
// Do something here
}
}
This would check each element of the list and if its a string you could work on it.
Hopefully, type will be an instance of ParameterizedType. So you can use the method getActualTypeArguments().
I just find my solution .. I don't know it is better or not
I am comparing two Type variable like this...
if (type.toString().equalsIgnoreCase(
new TypeToken<List<Test.MyClass>>() {
}.getType().toString())) {
}else
{
}

How to parse a String variable into any data type in Java?

I want to build a method that can convert a String value to a given Field object data type through Java Reflection.
Here is my code:
String value = ...;
Class<? extends MyObject> clazz = getClazz();
Field f = clazz.getDeclaredField("fieldName");
boolean fieldIsAccessible = f.isAccessible();
if (!fieldIsAccessible) {
f.setAccessible(true);
}
f.getType().cast(value);
if (!fieldIsAccessible) {
f.setAccessible(false);
}
When I run this code at firs attempt, I receive this exception java.lang.ClassCastException.
I want to convert value to class java.math.BigDecimal.
What is my code missing ?
EDIT:
View the solution I came up with.
You could make this work for classes that have a string constructor like this:
f.getType().getConstructor( String.class ).newInstance( value );
In Java, there is no universal method for converting a String into an instance of an arbitrary class. Many classes simply don't support such a conversion. And there's no standard interface for those that do support it.
Your best bet is to look for a constructor that accepts a String as its sole argument. Of course, not every class provides such a constructor, and there's no guarantee that the semantics would be what you'd expect.
There is a Github project (MIT Licensed) called type-parser which does converting a string value to the desired data type
Here is the project description from GitHub
This is a light weight library that does nothing but parse a string to
a given type. Supports all applicable java classes, such as Integer,
File, Enum, Float etc., including generic Collection types/interfaces
such as List, Set, Map, arrays and even custom made types. Also
possible to register your own parsers.
As maerics said, you cant just cast a String to a data type. Is it possible you mean "how do I parse a BigDecimal from a String", to which the answer is...
fieldName = new BigDecimal(value);
The Class cast method throws the ClassCastException if the object is not null and it not assignable to type T. There are only a few types of variable to which a String reference is assignable, String, Object, Serializable, Comparable, and CharSequence.
Many, but not all, classes have ways of producing an object instance based on a String. In some cases, including BigDecimal, there is a constructor that takes a String representation of the new object's value. You could use the Class getDeclaredConstructor method specifying a single String argument, to get the Constructor object for such a constructor, if there is one. However, there is some risk that you will not get a useful object without e.g. calling some setXXX methods, and this approach is limited to those classes that have the right form of constructor.
You are presumably trying to solve some higher level problem, possibly related to serialization and deserialization. That problem may be much more easily solvable than your current problem.
Perhaps not answering the question how to do convert a String into a java type, as there is no generic way of doing it. But there is a library that can help you with this. See type-parser library. Here's how the above code sniped could look like:
String value = ...;
Class<? extends MyObject> clazz = getClazz();
Field f = clazz.getDeclaredField("fieldName");
boolean fieldIsAccessible = f.isAccessible();
if (!fieldIsAccessible) {
f.setAccessible(true);
}
TypeParser parser = TypeParser.newBuilder().build();
// parse value to whatever type f.getGenericType() returns
Object o = parser.parseType(value, f.getGenericType());
if (!fieldIsAccessible) {
f.setAccessible(false);
}
}
I also gone through same scenario. Pasting code which i have written after doing some research. Guys please give suggestion if you feel anything wrong.
private <T extends Object> T convertStringToType(String value,Class type){
if( type.equals(Double.class)){
return (T) Double.valueOf(value);
}
else if(type.equals(Integer.class)){
if(value.contains(".")){
BigDecimal bigDecimal= new BigDecimal(value);
return (T) (Integer)bigDecimal.intValue();
}
return (T) Integer.valueOf(value);
}
else{ // add other type which you need
throw new Exception("Invalid type");
}
}
You can create a small method using Supplier and read the String using Scanner:
private static <T> T getTokenValue(Supplier<T> supplier) {
return supplier.get();
}
String line = "12.0";
Scanner scanner = new Scanner(line);
double value = getTokenValue(scanner::nextDouble);
If we need to get the int, the call will be like,
getTokenValue(scanner::nextInt)
The code is a sample and can be improve using the vavr dependency and Try clause that can throw custom exceptions with more generic code.
Try.ofSupplier(supplier).getOrElseThrow(new RuntimeException("Custiome message"));
varv has a lot of control logic that can be used to write more generic code.
Here is the solution I came up with:
public static Object parse(String value, Class<?> clazz) throws NotSupportedException {
String canonClassName = clazz.getCanonicalName();
if (canonClassName.equalsIgnoreCase("java.math.BigDecimal")) {
return new BigDecimal(value);
}
// Add other supported classes here ...
throw new NotSupportedException("The class [" + canonClassName + "] is not supported.");
}
I found my answer in this thread: How to convert String object to Boolean Object? - you can parse strings to booleans using:
Boolean boolean1 = Boolean.valueOf("true");
boolean boolean2 = Boolean.parseBoolean("true");

Is there a way to define a generic method that checks for null and then create the object?

I'd like to write a method that checks where the argument is null, and if it is, returns a new object of that type. it looks like:
public static <T> T checkNull(T obj) {
if (null == obj) return someHowCreateTheObjectWithTypeT();
else return obj;
}
After some struggling and digging, I still can't get a way to achieve this, is it atually possible in java?
I thought about reflection at first. But I just can't get a Class instance when the object is null, and you can't create a Class without the type T's name...
Update:
I thought about passing a Class as a parameter, but that's not the best solution, as the following answers shows :)
My currunt solution is to use a defaultValue parameter:
public static <T> T checkNull(T obj, T defaultValue) {
if (null == obj) return defaultValue;
return obj;
}
Which is faster and safer than a reflection solution, and is the same verbose;
But then I have to systematically specify a DEFAULT_VALUE for all types of interest, which is not an easy work.
This is not possible. For generics to work in this manner, it has to capture at compile-time the type that it will be called with. However, null has no type so you won't be able to figure out T to instantiate it.
Now, you may be able to work around this also passing in the Class instance, but you will need some rather robust error handling using Reflection to ensure that type T is a concrete class and has a public parameterless constructor that you can invoke.
Generic information is compile time only and not available at runtime. You'd have to pass the Class of the object in as a hint, and the class would have to have a public default constructor. e.g.
public static T checkNull(Object o, Class<T> c) {
try {
return (o == null) ? c.newInstance() : o;
} catch (Exception e) {
return null;
}
}
Cannot be done. You must add an additional parameter of Class<T>, and then use it to reflectively new. The type T does not survive the compilation process.
As others have pointed out, this can't be done. However, Guava provides an equivalent to the default value you method you posted:
String foo = Objects.firstNonNull(someString, "default");
This differs slightly from your method in that firstNonNull will throw a NullPointerException if both arguments are null.
Another option would be to create a method that makes use of Guava's Supplier<T> interface or something similar:
public static T firstNonNull(T first, Supplier<? extends T> defaultSupplier) {
return first != null ? first : Preconditions.checkNotNull(defaultSupplier.get());
}
You could then use a Supplier that creates and returns a new default instance when and only when the first argument is null.

Categories

Resources