开发者

Cast element in Java For Each statement

开发者 https://www.devze.com 2022-12-23 06:32 出处:网络
Is it possible (or even advisable) to cast the element retrieved from a for each statement in the statement itself? I do know that each element in list will be of type <SubType>.

Is it possible (or even advisable) to cast the element retrieved from a for each statement in the statement itself? I do know that each element in list will be of type <SubType>.

I.E.:

List<BaseType&g开发者_JAVA百科t; list = DAO.getList();  
for(<SubType> element : list){ 
    // Cannot convert from element type <BaseType> to <SubType>
    ...
}

rather than:

List <BaseType> list = DAO.getList();
for(<BaseType> el : list){
    <SubType> element = (<SubType>)el;
    ...
}


Do you really know that each entry is going to be a subtype ? The DAO simply has to fulfill the List<BaseType> contract, and if you're assuming a subclass, then I think something is wrong somewhere. I'd perhaps concentrate more on getting the interface to the DAO correct, and have it contractually return what you want.


For all the reasons stated by others, you shouldn't do this. However, if you cannot change the interface, the following is possible:

for (BaseType element : list) {
    SubType subType = (SubType)element;
    ...
}

As far as I know, this is the only way to do this and remain truly type safe - i.e. not rely on type erasure to catch any problems, which it will not necessarily do until much later.

I realize this is not EXACTLY what you were looking for, but it does handle the casting.


It is in fact possible to combine the cast with the for loop, like so:

List<BaseType> list = DAO.getList();  
for (SubType subType : ((List<SubType>) list)){ 
    ...
}

Or you can use this slightly-cleaner pattern:

List<SubType> list = (List<SubType>) DAO.getList();  
for (SubType subType : list){ 
    ...
}

You will get an unchecked cast warning from the Java compiler, unless you suppress it. The effect of the first form will be effectively identical to casting each element within the loop. The second form will also enforce that new additions to the list must conform to SubType.

Note that this will NOT work with arrays, since arrays have distinct runtime types. In other words, BaseType[] is not castable to SubType[]. You can use the Arrays API to work around this, like so:

BaseType[] array = DAO.getArray();
for (SubType subType : Arrays.<SubType>asList(array)) {
    ...
}


Possible, yes! but god forbid, Why? My early attempts in my career did that and I have learnt. Programming to interfaces always has an advantage. I always get questions from junior developers about handling cases where only subtypes have the methods/functionality required.

Say Animal class with Dog subtype having method bark(). They want bark() functionality. The actual challenge is that they want a behaviour of animal communication not bark() but animal speak(). So a new Cat sub class would not require meow(). What about this then:- My dog's form a pack, but cats don't. The answer pack() behaviour is not owned by a single dog. Pack is a different aspect, pass a pack to all objects and ask the objects to join the pack. (Visitor pattern/Adapter pattern). My Wolf class can use the same behaviour.

Am I rigid about this, no if it is only 1 off instance I am fine. If the answer is I am not sure, then you better play safe by working at interface contracts.


If you are not partial to Google collections, you can wrap the list with transform method. In your case it will be very efficient and totally compliant. I would put it as a wrapper method though as Brian has suggested.

public List< SubType > fromDao ( )
{
    // Put a comment for maintainer

    // Lists from DAO always contain SubTypes
    return
        Lists.transform(
            DAO.getList( ),
            new Function< BaseType, SubType >( )
            {
                public SubType apply ( final BaseType from )
                {
                    return (SybType) from;
                }
            };
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号