Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this cast in my generic method safe?

I have code in my project that looks like this:

public interface Bar<T extends Foo<?>> {
 //...
}

public class MyFoo implements Foo<String> {
    private List<Bar<Foo<String>> barFoo = ...

    public <U extends Foo<String>> boolean addBar(Bar<? extends U> b) {
        barFoo.add((Bar<Foo<String>>) b); //safe cast?
    }

}

Eclipse gives a warning for the cast in addBar that the cast is unsafe. However, am I correct in assuming that the cast will not throw given the restrictions that I have put on the type parameters, and therefore the cast is indeed safe?

like image 386
Dongie Agnir Avatar asked Feb 13 '13 21:02

Dongie Agnir


People also ask

Do generics prevent type cast errors?

Implementing generics into your code can greatly improve its overall quality by preventing unprecedented runtime errors involving data types and typecasting.

What is the purpose of using generics?

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.

What does it mean to use a generic mechanism in Java?

A generic interface declaration defines a set of types, one for each possible invocation of the type parameter section. All parameterized types share the same interface at runtime. A method is generic if it declares one or more type variables. These type variables are known as the formal type parameters of the method.


1 Answers

Not in general.

Suppose Bar has a method void get(T value), and there are two implementations of Foo<String>, MyFoo and YourFoo. Now suppose a caller calls addBar on a value of type Bar<MyFoo>. This works: when U = Foo<String>, we have that Bar<MyFoo> is a subtype of Bar<? extends U>. Now we cast that value to a Bar<Foo<String>>.

Now if Bar has no methods that accept T's as arguments, there's no problem. But suppose it has a method void process(T value). The implementation we called has T = MyFoo, so it only has a process(MyFoo value) method. Once we cast it to a Bar<Foo<String>>, though, we might call it with a YourFoo instead. This is illegal.

Stab in the dark, but I suspect that what you really wanted to do was declare barFoo as a List<? extends Bar<? extends Foo<String>>.

like image 198
jacobm Avatar answered Sep 23 '22 21:09

jacobm