Understand Java generics and Unlimited variable length arguments. Both these facilities are used in the Android AsyncTask class.
satya - Monday, July 26, 2010 4:54:15 PM
How to instantiate
ArrayList<String> als = new ArrayList<String>
List<String> ls = new ArrayList<String>
ls = als; //right
als = ls; //wrong
satya - Monday, July 26, 2010 4:55:00 PM
following inequality holds
List<String> != List<Object>
satya - Monday, July 26, 2010 4:57:15 PM
Example of a generic method
void printCollection(Collection<?> c)
{
for (Object e : c)
{
System.out.println(e);
}
}
satya - Monday, July 26, 2010 5:01:45 PM
What is "?": an unknown type
What is "?": an unknown type
satya - Monday, July 26, 2010 5:02:18 PM
Extendign unknown types for generic methods
public void drawAll(List<? extends Shape> shapes) { ... }
satya - Monday, July 26, 2010 5:07:29 PM
A true generic method
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o); // correct
}}
satya - Monday, July 26, 2010 9:29:36 PM
java generics inheritance
java generics inheritance
satya - Monday, July 26, 2010 10:07:57 PM
there is only one instance of a generic type class
This means a static variable must be mentioned based on the raw type. for example
SomeGenericType.Constant //good
and not
SomeGenericType<T>.Constant //error
satya - Monday, July 26, 2010 10:11:14 PM
Really good source on generics
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
satya - Monday, July 26, 2010 10:15:20 PM
Hence it is wrong to have a static variable with a generic type
public class MyGenericClass<T>
{
static T somevariable; //wrong
static String variable2; //ok
...
}
satya - Monday, July 26, 2010 10:22:04 PM
Quoting Angelica Langer from above
If, for instance, you have a non-generic legacy method that takes a List as an argument, you can pass a parameterized type such as List
satya - Tuesday, July 27, 2010 12:19:32 PM
Here is a simple generics class
public class GenericPair<X,Y> {
public X varX;
public Y varY;
public GenericPair(X inVarX, Y inVarY)
{
varX = inVarX;
varY = inVarY;
}
public X getFirst()
{
return varX;
}
public Y getSecond()
{
return varY;
}
}
satya - Tuesday, July 27, 2010 12:20:58 PM
Then I can use it this way
public void testGenerics()
{
GenericPair<String, Integer> myPair =
new GenericPair<String, Integer>("satya",55);
Log.d(tag, myPair.getFirst());
this.mReportTo.reportBack(tag, myPair.getFirst());
Log.d(tag, myPair.getSecond().toString());
this.mReportTo.reportBack(tag, myPair.getSecond().toString());
}
satya - Tuesday, July 27, 2010 12:28:07 PM
You can derive (in this case ungenercise)
public class DerivedPair
extends GenericPair<String, Integer>
{
DerivedPair(String a, Integer i)
{
super(a,i);
}
}
satya - Tuesday, July 27, 2010 12:29:42 PM
Then you can rewrite the code as follows
public void testDerivedGenerics()
{
DerivedPair myPair =
new DerivedPair("satya",55);
Log.d(tag, myPair.getFirst());
this.mReportTo.reportBack(tag, myPair.getFirst());
Log.d(tag, myPair.getSecond().toString());
this.mReportTo.reportBack(tag, myPair.getSecond().toString());
}
satya - Tuesday, July 27, 2010 12:44:40 PM
Here is how to use variable number of arguments
public void testParams(String s1, String... strings)
{
this.mReportTo.reportBack(tag, "Parent:" + s1);
for(String s : strings)
{
this.mReportTo.reportBack(tag, "Child:" + s);
}
}
When there are variable number of arguments, that argument needs to be the last or the only argument to the function. The argument then is passed to the function as an array that is indexable.
satya - Tuesday, July 27, 2010 12:45:47 PM
Given that function I can use
testParams("Parent", "Child1");
// or
testParams("Parent", "Child1", "Child2");
//or
testParams("Parent", "Child1", "Child2", "Child3");
satya - Thursday, November 04, 2010 3:54:37 PM
The meaning of ? mark
void printCollection(Collection<Object> c)
{
for (Object e : c)
{
System.out.println(e);
}
}
void printCollection(Collection<?> c)
{
for (Object e : c)
{
System.out.println(e);
}
}
The first one will be useless as you cannot pass a collection of strings. you can only strictly pass a collection of objects.
From a generic "confusion" the second one says let me pass a collection of any type of object.
satya - Friday, November 05, 2010 9:19:06 AM
By extension...
By extension
void draw(Collection<Shape> shapes)
{
}
will not be of much value. Because I could not pass a Collection
However the same meaning can be implied by the following
So in short
is equivalent to
void draw(Collection<? extends Shape> shapes)
{
}
Collection<?>
Colelction<? extends Object)
satya - Friday, November 05, 2010 10:01:41 AM
Types go away at run time
SomeClass<String> gcString;
SomeClass<int> gcInt;
At run time both gcString and gcInt will point to the same type of class. So it doesn't make sense to type cast generic class variables at run time like this
SomeClass<String> gcString1 = (SomeClass<String>)gcString
satya - Friday, November 05, 2010 11:18:40 AM
Can I manipulate objects of the generic types
public class GenericPair<X,Y>
{
public X varX;
public Y varY;
public GenericPair(X inVarX, Y inVarY)
{
varX = inVarX;
varY = inVarY;
//Let's do something with varX of type X
//Lets look for a valid function on a string object
String s="";
s.concat("ddd");
//See if such a method is allowed
varX.concat("ddd"); //Compile error
}
public X getFirst()
{
return varX;
}
public Y getSecond()
{
return varY;
}
}
satya - Friday, November 05, 2010 2:04:17 PM
Consider this class
public class MyBase
{
public String s = "";
}
class MyDerived1 extends MyBase{}
class MyDerived2 extends MyBase{}
satya - Friday, November 05, 2010 2:05:30 PM
Then you can do
public class GenericStringBasedPair<X extends MyBase, Y extends MyBase>
{
public X varX;
public Y varY;
public GenericStringBasedPair(X inVarX, Y inVarY)
{
varX = inVarX;
varY = inVarY;
varX.s.concat("abc");
varY.s.concat("xyz");
}
public X getFirst()
{
return varX;
}
public Y getSecond()
{
return varY;
}
}
satya - Friday, November 05, 2010 2:20:54 PM
The super key word
What does the following mean
void somemethod(SomeType<T super String> st)
This method will take any "SomeType" whose generic type is not a derived class of "String" but a String itsels or its base class.
satya - Friday, November 05, 2010 4:34:19 PM
Summarized predicates of java generices
Functions and classes generally take fixed types as input and return fixed types.
Java generics extend this idea where functions and classes can be written they are "applicable" to more than one type, and the type is explicitly codified in the source code for documentation and compile time checking.
When the type is not explicitly stated in a generic type there are only a few things you can do with that typed object other than basic operations and the methods available on the base object class
One can give hints to the compiler that a generic type can be a sub type or a super type so that operations on those types can be allowed
A generic type instantiated or realized with two distinct parameterized types whether those types are extended from each other or otherwise are not related. So a collection of circles is not the same as a collection of shapes even though a circle is a shape.
Funtions or classes that take generic types as arguments could consider compile hints through wild cards
The available wild cards are: ?, ? extends someBaseclass, ? super someDerivedClass
There is only one instance of the generic class
The static variables in a generic class is referred with out the generic type argument
It is wrong to ask the instance type of a generic class object at run time
Both classes and functions can be genericized
satya - Friday, November 05, 2010 4:37:46 PM
netmite ArrayAdapter source code
netmite ArrayAdapter source code
satya - Friday, November 05, 2010 4:39:24 PM
Study this class how a parameterized class is developed
satya - 8/3/2018, 9:04:43 AM
You cannot override when raw types are the same
//You cannot override when raw types are the same
public class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }
}
satya - 8/3/2018, 10:54:15 AM
? is called a wild card
? is called a wild card
satya - 8/3/2018, 10:54:58 AM
A bounded wild card
//This is called a bounded wild card
<? extends SomeBaseClass>
satya - 8/3/2018, 11:07:54 AM
Consider this: adds are prevented at compile time on generic collection classes
/*
* Test the state change methods on collections
*/
void addAllSimples(List<? extends Simple> simpleDerivedList)
{
Simple s = new Simple();
Derived d = new Derived();
Object so = s;
//Following fails: compile error
//simpleDerivedList.add(s);
//simpleDerivedList.add(so);
//So all adds are prevented
}
satya - 8/3/2018, 11:09:42 AM
Here is a similar example from Bracha
public void addRectangle(List<? extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
satya - 8/3/2018, 11:13:42 AM
Why? you ask
Bounded wild cards allow you to pass a list of any type as long as it extends the base class
So it can be a list of shapes
it can be a list of triangles
it can be a list of rectangles
It makes perfect sense to read the shapes as they are all shapes
But adding a basic shape to a list of rectangles will be wrong and violates the contract that all are rectangles.
Similarly adding a triangle to a list of rectangles is clearly wrong.
So as you service many types of lists, you cannot be sure what list it is.
Even adding an object is caught at compile time.
satya - 8/3/2018, 11:21:33 AM
Generic method signature
<T> void addAllSimplesFixed(
List<T> genericizedList, List<T> fromList)
{}
satya - 8/3/2018, 11:21:53 AM
Wrong signature
void <T> addAllSimplesFixed(
List<T> genericizedList, List<T> fromList)
{}
satya - 8/3/2018, 11:36:19 AM
Reconsidered
<T> void addAllSimplesFixed(List<T> toList, T object)
{
//You cannot do this because you don't know what type the list is
//Simple s = new Simple();
//Derived d = new Derived();
//Object so = s;
//genericizedList.add(s);
toList.add(object);
}
satya - 8/3/2018, 11:37:45 AM
See this code now
private void test9()
{
//See c.addAllSimples() mehod to see what it does
GenericMethodTestClass1 c = new GenericMethodTestClass1();
c.addAllSimplesWrong(new ArrayList<Simple>());
Simple s = new Simple();
Derived d = new Derived();
GenericPair<Integer,Integer> intPair = new GenericPair<>(1,2);
List<Simple> simples = new ArrayList<>();
c.addAllSimplesFixed(simples, s);
c.addAllSimplesFixed(simples, d);
//Compiler error
//Method type is inferred
//c.addAllSimplesFixed(simples, intPair);
List<Derived> deriveds = new ArrayList<>();
//fails
//c.addAllSimplesFixed(deriveds, s);
c.addAllSimplesFixed(deriveds, d);
System.out.println("Test9:" + simples);
}
satya - 8/3/2018, 11:38:54 AM
Type inference: (Bracha)
Notice that we don?t have to pass an actual type argument to a generic method. The compiler infers the type argument for us, based on the types of the actual arguments. It will generally infer the most specific type argument that will make the call type-correct.
satya - 8/3/2018, 11:43:53 AM
So, Reads can be accommodated with wild cards. We need generic typed methods to allow adds.
So, Reads can be accommodated with wild cards. We need generic typed methods to allow adds.
satya - 8/3/2018, 2:08:42 PM
Short summary
//functions that take specific objects
//These functions serve only ONE type of client
f1(String...)
f1(List<Object> ...)
//functions that work for multiple inputs
//These serve number of typed clients
//But they can't add
f1(List<?>...)
f1(List<? extends baseclass ....)
//(generic) functions with types specified
//allows adds
<T> f1(List<T>....)
satya - 8/3/2018, 2:31:56 PM
Rawtypes
//For the following
List<String>
//List is a rawtype
satya - 8/3/2018, 2:34:33 PM
Raw types and generic types
//consider
void m1(List stringList){}
//you can call it with
List<String> stringList = new ArrayList<>();
m1(stringList)
satya - 8/3/2018, 2:36:25 PM
List of anything
//Exactly a list of objects
List<Object>
//List of any set of objects
//List of strings, List of fruits
List<?>
List
//So
List (kind of) == List<?>
satya - 8/3/2018, 2:42:45 PM
Following equivalence is valid
List <String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
satya - 8/3/2018, 2:44:43 PM
Casts and instanceof
//Start with a plain collection
Collection cs = new ArrayList<String>();
// illegal
if (cs instanceof Collection<String>) { ...}
//Unchecked warning
Collection<String> cstr = (Collection<String>) cs;
satya - 8/3/2018, 5:15:16 PM
Using class literals
Collection<EmpInfo> emps =
sqlUtility.select(EmpInfo.class, ?select * from emps?);
...
public static <T> Collection<T> select(Class<T>c, String sqlStatement) {
Collection<T> result = new ArrayList<T>();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
T item = c.newInstance();
/* use reflection and set all of item?s fields from sql results */
result.add(item);
}
return result;
}
satya - 8/3/2018, 5:15:46 PM
Class literal
//Example of a class literal
Class<T> c;
satya - 8/3/2018, 5:17:13 PM
Bounded wild cards
Those that look like <? extends Baseclass>
Bounded wildcards were useful when reading from a data structure.
satya - 8/3/2018, 5:24:43 PM
These are all method signatures. Each is telling the compiler something about the contract
function(<Object>)
function(<? extends String)
function(<T>)
function(<? extends T)
function(<? super T)
satya - 8/3/2018, 5:26:59 PM
Bounds
//Following sets a lower bound
//Don't send me any classes below String
//Anything derived from String is fine
function(<? extends String>)
//This sets an upper bound
//Only send me classes that are parents of SpecialString
//all the way to Object
function(<? super SpecialString>)
satya - 8/3/2018, 5:33:39 PM
On Upper bounds
I am guaranteed everything passed to me are my parents.
Because I am the grandest, I can behave like any of my parents in the hierarchy
So if I have a list of my parents, irrespective of their type, I can be added to that list.
So this is the opposite of "read" (in the lower bound case)
I can also add any of my derived classes to the parent lists as well.
satya - 8/3/2018, 5:38:09 PM
I got my lower and upper bounds crossed!
Read them reverse, just the names, the rest works.
satya - 8/3/2018, 5:42:05 PM
Consider this
Sink<Object> s;
Collection<String> cs;
//signature of a function
public static <T>
T writeAll(Collection<T> coll, Sink<? super T> snk){...}
//Call...
String str = writeAll(cs, s); // Yes!
//T gets resolved to "String"
//Type inference of generic methods
//How to read:
1. Take a string collection
2. Take a sink that can absorb Strings
3. Sink of Objects can absorb Strings
satya - 8/3/2018, 5:47:38 PM
More on bounds
In general, if you have an API that only uses a type parameter T as an argument, its uses should take advantage of lower bounded wildcards (? super T). Conversely, if the API only returns T, you?ll give your clients more flexibility by using upper bounded wildcards (? extends T)
satya - 8/3/2018, 6:04:52 PM
What are covariant returns?
What are covariant returns?
satya - 8/5/2018, 8:34:25 AM
How to get once head around the weeds of generics?
Ignore generics for the moment
You are writing a function
this is a function that is reusable
this is a function that works for any type
this is a function that works for any super type of this type
this is a function that works for any sub type of this type
The rest is unnecessary detail!