Im relatively new to Java, and I recently came across a syntax that I have never seen before.
public class loadSomeData extends AsyncTask<String, Integer, String>{ etc..}
The part that confuses me is the stuff between the <> brackets. I understand what each of the Types are used for in this class, but why declare them in the class declaration?
More specifically what is this: <DataType> called in Java so I can research it?
Thank you
You're looking for "generics" in Java.
In brief, a collection class (or any class, really) may declare a parameterized type using that syntax so that users of the class can ensure that only objects of the same type will be stored in its collections (or otherwise operated on by it).
Before generics there was no type safety on collections such as lists:
List numbers = new ArrayList();
numbers.add(Integer.valueOf(123)); // OK
numbers.add("foo"); // Uh-oh!
But now you can ensure that only the type(s) you declare can be added:
List<Number> numbers = new ArrayList<Number>();
numbers.add(Integer.valueOf(123)); // OK
numbers.add("foo"); // Compile-time error!
You are seeing Java's Generics feature. Here is a good tutorial: http://docs.oracle.com/javase/tutorial/java/generics/index.html
The <DataType> structure is referred to as the type paramaters of the AsyncTask class. AsyncTask is a genericized Java class. This means that it can use different generic classes in its operation. See the link above.
AsyncTask is a generic type, because it can be parameterized with types just as java.util.List, java.util.Set, and numerous standard Java classes.
Read the Java tutorial about generics to learn more.
It's useful to declare them in the class declaration because loadSomeData (which should be named LoadSomeData, or even better: SomeDataLoader) as a specialization of AsyncTask that handles String, Integer and String, and not any other types.
Related
I've just been diving into Java generics and have come across something puzzling. I have a List of Class objects. These Class objects are of classes that extend the class MyType. What I want to do is the following:
Class<? extends MyType>[] myArray = myList.toArray( Class<? extends MyType>[] );
Now I know this won't work. But how is it possible to create such an array? My trouble is that I need to pass this List as a Class array to a method. I'd rather avoid #SuppressWarnings and figure out if it's possible.
You can pass the list as such but not instantiate as such. Must be instanced with concrete class substitutiona but then be assigned to whatever the captures.
There is rule "don't mess arrays with generics". There is the restriction in Java that states that creation of arrays of parameterized types is not allowed. So, the answer for your question is no, you can't create an array of any generic types.
UPD: Consider using any collection type instead of arrays. They will work just fine.
Or you can (but better not do that though) use array of non-generic elements and then cast them to appropriate type, suppressing warnings.
You have to provide the concrete type here which you also should know because of the type of myList.
I know how to access generic types of fields using reflection: Just check if field.getGenericType() instanceof ParameterizedType.
But how can one check the same for an arbitrary object, not knowing where it was declared?
Generics apply to variable declarations, method return types, etc., not objects per-se. You can determine whether the Class of a particular object uses generics via myObj.getClass().getTypeParameters() but you can't determine what values of those type parameters the specific object instance was created with.
Objects do not store generic information per se, so the bytecode generated for new ArrayList<Integer>() is exactly the same as the one for new ArrayList<String>(). I mean exactly. This is what is called type erasure of Java generics. They are just desugared to new ArrayList().
But, in almost all other situations, type parameters are retained, like field/parameter/return type declarations. One of the cases that is retained and not erased is the super class of a class. So if you create a class that extends ArrayList<String> you can access that information at runtime.
But this seems overkill, doesn't it? A new class that extends ArrayList<String> and another one that extends ArrayList<String>, etc. seems impractical. Anonymous inner classes can make this much easier. So, if you want to keep the generic information, you just do new ArrayList<String>() {} instead of new ArrayList<String>(). You can call getClass().getGenericSuperclass() on the created object to get the generic info.
I have seen it mentioned on some places online that in some situations it is possible to use the reflection API to get back information about generic data types which I thought would be lost through type erasure.
I am looking for complete list of the situations where type erasure is not complete i.e. something is still accessible via reflection. A Good list of examples and associated reflection code that can get at the generic types would be excellent.
UPDATE http://tutorials.jenkov.com/java-reflection/generics.html had exactly the examples I was looking for.
I think it just comes down to this:
No object instance stores any type information.
The classes, however, retain all their generic signatures (otherwise you could not have any generic type checking at compile time)
So, using reflection, you can read the generic type information for a given class.
Example:
class MyList extends ArrayList<MyObject>{}
List<MyObject> x = new MyList();
Reflection will tell you that this is a List of MyObject (because this information is compiled into the MyList class).
but
List<MyObject> x = new ArrayList<MyObject>();
Reflection will not tell you anything useful (because the ArrayList class knows nothing about MyObject).
The general idea is that if you create a named or anonymous class that is a subclass of a generic type with particular types for the type parameters, then the subclass is not generic and not subject to type erasure. Assuming that you can get hold of the Class object for the subclass, you can use reflection on that object to find out what the parameter types are.
When you think about it, this is not really an "exception" to the erasure rule. Rather, it is arranging that the class in question is not generic by explicitly reifying it.
There are methods like these which require Class literals as argument.
Collection<EmpInfo> emps =
SomeSqlUtil.select(
EmpInfo.class,
"select * from emps");
or
GWT.create(Razmataz.class);
The problem presents itself when I need to supply generic specific classes like
EmpInfo<String>
Razmataz<Integer>
The following would be wrong syntax
Collection<EmpInfo<String>> emps =
SomeSqlUtil.select(
EmpInfo<String>.class,
"select * from emps");
or
GWT.create(Razmataz<Integer>.class);
Because you cannot do syntax like
Razmataz<Integer>.class
So, how would I be able to squeeze a class literal out of
EmpInfo<String>
Razmataz<Integer>
so that I could feed them as arguments to methods requiring Class literals?
Further info
Okay, I confess that I am asking this primarily for GWT.
I have a pair of GWT RPC interface Razmataz. (FYI, GWT RPC interface has to be defined in server-client pairs). I plan to use the same interface pair for communicating whether it be String, Integer, Boolean, etc.
GWT.create(Razmataz) for Razmataz<T>
complains that, since I did not specify T, GWT compiler treated it as Object. Then GWT compiler would not accept Object class. It needs to be more specific than being an Object.
So, it seems there is no way for me to tell GWT.create what T is because a Class literal is a runtime concept while generics is a compile time concept, Right?
Quote from Java Generics and Collections, section 7.2:
Class literals are also restricted; it is not even syntactically valid to supply a type parameter to the type in a class literal. Thus, the following fragment is illegal:
class ClassLiteral {
public Class<?> k = List<Integer>.class; // syntax error
}
Indeed, Java's grammar makes a phrase such as the preceding one difficult to parse, and it may trigger a cascade of syntax errors [...]
This syntax problem leads to an irregularity. Everywhere else that a reifiable type is required, you may supply either a raw type (such as List) or a parameterized type with unbounded wildcards (such as List<?>). However, for class tokens, you must supply a raw type; not even unbounded wildcards may appear. Replacing List<Integer> with List<?> in the preceding code leads to a similar error cascade.
So, you have no choice but use only raw types in class tokens, like
GWT.create(Razmataz.class);
You can't.
Use an unsafe cast:
Collection<EmpInfo<String>> emps =
(Collection<EmpInfo<String>>) someMethod(EmpInfo.class);
Someone left a short but concise answer here, which I was about to choose as the answer. Unfortunately, that person deleted that answer. If that person would be so kind to re-post that answer for me to select. In the mean time, let me state that answer and how I made use of it.
This is what I should have thought of,
Interface RazmatazString extends Razmataz<String>{}
GWT.create(RazmatazString.class);
Basing on the answer that was deleted,
I would have a basic Razmataz interface pair the does a lot of stuffs, which I am too lazy to repeat.
Abstract class Razmatazer{
.....
Interface Razmataz<T>{
// does a lot of RPC stuffs
}
Interface RazmatazAsync<T>{
// does a lot of RPC stuffs
}
RazmatazAsync<?> razmatazAsyncRPC;
}
The concept is not to instantiate razmatazAsyncRPC handle at the base class but at the derived class.
For T = String
StringRazmatazer extends Razmatazer{
Interface RazmatazStringAsync extends RazmatazAsync<String>{}
Interface RazmatazString extends Razmataz<String>{}
razmatazAsyncRPC = GWT.create(RazmatazString.class);
}
Otherwise I would have to repeat ~100 lines of code, ~50 each for Razmataz and RazmatazAsync, over various T parametric values of String, Map, Boolean, Integer, etc.
The basic premise for overcoming this hurdle was - I am lazy to repeat those lines.
this morning I came across this code, and I have absolutely no idea what that means. Can anyone explain me what do these <T> represent? For example:
public class MyClass<T>
...
some bits of code then
private Something<T> so;
private OtherThing<T> to;
private Class<T> c;
Thank you
You have bumped into "generics". They are explained very nicely in this guide.
In short, they allow you to specify what type that a storage-class, such as a List or Set contains. If you write Set<String>, you have stated that this set must only contain Strings, and will get a compilation error if you try to put something else in there:
Set<String> stringSet = new HashSet<String>();
stringSet.add("hello"); //ok.
stringSet.add(3);
^^^^^^^^^^^ //does not compile
Furthermore, another useful example of what generics can do is that they allow you to more closely specify an abstract class:
public abstract class AbstClass<T extends Variable> {
In this way, the extending classes does not have to extend Variable, but they need to extend a class that extends Variable.
Accordingly, a method that handles an AbstClass can be defined like this:
public void doThing(AbstClass<?> abstExtension) {
where ? is a wildcard that means "all classes that extend AbstClass with some Variable".
What you see here is something called Generics. They were introduced to Java in release 1.5.
You can read about them here and here. Hope this helps.
Imagine you're writing a List or Array class. This class must be able to hold elements of an unknown type. How do you do that?
Generics answers this question. Those <T> you're seeing can be read as some type. With generics you can write class MyList<T> { ... }, which in this context means a list that holds some type.
As an usage example, declare a list to store integers, MyList<Integer> listOfInts, or strings, MyList<String> listOfStrings, or one class you've written yourself MyList<MyClass> listOfMyClass.
What you are seeing is Java generics, which allows classes and methods to be parameterized by other classes. This is especially useful when creating container classes, since it saves you having to create separate classes for "a list of integers", "a list of strings", etc. Instead, you can have a single "list of some type T, where T is a variable" and then you can instantiate the list for some specific type T. Note that Java generics is not quite the same as template types in C++; Java generics actually use the same class definition but add implicit casting (generated by the compiler) and add additional type-checking. However, the different instantiations actually make use of the same exact type (this is known as erasure), where the parameterized types are replaced with Object. You can read more about this at the link.
Since noone has mentioned it yet, there is a very comprehensive guide/FAQ/tutorial on generics which can be found on Angelika Langer's site.