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
{
}
Related
< T > T foo(P p) {
...
}
I'll get different types of return from foo according to the parameter I inserted, which means T changes according to p.
Then I try to call this function and use its return result.
Class x = foo(p);
What should I write in substitute of Class here?
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
Let me give the exact sample here.
public <T> List<T> getProperty(Property property) {
switch(property) {
case NAME: List<Name> names = new ArrayList<Name>();
names.add(this.name); return (List<T>) names;
case PHONE: return (List<T>) this.phones;
case EMAIL: return (List<T>) this.emails;
case ADDRESS: return (List<T>) this.addresses;
case NOTE: List<Note> notes = new ArrayList<Note>();
notes.add(this.note); return (List<T>) this.note;
default: return null;
}
}
public enum Property {
NAME, PHONE, EMAIL, ADDRESS, NOTE
}
public List<Entry> search(Property property, String s) {
if(this.isEmpty()) {
return null;
}
List<Entry> result = new ArrayList<Entry>();
for(Entry e : entries) {
if(e.getProperty(property) != null) {
for( **Object** p : e.getProperty(property)) { //What should I write instead of Object
if(p != null) {
if(p.containString(s)) { //there'll be errors if use Object. Need to know p's class.
result.add(e);
}
}
}
}
}
return this.nonDuplicatedResult(result);
}
I'm really not sure what you're asking. You haven't explained your use cases at all and haven't given us much code to look at. It's difficult to provide useful feedback from within the fog of obfuscation.
Generally speaking, if you want a method that returns a different object depending on the value of a supplied argument, then what you're probably talking about is a static factory method which can return any object that is a subtype of the method's return type. It is convenient to make such objects a part of an interface-based type system (eg. the static factories for the EnumSet class).
The use of an interface-based type system is actually necessary if you wish to return an enum, because enums cannot be part of a class hierarchy, but they can implement an interface that forms an interface-based type system.
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
No it isn't. The return type is P. You're over-thinking this. The 'enum' case isn't a job for Generics at all.
Assuming you have an finite number of return types, you could just check through each one using instanceof to see if the returned value is of a certain type. So in this case Object would substitute class, then you could later cast it.
What is happening is basically with that method definition, what you are saying to the compiler is that your method will return whatever the parameter assignment declares itself to be. You can do that, but how your method is implemented will boil down to a compiler warning, as you can't actually ensure that you are generating the appropriate type - since you don't know it, it is never passed to the method, and erased at compile time.
More typically what you would do is:
<T extends P> T foo(T p) {
...
}
Now you get an object of the right type as a parameter, so you have some idea of what to return. That concept has little utility with enums, though.
Here is a real world example of where you could use the method definition you posed in your question:
public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
}
Of course such a method generates a compiler warning. Now, what you are saying here is that the caller will define a variable, and will be sure to pass in at least one interface of the type they define. If they don't, they will end up with a ClassCastException at runtime, but you avoid calling code that knows what it is doing from explicitly casting.
It is debatable if that is a good idea.
So the short answer is that you can define the Class to be whatever you want - the compiler will accept anything - but if the method doesn't return the correct type, you will get an exception at runtime, so it is all about how you implement the method. Rarely can a method be smart enough to return the right thing without the correct type as a parameter. And if you can't pass in an appropriate parameter declared with the generic type to the method, you will have to deal with a compiler warning in order to return anything (other than null).
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
I am having a slight inconvenience when working with generics in Java. Please consider the following code:
/**
* MyElement class is simply a wrapper for a generic object.
*/
public static class MyElement<T> {
public final T OBJ;
public MyElement(T obj) {
this.OBJ = obj;
}
}
/**
* MyElementList contains an array list of MyElements of the given type, T.
* This represents a class that uses a list of MyElements of a certain type,
* and this list can be accessed in an unmodifiable format.
*/
public static class MyElementList<T> {
//Properties
private List<MyElement<T>> elementList = new ArrayList();
//CTOR
public MyElementList(List<MyElement<T>> initElements) {
elementList.addAll(initElements);
}
//Getter
public List<MyElement<T>> getElements() {
return Collections.unmodifiableList(elementList);
}
}
public static void main(String[] args) {
//New list of elements
//Notice that I did not explicitly specify the type for 'MyElement'
List<MyElement> theElements = new ArrayList(Arrays.asList(
new MyElement[] {
new MyElement("E 1"),
new MyElement("E 2"),
new MyElement("E 3")
}
));
//Also notice I did not explicitly specify the type for 'MyElementList'
MyElementList theList = new MyElementList(theElements);
//The following does not work.
//It seems to not work because theList.getElements() returns a 'List'
//not necessarily a 'List<MyElement>' which is what I would expect it to
//return...
//Why???
for(MyElement e : theList.getElements()) {
System.out.println(e.OBJ.toString());
}
//Currently my work around is to do the following, but I do not like
//having to introduce another variable, and I would rather just do the
//one above
List<MyElement> listOfElements = theList.getElements();
for(MyElement e : listOfElements) {
System.out.println(e.OBJ.toString());
}
//How come the first 'for-each' loop method does not work?
//Is there anyway I could get it to work?
//THANK YOU!
}
In the main method, if I don't specify the type parameter for 'MyElementList' the 'getElements()' method only returns a 'List', not a 'List<MyElement>'. This is inconvenient because if I want to iterate through each 'MyElement' I need to introduce another variable as a temporary list, shown in the code.
Why doesn't the 'getElements()' method return a 'List<MyElement>'?
Without making significant changes to 'MyElementList' Is there anything I can do to fix this?
Is this a bad design practice?
The IDE I am using is Netbeans 7.2
Thanks in advance!
EDIT
Thank you all for your quick responses. I am very impressed with the community here. I have concluded the following:
If a generic hint is not specified, Java ignores ALL other associated generic hints for a class - which is kind of lame, but I can live with it.
When using generics, it is a best practice to actually specify the generic type when creating an instance of the class. This seems to be the most object oriented solution.
Thanks again!
If you change MyElementList to look like
public static class MyElementList<T extends MyElement> {
//Properties
private List<T> elementList = new ArrayList<T>();
//CTOR
public MyElementList(List<T> initElements) {
elementList.addAll(initElements);
}
//Getter
public List<T> getElements() {
return Collections.unmodifiableList(elementList);
}
}
It should work.
EDIT Generics can be seen as compile time hints in Java, since Java erasure will convert generics to Object. Updating your class as above will tell the compiler only elements which extend MyElement fit the list and for(MyElement e : theList.getElements()) will work.
EDIT 2 As pointed out by others (sorry, I didn't see it at first glance) also change the raw declaration to:
MyElementList<MyElement> theList = new MyElementList<MyElement>(theElements);
Te first does not work because getElements returns a List<?> for the raw type
The second works because you assigned it to a List<MyElement>, ignoring the warning. Ignoring was ok because you know what it contains, but the compiler doesn't.
Instead of using
for(MyElement e : theList.getElements()) {
System.out.println(e.OBJ.toString());
}
you could use
for (Iterator<MyElement> it = theList.getElements().iterator(); it.hasNext();) {
MyElement e = it.next();
System.out.println(e.next().OBJ.toString());
}
which makes your compiler compliant.
But I would prefer to specify the types that your classes require when instantiating/accessing them (and your compiler too, I guess ;)).
Why doesn't the getElements() method return a List<MyElement>
Because MyElement is typed!
Without making significant changes to MyElementList Is there
anything I can do to fix this?
You can probably use a wildcard:
List<MyElement<?>> someList = getElements();
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");
I have this class, just for the purpose of learning:
public class MyClass{ //Looking for a solution without making my class also generic <Type>
//Private Arraylist var to hold the value called myvar
public MyClass(ArrayList<MyDesiredType> incoming) {
//CODE myVar=incoming
}
public MyDesiredType getType() {
return myVar.get(0);
}
}
Is there any way to infer in the incoming object from the constructor to the return type of the method without warnings and castings and loosing typesafeness, but most of all WITHOUT making the whole class GENERIC (seems redundant to me)? If not, why should I think this is not feasible for the compiler?
This is a reformulated question I already did, but it was my first one and I learned how to expose it clear because nobody understood. I tried to edit later the original question but everything was buried. I changed and simplified the example and try to put it easy. Original question: Java Generics Silly Thing (Why cant I infer the type?).
If there is any problem just tell it to me and I will remove it.
No, there is not. How would the compiler know what type to return? The generic type of ArrayList in the constructor will not be known during compile time. You either have to make the whole class generic or take another approach.
Consider this:
public class Test {
public static void main(String[] args) {
List<String> arrList = new ArrayList<String>();
arrList.add("FOO");
Test test = new Test(arrList);
String testStr = test.returnWhat();
System.out.println("testStr");
}
private final List myList; //warning
public <T> Test(List<T> ttype) {
myList = ttype;
}
public <T> T returnWhat() {
return (T) myList.get(0); //warning
}
}
This works but gives you warnings on the marked lines. So, really there is no way to achieve what you are describing without making the whole class generic.
Because, what if:
public class Test {
public static void main(String[] args) {
List<String> arrList = new ArrayList<String>();
arrList.add("FOO");
Test test = new Test(); // now what?
String testStr = test.returnWhat(0); // no warning...
JPanel p = test.returnWhat(0); // goes through without warning, real nice...
test.returnWhat(0); // returns Object
Test test2 = new Test(arrList);
test2.addElement(new Object()); // boom, inserted object into list of string.
String nono = test2.returnWhat(1); // the universe goes down. assign an object to string without warning. even
// though one COULD think the class is generic.
}
// private List<T> myList = new ArrayList<T>(); compiler error, T is unknown
private List myList = new ArrayList();
public Test() {
myList.add(new Object());
}
public <T> Test(List<T> ttype) {
myList = ttype;
}
public <T> T returnWhat(int index) {
return (T) myList.get(index);
}
public <T> void addElement(T el) {
myList.add(el);
}
}
The second one doesn't compile when myList is made generic. How could the compiler determine the type of <T> in the case where the default constructor is used?
Further, this could lead to serious problems with Objects in collections that rely on the fact that only certain types are inserted.
This will generate the following exception:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Object cannot be cast to java.lang.String at
Test.main(Test.java:27)
Did I manage to convince you?
Real nice question, btw. I had to think about this one quite a bit.
When you say that you want the compiler to "infer in the incoming object from the constructor to the return type of the method without warnings and castings and loosing typesafeness", it seems that you are saying that it should infer the result of getType() from the input of the constructor. If both happen in the same function, it could. The problem is that the object may not exist in only one function, and so the extra type information (the generic type) is needed to pass this kind of object between functions.
For example, if I want to write a function that takes a MyClass object, I need to know what getType() will return so I can use the returned value. By adding a generic type of MyClass we are giving a description to what it holds.
Another way to look at it is that MyClass is a container. By adding generics, we are saying it is a container of a specific type of thing, and so we can more easily predict what we will get out of it.
There is no way for the compiler to know at runtime what type your arraylist is. I really dont see the problem using something along the lines of this:
public class MyClass<TYPE> {
private ArrayList<TYPE> incoming;
public MyClass(ArrayList<TYPE> incoming) {
this.incoming = incoming;
}
public TYPE getType() {
return incoming.get(0);
}
}
This way you can do:
ArrayList<Integer> numbers = createListOfNumbers();
MyClass<Integer> myClass = new MyClass<>(numbers);
Integer number = myClass.getType();
Or am i misinterpreting the question and you want to know the class at runtime?
No, if you want a class that can hold a list of a parameterized type.
Yes, if you want a class that can hold a list of exactly one type. You can declare that type explicitly in the field, constructor and accessor.
What you're forgetting is that not all code that you may run against is visible to the compiler! Jars can be added, removed, substituted at run time, that the compiler never saw. You may compile against an interface that is just:
public interface MyClassFactory {
MyClass getInstance();
}
Then at runtime you supply into the JVM an implementation. So the compiler never saw the actual code creating the MyClass that you will be using, so there is no way to perform such a compile time inference. You must either make the class generic or accept that there will not be type safety.