Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / July 2006

Tip: Looking for answers? Try searching our database.

jdk 5 generic, why not the other way arround for (T[] e, Collection<T> c)

Thread view: 
John_Woo - 15 Jul 2006 22:46 GMT
Hi,

I'm trying to understand the generic concept. The following confused
me:

    public static void main(String arg[])
    {
        Object[] oa = new Object [10];
        Collection<Object> co = new ArrayList<Object>();

        String[] sa = new String[10];
        Collection<String> cs = new ArrayList<String>();

        method(sa, co); //1
        method(oa, co); //2

        method(oa,cs); // 3, compile error:
//<T>method(T[],java.util.Collection<T>) in Test cannot be applied to
// (java.lang.Object[],java.util.Collection<java.lang.String>)
// method(oa,cs);
    }

    static <T> void method(T[]e, Collection<T> c)
    {    //do nothing }

The #2 is obvious, but why #1 is ok and #3 is wrong?

--
Thanks
John
Toronto
Timo Stamm - 15 Jul 2006 23:05 GMT
John_Woo schrieb:
> Hi,
>
[quoted text clipped - 22 lines]
>
> The #2 is obvious, but why #1 is ok and #3 is wrong?

Imagine what would happen if this would compile, and your method did
something:

  static <T> void method(T[] e, Collection<T> c) {
    for (T t : e) {
      c.add(e);
    }
  }

  Object[] oa = new Object [10];
  Collection<String> cs = new ArrayList<String>();
  method(oa, cs);
  String s = cs.get(cs.size()-1); // obviously an error

Timo
John_Woo - 15 Jul 2006 23:45 GMT
> John_Woo schrieb:
> > Hi,
[quoted text clipped - 37 lines]
>    method(oa, cs);
>    String s = cs.get(cs.size()-1); // obviously an error

Thanks, Timo,
but how about this:

   static <T> void method(T[] e, Collection<T> c) {
     e[0] = ((ArrayList)c).get(0);
    }

isn't that make the other way around?
Timo Stamm - 16 Jul 2006 00:55 GMT
John_Woo schrieb:
>> Imagine what would happen if this would compile, and your method did
>> something:
[quoted text clipped - 18 lines]
>
> isn't that make the other way around?

The point of Generics is to eliminate those casts. You should never use
casts in parameterized code.

So you want to add a String to an Object-container. That's not a problem:

  Object[] oa = new Object [10];
  Collection<String> cs = new ArrayList<String>();
  oa[0] = cs.iterator().next();

If you want to move the action into a seperate method, you have to
express the type boundaries properly:

  static <E, C extends E> void method(E[] e, Collection<C> c) {
    e[0] = c.iterator().next();
  }

This method will add the first element of the Collection c to the array
e, but the element type of c must be a sub class (or the same) of the
element type of e.

If this confuses you, don't be frustrated. Generic types alone are more
complicated than the whole type system of java 1.4.

Timo
John_Woo - 16 Jul 2006 12:49 GMT
> John_Woo schrieb:
> >> Imagine what would happen if this would compile, and your method did
[quoted text clipped - 44 lines]
>
> Timo

Thanks, Timo.

   static <T> void a(T[] e, Collection<T> c) {
         e[0] = c.iterator().next();
    }

   static <T> void b(T[] e, Collection<T> c) {
          e[0] = (T)((ArrayList)c).get(0);
   }

Can u tell, why a passed comile, but b has  unchecked or unsafe
operations ?
I meant in b, compiler should have known that all elements in array or
in collection,
are of type T.
Thomas Hawtin - 16 Jul 2006 20:38 GMT
>     static <T> void a(T[] e, Collection<T> c) {
>          e[0] = c.iterator().next();
[quoted text clipped - 9 lines]
> in collection,
> are of type T.

There are two problems with b - the two casts. Casting to ArrayList
removes the generic parameter, so is dubious. Casting T cannot be
checked at runtime, so is unsafe.

What you can write is:

    static <T> void c(T[] e, Collection<T> c) {
          e[0] = ((ArrayList<T>)c).get(0);
    }

Given a Collection<T> then if its erasure is at runtime an ArrayList it
must be an ArrayList<T>.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Ingo R. Homann - 17 Jul 2006 09:55 GMT
Hi Timo,

I think, Johns example is not so good (because his cast pointed you in a
wrong direction). I think, Johns idea is correct, that your example (the
other way round) would suffer the same problem:

Imagine what would happen if this would compile, and your method did
something:

  static <T> void method(T[] e, Collection<T> c) {
    int i=0;
    for (T t : c) {
      e[i++]=t;
    }
  }

  String[] sa = new String[10];
  Collection<Object> co = new ArrayList<Object>();
  co.add(new Long(0));
  method(sa, co);
  String s = sa[0]; // obviously an error

The point is (what Mike said): 'Arrays "know" [at runtime] what type
they should contain; generics do not.'

I think this asymmetry between Arrays and generic Collections is a great
design flaw. (Although I am aware that solving this is not easy and
suffers other problems... one main problem is that a String[] can be
assigned to an Object[]-variable: A String[] does not have all abilities
of an Object[] (for example the ability to insert a Long), so it sould
not be assignable!)

Ciao,
Ingo
Mike Schilling - 16 Jul 2006 02:19 GMT
> Hi,
>
[quoted text clipped - 22 lines]
>
> The #2 is obvious, but why #1 is ok and #3 is wrong?

Arrays "know" what type they should contain; generics do not.  Thus:

   String [] sarr = new String[12];
   Object[] oarr = sarr;

is safe, since

   oarr[0] = new Object();    // throws exception at runtime.

With generics, on the other hand:

   List<String> slist = new ArrayList<String>();
   List<Object> olist = slist; // not allowed

is not safe, since

   olist.add(new Object());    // no runtime exception

would not be prevented.
John_Woo - 16 Jul 2006 12:52 GMT
> > Hi,
> >
[quoted text clipped - 42 lines]
>
> would not be prevented.

Thanks, Mike.

So, can we make a top-level generics type for list, like

List<?> allList = new ArrayList<?>();
so it can accept of types of objects.

if possible, any example?
Thomas Hawtin - 16 Jul 2006 20:44 GMT
> List<?> allList = new ArrayList<?>();
> so it can accept of types of objects.

No, you would need:

    List<Object> allList = new ArrayList<Object>();

? stands in for a particular generic argument, so you cannot create an
object with a wildcard generic argument. (You can, however, create an
object with a generic argument that contains a wildcard, such as new
ArrayList<List<?>>().)

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Mike Schilling - 17 Jul 2006 07:50 GMT
>> List<?> allList = new ArrayList<?>();
>> so it can accept of types of objects.
[quoted text clipped - 7 lines]
> object with a generic argument that contains a wildcard, such as new
> ArrayList<List<?>>().)

There are two different idea fighting it out here.

1.  List<Object> is a list that can contain any sort of object.

2. List<?> is a reference that can refer to any list, regardless of what
sort of object that list consists of.

They are quite different things.  The fact that

   Object[]

fulfills both for arrays serves to confuse things, but

   new Object[12]

is the first idea, and

   Object[] ref = new String[12]

is the second idea.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.