views:

72

answers:

4

This code:

class RawStringIterator {
        java.util.Stack<State> stateStack = new java.util.Stack<State>();
        RawStringIterator(RawStringIterator i) {
              stateStack = (java.util.Stack<State>) i.stateStack.clone();
        }
        /* ... */
}

gives me this warning:

Type safety: Unchecked cast from Object to Stack<Utils.OperatorTree.RawStringIterator.State>

I guess I can ignore the warning here. But I wonder about how to use clone() in general? Do I always have to use a @SuppressWarnings("unchecked") every time I use clone()? Or should I always do the completely redundant extra check?

A: 

You have very little choice but to ignore it.

Whilst not directly relevant (because you're not writing a clone() method), this entry in the Java Generics FAQ makes good reading (as does the whole FAQ!)

dty
+4  A: 

If you have the choice, the best is not to implement / use clone() at all, because it is a broken API. Just implement / use a copy constructor instead.

If for some pressing reason you must use clone() but can change its implementation, consider declaring Stack<T>.clone() to return Stack<T> instead of Object - covariant return types are legal since Java5.

Update: if the Stack in question is java.util.Stack, consider its Javadoc:

A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class.

And e.g. ArrayDeque provides a copy constructor.

Péter Török
`Stack<T>` is `java.util.Stack<T>` here. So I cannot really change any declaration there.
Albert
@Albert, you may still be able to switch to a different collection though - see my update.
Péter Török
+1 for `Deque`.
Bozho
Would the downvoter care to add an explanation?
Péter Török
+2  A: 

There is no way to avoid the cast here. clone() returns Object, if it is java.util.Stack, it is not making use of co-variant return types.

If this is not java.util.Stack, then don't implement clone() - it's really hard to get it right. Make a copy-constructor instead.

Bozho
You can (and are recommended to) use covariant return types with your `clone()` - Effective Java 2nd Ed. Item 11 shows explicit examples.
Péter Török
yes, but java.util.Stack does not. That was my point. I'll clarify
Bozho
No, `java.util.Stack` does not have a copy constructor. Otherwise I would have used it.
Albert
sorry, was under a wrong impression. removed that part.
Bozho
A: 

Yes, you'll need to explicitly suppress the warnings each time you use clone().

This is one of the reasons you might prefer to use copy constructors instead of clone(), if available.

By the way in your code, when the RawStringIterator(RawStringIterator i) constructor is used, the first initialisation of stateStack is unnecessary:

class RawStringIterator {
    Stack<State> stateStack = new Stack<State>();
    RawStringIterator(RawStringIterator i) {
          stateStack = (Stack<State>) i.stateStack.clone();
    }
    /* ... */
}

You might want to remove that.

Grodriguez