why java lets you cast into collection?
Clash Royale CLAN TAG#URR8PPP
up vote
6
down vote
favorite
I have a simple foo class and I am casting to Collection
(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 java compiler does not return incompatible types error when I try to cast the Foo
class into a collection?
Foo
class does not implement Collection
.
I would expect incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
add a comment |Â
up vote
6
down vote
favorite
I have a simple foo class and I am casting to Collection
(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 java compiler does not return incompatible types error when I try to cast the Foo
class into a collection?
Foo
class does not implement Collection
.
I would expect incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
4
You could write a subclass ofFoo
that implementsList
orMap
.
– khelwood
42 mins 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
41 mins ago
1
@istovatis becauseOther
is a class, and a subclass ofFoo
cannot also extendOther
.
– Andy Turner
40 mins ago
add a comment |Â
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I have a simple foo class and I am casting to Collection
(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 java compiler does not return incompatible types error when I try to cast the Foo
class into a collection?
Foo
class does not implement Collection
.
I would expect 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 Collection
(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 java compiler does not return incompatible types error when I try to cast the Foo
class into a collection?
Foo
class does not implement Collection
.
I would expect incompatible types error, because given the current Foo
class signature, this cannot be a Collection
.
java collections casting
java collections casting
edited 42 mins ago


Federico klez Culloca
14.7k124274
14.7k124274
asked 45 mins ago
istovatis
784823
784823
4
You could write a subclass ofFoo
that implementsList
orMap
.
– khelwood
42 mins 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
41 mins ago
1
@istovatis becauseOther
is a class, and a subclass ofFoo
cannot also extendOther
.
– Andy Turner
40 mins ago
add a comment |Â
4
You could write a subclass ofFoo
that implementsList
orMap
.
– khelwood
42 mins 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
41 mins ago
1
@istovatis becauseOther
is a class, and a subclass ofFoo
cannot also extendOther
.
– Andy Turner
40 mins ago
4
4
You could write a subclass of
Foo
that implements List
or Map
.– khelwood
42 mins ago
You could write a subclass of
Foo
that implements List
or Map
.– khelwood
42 mins 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
41 mins 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
41 mins ago
1
1
@istovatis because
Other
is a class, and a subclass of Foo
cannot also extend Other
.– Andy Turner
40 mins ago
@istovatis because
Other
is a class, and a subclass of Foo
cannot also extend Other
.– Andy Turner
40 mins ago
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
7
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
3
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
32 mins ago
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
7
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
7
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
7
down vote
up vote
7
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 24 mins ago
answered 40 mins ago
T.J. Crowder
658k11311591258
658k11311591258
add a comment |Â
add a comment |Â
up vote
3
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
32 mins ago
add a comment |Â
up vote
3
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
32 mins ago
add a comment |Â
up vote
3
down vote
up vote
3
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 22 mins ago
answered 35 mins ago
ernest_k
15k41430
15k41430
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
32 mins ago
add a comment |Â
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
32 mins ago
1
1
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
32 mins ago
Indeed, cast is not permitted even though for interfaces when the class is turned into final
– istovatis
32 mins 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-java-lets-you-cast-into-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
4
You could write a subclass of
Foo
that implementsList
orMap
.– khelwood
42 mins 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
41 mins ago
1
@istovatis because
Other
is a class, and a subclass ofFoo
cannot also extendOther
.– Andy Turner
40 mins ago