why does Java let you cast to a collection?
Clash Royale CLAN TAG#URR8PPP
up vote
10
down vote
favorite
I have a simple foo
class and I am casting to a collection interface (either Map
or List
). No compiler error.
public class Foo
public List<String> getCollectionCast()
return (List<String>) this; //no compiler error
public Map<String, String> getCollection2Cast()
return (Map<String, String>) this; //no compiler error
public Other getCast()
return (Other)this; //incompatible types, Cannot cast Foo to Other
public static class Other
// Just for casting demo
My question is: Why does the Java compiler not return incompatible types error when I try to cast the Foo
class to a collection?
Foo
does not implement Collection
.
I would expect an incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
add a comment |Â
up vote
10
down vote
favorite
I have a simple foo
class and I am casting to a collection interface (either Map
or List
). No compiler error.
public class Foo
public List<String> getCollectionCast()
return (List<String>) this; //no compiler error
public Map<String, String> getCollection2Cast()
return (Map<String, String>) this; //no compiler error
public Other getCast()
return (Other)this; //incompatible types, Cannot cast Foo to Other
public static class Other
// Just for casting demo
My question is: Why does the Java compiler not return incompatible types error when I try to cast the Foo
class to a collection?
Foo
does not implement Collection
.
I would expect an incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
6
You could write a subclass ofFoo
that implementsList
orMap
.
– khelwood
2 hours ago
Yes I know. My question is why java compiler does not show me incompatibles types error, as it shows when I try to cast Foo to Other (as expected)
– istovatis
2 hours ago
2
@istovatis becauseOther
is a class, and a subclass ofFoo
cannot also extendOther
.
– Andy Turner
2 hours ago
Possible duplicate of Java casting in interfaces (or at least closely related)
– Hulk
40 mins ago
In the question above there are two classes that implement two interfaces. Here the foo class does not implement any interface. In addition, in the question you provided, compiler complains in an interface cast, but not complaints in the other. Hence, we have to do with two different examples
– istovatis
21 mins ago
add a comment |Â
up vote
10
down vote
favorite
up vote
10
down vote
favorite
I have a simple foo
class and I am casting to a collection interface (either Map
or List
). No compiler error.
public class Foo
public List<String> getCollectionCast()
return (List<String>) this; //no compiler error
public Map<String, String> getCollection2Cast()
return (Map<String, String>) this; //no compiler error
public Other getCast()
return (Other)this; //incompatible types, Cannot cast Foo to Other
public static class Other
// Just for casting demo
My question is: Why does the Java compiler not return incompatible types error when I try to cast the Foo
class to a collection?
Foo
does not implement Collection
.
I would expect an incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
I have a simple foo
class and I am casting to a collection interface (either Map
or List
). No compiler error.
public class Foo
public List<String> getCollectionCast()
return (List<String>) this; //no compiler error
public Map<String, String> getCollection2Cast()
return (Map<String, String>) this; //no compiler error
public Other getCast()
return (Other)this; //incompatible types, Cannot cast Foo to Other
public static class Other
// Just for casting demo
My question is: Why does the Java compiler not return incompatible types error when I try to cast the Foo
class to a collection?
Foo
does not implement Collection
.
I would expect an incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
java collections casting
edited 10 mins ago
asked 3 hours ago
istovatis
804924
804924
6
You could write a subclass ofFoo
that implementsList
orMap
.
– khelwood
2 hours ago
Yes I know. My question is why java compiler does not show me incompatibles types error, as it shows when I try to cast Foo to Other (as expected)
– istovatis
2 hours ago
2
@istovatis becauseOther
is a class, and a subclass ofFoo
cannot also extendOther
.
– Andy Turner
2 hours ago
Possible duplicate of Java casting in interfaces (or at least closely related)
– Hulk
40 mins ago
In the question above there are two classes that implement two interfaces. Here the foo class does not implement any interface. In addition, in the question you provided, compiler complains in an interface cast, but not complaints in the other. Hence, we have to do with two different examples
– istovatis
21 mins ago
add a comment |Â
6
You could write a subclass ofFoo
that implementsList
orMap
.
– khelwood
2 hours ago
Yes I know. My question is why java compiler does not show me incompatibles types error, as it shows when I try to cast Foo to Other (as expected)
– istovatis
2 hours ago
2
@istovatis becauseOther
is a class, and a subclass ofFoo
cannot also extendOther
.
– Andy Turner
2 hours ago
Possible duplicate of Java casting in interfaces (or at least closely related)
– Hulk
40 mins ago
In the question above there are two classes that implement two interfaces. Here the foo class does not implement any interface. In addition, in the question you provided, compiler complains in an interface cast, but not complaints in the other. Hence, we have to do with two different examples
– istovatis
21 mins ago
6
6
You could write a subclass of
Foo
that implements List
or Map
.– khelwood
2 hours ago
You could write a subclass of
Foo
that implements List
or Map
.– khelwood
2 hours ago
Yes I know. My question is why java compiler does not show me incompatibles types error, as it shows when I try to cast Foo to Other (as expected)
– istovatis
2 hours ago
Yes I know. My question is why java compiler does not show me incompatibles types error, as it shows when I try to cast Foo to Other (as expected)
– istovatis
2 hours ago
2
2
@istovatis because
Other
is a class, and a subclass of Foo
cannot also extend Other
.– Andy Turner
2 hours ago
@istovatis because
Other
is a class, and a subclass of Foo
cannot also extend Other
.– Andy Turner
2 hours ago
Possible duplicate of Java casting in interfaces (or at least closely related)
– Hulk
40 mins ago
Possible duplicate of Java casting in interfaces (or at least closely related)
– Hulk
40 mins ago
In the question above there are two classes that implement two interfaces. Here the foo class does not implement any interface. In addition, in the question you provided, compiler complains in an interface cast, but not complaints in the other. Hence, we have to do with two different examples
– istovatis
21 mins ago
In the question above there are two classes that implement two interfaces. Here the foo class does not implement any interface. In addition, in the question you provided, compiler complains in an interface cast, but not complaints in the other. Hence, we have to do with two different examples
– istovatis
21 mins ago
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
15
down vote
It's not because they're collection classes, it's because they're interfaces. Foo
doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this
isn't of a class that implements those interfaces, naturally it's a runtime error.
If you change List<String>
to ArrayList<String>
, you'll get a compiler-time error for that, too, since a Foo
subclass could implement List
, but can't extend ArrayList
(since Foo
doesn't). Similarly, if you make Foo
final
, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo
can't have subclasses, and doesn't implement those interfaces).
add a comment |Â
up vote
8
down vote
The compiler doesn't prevent code from casting a type to an interface, unless it can establish for sure that the relationship is impossible.
If the target type is an interface, then it makes sense because a class extending Foo
can implement Map<String, String>
. However, note that this only works as Foo
is not final
. If you declared your class with final class Foo
, that cast would not work.
If the target type is a class, then in this case it would simply fail (try (HashMap<String, String>) this
), because the compiler knows for certain that the relationship between Foo
and HashMap
is impossible.
As a reference this rules are described in JLS-5.5.1 (T = target type - Map<String, String>
, S = source type - Foo
)
If T [target type] is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
Note the bold-italic comment in the quoted text.
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
15
down vote
It's not because they're collection classes, it's because they're interfaces. Foo
doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this
isn't of a class that implements those interfaces, naturally it's a runtime error.
If you change List<String>
to ArrayList<String>
, you'll get a compiler-time error for that, too, since a Foo
subclass could implement List
, but can't extend ArrayList
(since Foo
doesn't). Similarly, if you make Foo
final
, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo
can't have subclasses, and doesn't implement those interfaces).
add a comment |Â
up vote
15
down vote
It's not because they're collection classes, it's because they're interfaces. Foo
doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this
isn't of a class that implements those interfaces, naturally it's a runtime error.
If you change List<String>
to ArrayList<String>
, you'll get a compiler-time error for that, too, since a Foo
subclass could implement List
, but can't extend ArrayList
(since Foo
doesn't). Similarly, if you make Foo
final
, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo
can't have subclasses, and doesn't implement those interfaces).
add a comment |Â
up vote
15
down vote
up vote
15
down vote
It's not because they're collection classes, it's because they're interfaces. Foo
doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this
isn't of a class that implements those interfaces, naturally it's a runtime error.
If you change List<String>
to ArrayList<String>
, you'll get a compiler-time error for that, too, since a Foo
subclass could implement List
, but can't extend ArrayList
(since Foo
doesn't). Similarly, if you make Foo
final
, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo
can't have subclasses, and doesn't implement those interfaces).
It's not because they're collection classes, it's because they're interfaces. Foo
doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this
isn't of a class that implements those interfaces, naturally it's a runtime error.
If you change List<String>
to ArrayList<String>
, you'll get a compiler-time error for that, too, since a Foo
subclass could implement List
, but can't extend ArrayList
(since Foo
doesn't). Similarly, if you make Foo
final
, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo
can't have subclasses, and doesn't implement those interfaces).
edited 2 hours ago
answered 2 hours ago
T.J. Crowder
658k11311591259
658k11311591259
add a comment |Â
add a comment |Â
up vote
8
down vote
The compiler doesn't prevent code from casting a type to an interface, unless it can establish for sure that the relationship is impossible.
If the target type is an interface, then it makes sense because a class extending Foo
can implement Map<String, String>
. However, note that this only works as Foo
is not final
. If you declared your class with final class Foo
, that cast would not work.
If the target type is a class, then in this case it would simply fail (try (HashMap<String, String>) this
), because the compiler knows for certain that the relationship between Foo
and HashMap
is impossible.
As a reference this rules are described in JLS-5.5.1 (T = target type - Map<String, String>
, S = source type - Foo
)
If T [target type] is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
Note the bold-italic comment in the quoted text.
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
add a comment |Â
up vote
8
down vote
The compiler doesn't prevent code from casting a type to an interface, unless it can establish for sure that the relationship is impossible.
If the target type is an interface, then it makes sense because a class extending Foo
can implement Map<String, String>
. However, note that this only works as Foo
is not final
. If you declared your class with final class Foo
, that cast would not work.
If the target type is a class, then in this case it would simply fail (try (HashMap<String, String>) this
), because the compiler knows for certain that the relationship between Foo
and HashMap
is impossible.
As a reference this rules are described in JLS-5.5.1 (T = target type - Map<String, String>
, S = source type - Foo
)
If T [target type] is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
Note the bold-italic comment in the quoted text.
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
add a comment |Â
up vote
8
down vote
up vote
8
down vote
The compiler doesn't prevent code from casting a type to an interface, unless it can establish for sure that the relationship is impossible.
If the target type is an interface, then it makes sense because a class extending Foo
can implement Map<String, String>
. However, note that this only works as Foo
is not final
. If you declared your class with final class Foo
, that cast would not work.
If the target type is a class, then in this case it would simply fail (try (HashMap<String, String>) this
), because the compiler knows for certain that the relationship between Foo
and HashMap
is impossible.
As a reference this rules are described in JLS-5.5.1 (T = target type - Map<String, String>
, S = source type - Foo
)
If T [target type] is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
Note the bold-italic comment in the quoted text.
The compiler doesn't prevent code from casting a type to an interface, unless it can establish for sure that the relationship is impossible.
If the target type is an interface, then it makes sense because a class extending Foo
can implement Map<String, String>
. However, note that this only works as Foo
is not final
. If you declared your class with final class Foo
, that cast would not work.
If the target type is a class, then in this case it would simply fail (try (HashMap<String, String>) this
), because the compiler knows for certain that the relationship between Foo
and HashMap
is impossible.
As a reference this rules are described in JLS-5.5.1 (T = target type - Map<String, String>
, S = source type - Foo
)
If T [target type] is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
Note the bold-italic comment in the quoted text.
edited 2 hours ago
answered 2 hours ago
ernest_k
15.1k41430
15.1k41430
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
add a comment |Â
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
1
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
2 hours ago
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52698154%2fwhy-does-java-let-you-cast-to-a-collection%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
6
You could write a subclass of
Foo
that implementsList
orMap
.– khelwood
2 hours ago
Yes I know. My question is why java compiler does not show me incompatibles types error, as it shows when I try to cast Foo to Other (as expected)
– istovatis
2 hours ago
2
@istovatis because
Other
is a class, and a subclass ofFoo
cannot also extendOther
.– Andy Turner
2 hours ago
Possible duplicate of Java casting in interfaces (or at least closely related)
– Hulk
40 mins ago
In the question above there are two classes that implement two interfaces. Here the foo class does not implement any interface. In addition, in the question you provided, compiler complains in an interface cast, but not complaints in the other. Hence, we have to do with two different examples
– istovatis
21 mins ago