Understand Java generics and Unlimited variable length arguments. Both these facilities are used in the Android AsyncTask class.

satya - Monday, July 26, 2010 3:20:05 PM

Java generics

Java generics

Search for: Java generics

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 4:57:56 PM

Above snippets borrowed from

A 2004 PDF by Gilad Bracha

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

Search for: 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 to that method. Conversely, if you have a method that returns a List , you can assign the result to a reference variable of type List , provided you know for some reason that the returned list really is a list of strings.

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 to the draw function. By very definition the type Collection is not the same as Collection. In most cases a signature like this is in most likely not what you want.

However the same meaning can be implied by the following


void draw(Collection<? extends Shape> shapes) 
{
}

So in short


Collection<?>

is equivalent to


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

Search for: netmite ArrayAdapter source code

satya - Friday, November 05, 2010 4:39:24 PM

Study this class how a parameterized class is developed

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?

Search for: What are covariant returns?

satya - 8/3/2018, 6:12:31 PM

Behavior of arrays

Behavior of arrays

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!