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 / April 2007

Tip: Looking for answers? Try searching our database.

forEach and Casting

Thread view: 
Jason Cavett - 22 Apr 2007 18:32 GMT
I have a question about the use of the foreach statement in Java 1.5.

Currently, the collection I'm using an Iterator over contains objects
of a Generic type (an abstract class).  When I get the object from the
collection, I must cast it to the more specific type so I can use the
various methods.  There is no way to change this.

Is there any way, using the foreach statement in place of using an
Iterator, to cast to the right type?  I'm thinking something like
this...

Collection<Generic> genericCollection = new ArrayList<Generic>();
genericColelction = doSomeStuffToGetGenericCollection();

// this is the part I'm not sure about - can I even do something like
this?
for(Specific o : (Specific) genericCollection) {
 // do stuff
}

Thanks
Tim Hemig - 22 Apr 2007 18:46 GMT
> I have a question about the use of the foreach statement in Java 1.5.
>
[quoted text clipped - 15 lines]
>   // do stuff
> }

Seems, that you have only instances of the Specific class in your
Collection, if you know, that every one can be cast to it. therfore I would
use a Collection of your Specific type. As lang as you do not cast (after
test with instanceof) you cannot use the specific /new/ methods.

Another thing:
Everything, that gets overloaded is useable, because the abstract class
provides the need to implement it. Because you cannot make instances of an
akstract class, in your collection are only non abstract classes with the
abstract as superclass. So you have valid objects, with an implementation
of your method. so there should be no need to cast - but I did not test
that case.

Greetings,
  Tim
Jason Cavett - 22 Apr 2007 19:02 GMT
> > I have a question about the use of the foreach statement in Java 1.5.
>
[quoted text clipped - 33 lines]
>
> - Show quoted text -

I will only have A specific class in the Collection.  The problem is,
the method that returns the specific class decides which specific
class to return depending on the setup of certain components of the
system (so it can decide at runtime).

The method "doSomeStuffToGetGenericCollection();" is actually
something like this...

public ArrayList<Generic> getDirectDescendentsOfType(Class classType)

I use it with a tree structure so I can get specific children of type
classType.  So, unfortunately, I'm always going to get back the
superclass Generic.  Each version of the Specific classes implements
Generic, but they also have additional methods depending on the
Specific class, so I need the cast to the specific class.

Anyway, I hope that all made sense.  Any additional suggestions?  Is
it possible to cast the entire Collection to a type all in one shot?
Should I just cast each individual item as it's used in the foreach
loop?
Piotr Kobzda - 22 Apr 2007 20:02 GMT
> The method "doSomeStuffToGetGenericCollection();" is actually
> something like this...
>
> public ArrayList<Generic> getDirectDescendentsOfType(Class classType)

What about declaring it as:

    public <E extends Generic> List<E>
getDirectDescendentsOfType(Class<? extends E> classType)

?

> Is
> it possible to cast the entire Collection to a type all in one shot?

Yes.  But you shouldn't do that, it violates a type safety:

    for(Specific o : (List<Specific>)(List<?>)genericCollection) { ...

> Should I just cast each individual item as it's used in the foreach
> loop?

Using as above declared generic method, you won't need to do that.
The following should work:

    for(Specific o : getDirectDescendentsOfType(Specific.class)) { ...

piotr
Jason Cavett - 22 Apr 2007 21:04 GMT
> > The method "doSomeStuffToGetGenericCollection();" is actually
> > something like this...
[quoted text clipped - 24 lines]
>
> piotr

Wow...excellent.  That works.

Now, unfortunately, despite some of the reading I've done, I don't
fully understand the notation.  Would you mind explaining it as I
don't like to use a tool I don't understand for fear of misuse.

Thanks a lot, though.  It's appreciated.
Piotr Kobzda - 22 Apr 2007 21:36 GMT
> Now, unfortunately, despite some of the reading I've done, I don't
> fully understand the notation.  Would you mind explaining it as I
> don't like to use a tool I don't understand for fear of misuse.

Well, that's not very hard to understand.  There is a single type
parameter (declared with type variable E) which serves two roles, 1)
constraints returned list elements type to any valid subclass of your
base class, and 2) declares a type (using wildcard to allow subclasses)
of Class objects being accepted by the method.

Whatever the actual type parameters are, they must match must that
declaration, that's all.

HTH,
piotr
Patricia Shanahan - 22 Apr 2007 19:23 GMT
> I have a question about the use of the foreach statement in Java 1.5.
>
[quoted text clipped - 15 lines]
>   // do stuff
> }

How about this?

for(Generic oGeneric : genericCollection) {
  Specific o = (Specific)oGeneric;
  // do stuff using o
}

Patricia
Jason Cavett - 22 Apr 2007 19:45 GMT
> > I have a question about the use of the foreach statement in Java 1.5.
>
[quoted text clipped - 27 lines]
>
> - Show quoted text -

Yeah, I thought about that, but it (somewhat) defeated the purpose for
me to move to the new foreach loops, anyway.

I decided to go with something like this:

ArrayList<Specific> var = (ArrayList<Specific>)
getDirectDescendentsOfType(Class classType)

And my getDirectDescendentsOfType is defined as...

public ArrayList<? extends Generic> getDirectDescendentsOfType(Class
classType) {
 // stuff
}

It works well.  The only downside is I get a warning every time I
perform the cast above.  So, I have to add @SuppressWarnings statement
to methods that have this within them.  Not a major thing, just
somewhat of a pain.

(I'm going to stick with this method unless anybody has any other
suggestions.)

Thanks again.
Piotr Kobzda - 22 Apr 2007 20:16 GMT
> I decided to go with something like this:
>
[quoted text clipped - 15 lines]
> (I'm going to stick with this method unless anybody has any other
> suggestions.)

See my previous post in this thread.  Generic method declared as there
will prevent you from suppressing this warning.

It also allows for a type-safe implementation of that method itself:

    List<E> list = new ArrayList<E>();
    // traverse tree descendants, and for each do that...
    if (type.isInstance(element)) {
        list.add(type.cast(entry));
    }
    ...
    return list;

piotr
Tom Hawtin - 22 Apr 2007 20:54 GMT
> Currently, the collection I'm using an Iterator over contains objects
> of a Generic type (an abstract class).  When I get the object from the
> collection, I must cast it to the more specific type so I can use the
> various methods.  There is no way to change this.

I suggest you really make sure whether you can change it or not. If you
are using generics, casts often mean design issues.

> // this is the part I'm not sure about - can I even do something like
> this?
> for(Specific o : (Specific) genericCollection) {

You can quite easily make a "safe" casting iterator.

    /**
      * <strong>{see Iterator#next}
      *    will throw ClassCastException...</strong>
      */
    public static <T> Iterable<T> castIterable(
        final Class<T> clazz, final Iterable<? super T> iterable
    ) {
        return new Iterable<T>() {
            public java.util.Iterator<T> iterator() {
                return new java.util.Iterator<T>() {
                    private final java.util.Iterator<? super T> target =
                        iterable.iterator();
                    public boolean hasNext() {
                        return target.hasNext();
                    }
                    public T next() {
                        return clazz.cast(target.next());
                    }
                    public void remove() {
                        target.remove();
                    }
                };
            }
        };
    }

...
        for (Specific thing : castIterable(Specific.class, generals)) {

(Disclaimer: Not tested.)

Tom Hawtin
Jason Cavett - 22 Apr 2007 21:20 GMT
> > Currently, the collection I'm using an Iterator over contains objects
> > of a Generic type (an abstract class).  When I get the object from the
[quoted text clipped - 42 lines]
>
> Tom Hawtin

Well, the reason it can't easily be changed is because I don't know
what class I'm going to want until runtime.  It depends on where the
user is at in the tree structure since each component in the tree is
different (even though they all have the same superclass).

As such, I need a class that can return the class type I want.
Lew - 22 Apr 2007 23:38 GMT
> Well, the reason it can't easily be changed is because I don't know
> what class I'm going to want until runtime.  It depends on where the
> user is at in the tree structure since each component in the tree is
> different (even though they all have the same superclass).
>
> As such, I need a class that can return the class type I want.

If you define the type polymorphically you do away with casting and
complicated generics both.

For example, suppose you had an interface Collectible representing the
supertype for the objects you want to store in a Collection.

public interface Collectible
{
    public void doSomethingAppropriate();
}

Now if you have a Collection<Collectible> you simply

 Collection<Collectible> stuff = buildCollection();
 for( Collectible coll : stuff )
 {
    coll.doSomethingAppropriate();
 }

Notice that there is /no/ specific run-time type knowledge needed in the
client class.

Let the object itself know what to do in doSomethingAppropriate() instead of
demanding that the client class have that inner knowledge.  It's called
"encapsulation" combined with "polymorphism" and it's a core O-O programming
trick.

Signature

Lew

Jason Cavett - 23 Apr 2007 14:01 GMT
> > Well, the reason it can't easily be changed is because I don't know
> > what class I'm going to want until runtime.  It depends on where the
[quoted text clipped - 33 lines]
> --
> Lew

I know what encapsulation and polymorphism is.  The problem is, I
can't use it in this situation.  My tree (in this case) is made up of
very different types of objects.  The only reason they have a similar
superclass is because I needed a common class to use with the tree.
However, the underlying information in each subclass is very different
depending on the subclass.  The only similariy between all the
subclasses is that they all have a name property and a certain
status.  Other than that, all other data is different.
Lew - 23 Apr 2007 14:15 GMT
> I know what encapsulation and polymorphism is.  The problem is, I
> can't use it in this situation.  My tree (in this case) is made up of
[quoted text clipped - 4 lines]
> subclasses is that they all have a name property and a certain
> status.  Other than that, all other data is different.

Could you make a wrapper class that has a common method where each subclass
knows what to do inside doSomethingAppropriate() with the object it wraps?

Signature

Lew

Jason Cavett - 23 Apr 2007 15:53 GMT
> > I know what encapsulation and polymorphism is.  The problem is, I
> > can't use it in this situation.  My tree (in this case) is made up of
[quoted text clipped - 10 lines]
> --
> Lew

Unfortunately, it's not that simple (and I wish it was.  For example,
each data object has different information that I need access to.  So,
I'm not just telling the data to do something that I don't need to
worry about, I actually have to get information back and that info is
different depending on the class in question.
Tom Hawtin - 23 Apr 2007 00:27 GMT
> Well, the reason it can't easily be changed is because I don't know
> what class I'm going to want until runtime.  It depends on where the
> user is at in the tree structure since each component in the tree is
> different (even though they all have the same superclass).

Have you considered a visitor (might be overblown for your situation).

Tom Hawtin
Jason Cavett - 23 Apr 2007 14:12 GMT
> > Well, the reason it can't easily be changed is because I don't know
> > what class I'm going to want until runtime.  It depends on where the
[quoted text clipped - 4 lines]
>
> Tom Hawtin

It may be a little overblown for my situation.  I'd have to look into
it a little more.  Unfortunately, my current timeline doesn't give me
the luxery of going back and refactoring a large part of code at the
moment.  But, I'll make sure to go back and look into it later.

Thanks for the suggestion.


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.