-2

I am reading about Generics in Effective Java item 23. It is mentioned as below:

While the prospect of accidentally inserting a coin into a stamp collection may appear far-fetched, the problem is real. For example, it is easy to imagine someone putting a java.util.Date instance into a collection that is supposed to contain only java.sql.Date instances.

I am not able to understand what does author mean by "it is easy to imagine someone putting a java.util.Date instance into a collection that is supposed to contain only java.sql.Date instances"?

Collection<java.util.Date> dateColl = new ArrayList();
String strDate = "2011-12-31 00:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
java.util.Date date = sdf.parse(strDate);
java.sql.Date sqlDate = new Date(date.getTime());

dateColl.add(sqlDate);

Why above code is not throwing compilation error?

venkysmarty
  • 11,099
  • 25
  • 101
  • 184

3 Answers3

2

I am not able to understand what does author mean by "it is easy to imagine someone putting a java.util.Date instance into a collection that is supposed to contain only java.sql.Date instances"?

In your example :

Collection<java.util.Date> dateColl = new ArrayList();
java.util.Date date = sdf.parse(strDate);
...
dateColl.add(date);

you do the reverse. You declare a Collection of java.util.Date. And besides you have added a java.util.Date instance in the collection of java.util.Date instance. You never use the java.sql.Date instance you declare and of course adding a java.util.Date instance in a collection of java.util.Date doesn't require any cast and doesn't question about type compatibility.

In a OOP point of view : a java.sql.Date IS a java.util.Date type. So, it is legal :

Collection<java.util.Date> dateColl = new ArrayList();
dateColl.add(new java.sql.Date(...));

To understand the problem, you should declare :

Collection<java.sql.Date> dateColl = new ArrayList();

and then try to add a java.util.Date instance. There, you will have a compilation problem since "you are putting a java.util.Date instance into a collection that is supposed to contain only java.sql.Date instances".

Without using generics in Collection classes, the compilation will not fail and therefore at the runtime, you may have ClassCastException if you expect to have a collection which contains only java.sql.Date instances :

Here, you will have a ClassCastException in the loop since you could not cast the java.util.Date instance to a java.sql.Date instance :

Collection mySqlDates = new ArrayList();
mySqlDates.add(new java.sql.Date(...));
mySqlDates.add(new java.util.Date(...));

for (Object object : mySqlDates) {
    java.sql.Date sqlDate = (java.sql.Date) object; 
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
0

date is of type java.util.Date, which is the same type you declared your Collection for, so no error. However, java.sql.Date does extend java.util.Date so you should be able to store both versions in your Collection without issue.

theKunz
  • 444
  • 4
  • 12
-1

Why above code is not throwing compilation error?

Your collection dateColl is of type java.util.Date so you can add any object which is of either java.util.Date or of it's subtypes as shown below:

Collection<java.util.Date> dateColl = new ArrayList();
String strDate = "2011-12-31 00:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
java.util.Date date = sdf.parse(strDate);
java.sql.Date sqlDate = new Date(date.getTime());
dateColl.add(date); //VALID
dateColl.add(sqlDate);//VALID

Infact you can add java.sql.Date object as well as shown above (because java.sql.Date extends (IS-A) java.util.Date)

Vasu
  • 21,832
  • 11
  • 51
  • 67
  • The OP is adding `date` to the collection, which is a `Date` object. It's not that you're wrong, you're misreading the situation. – Makoto Nov 25 '16 at 07:00