Why does this use of Generics not throw a runtime or compile time exception?
Clash Royale CLAN TAG#URR8PPP
up vote
6
down vote
favorite
I've got a method in a class that has a return type specified by use of a generic.
public class SomeMain
public static void main(String args)
Foo<Integer> foo = new Foo<Integer>();
System.out.println(foo.getFoo()); // Works, prints out "Foo"
public static class Foo<E>
public E getFoo()
return (E) "Foo";
With the generic return type, I assumed the return in the above example would evaluate to:
return (Integer) "Foo"; // Inconvertible types !!!
Instead a String
is returned and printed correctly.
I get a compilation error if I change the call to be:
String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);
What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.
java generics
add a comment |Â
up vote
6
down vote
favorite
I've got a method in a class that has a return type specified by use of a generic.
public class SomeMain
public static void main(String args)
Foo<Integer> foo = new Foo<Integer>();
System.out.println(foo.getFoo()); // Works, prints out "Foo"
public static class Foo<E>
public E getFoo()
return (E) "Foo";
With the generic return type, I assumed the return in the above example would evaluate to:
return (Integer) "Foo"; // Inconvertible types !!!
Instead a String
is returned and printed correctly.
I get a compilation error if I change the call to be:
String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);
What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.
java generics
add a comment |Â
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I've got a method in a class that has a return type specified by use of a generic.
public class SomeMain
public static void main(String args)
Foo<Integer> foo = new Foo<Integer>();
System.out.println(foo.getFoo()); // Works, prints out "Foo"
public static class Foo<E>
public E getFoo()
return (E) "Foo";
With the generic return type, I assumed the return in the above example would evaluate to:
return (Integer) "Foo"; // Inconvertible types !!!
Instead a String
is returned and printed correctly.
I get a compilation error if I change the call to be:
String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);
What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.
java generics
I've got a method in a class that has a return type specified by use of a generic.
public class SomeMain
public static void main(String args)
Foo<Integer> foo = new Foo<Integer>();
System.out.println(foo.getFoo()); // Works, prints out "Foo"
public static class Foo<E>
public E getFoo()
return (E) "Foo";
With the generic return type, I assumed the return in the above example would evaluate to:
return (Integer) "Foo"; // Inconvertible types !!!
Instead a String
is returned and printed correctly.
I get a compilation error if I change the call to be:
String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);
What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.
java generics
java generics
edited 52 mins ago
asked 1 hour ago
Ray
25.9k958103
25.9k958103
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
6
down vote
accepted
This is because overload resolution resolved your println
call to println(Object)
, since there is no println(Integer)
.
Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo"
are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.
In other words, no casts are performed inside getFoo
. The language spec supports this:
Section 5.5.2 Checked Casts and Unchecked Casts
The cast is a completely unchecked cast.
No run-time action is performed for such a cast.
After erasure, getFoo
returns Object
. And that gets passed into println(Object)
, which is perfectly fine.
If I call this method and pass foo.getFoo
, I will get an error:
static void f(Integer i)
System.out.println(i);
// ...
f(foo.getFoo()); // ClassCastException
because this time it needs to be casted.
Think that new rule should be introduced inlint
that highlights generics usage with compile-time constants
â Maxim
1 hour ago
Interesting. So, theE
in the method declarationpublic E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
â Ray
55 mins ago
add a comment |Â
up vote
2
down vote
System.out.println
does not have an overload that takes Integer
. So this statement:
System.out.println(foo.getFoo());
Is calling System.out.println(Object);
.
To verify that it would otherwise fail, try:
Foo<Integer> foo = new Foo<Integer>();
Integer fooInt = foo.getFoo(); //class cast exception
The following will fail in the same way:
public static void main(String args) throws Exception
Foo<Integer> foo = new Foo<Integer>();
print(foo.getFoo()); //Would also fail with a class cast exception
static void print(Integer in)
System.out.println(in);
And this is failing compilation for obvious reasons:
String fooString = foo.getFoo(); //can't work
foo
is Foo<Integer>
, and foo.getFoo()
returns an Integer
and the compiler can pick this up.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
This is because overload resolution resolved your println
call to println(Object)
, since there is no println(Integer)
.
Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo"
are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.
In other words, no casts are performed inside getFoo
. The language spec supports this:
Section 5.5.2 Checked Casts and Unchecked Casts
The cast is a completely unchecked cast.
No run-time action is performed for such a cast.
After erasure, getFoo
returns Object
. And that gets passed into println(Object)
, which is perfectly fine.
If I call this method and pass foo.getFoo
, I will get an error:
static void f(Integer i)
System.out.println(i);
// ...
f(foo.getFoo()); // ClassCastException
because this time it needs to be casted.
Think that new rule should be introduced inlint
that highlights generics usage with compile-time constants
â Maxim
1 hour ago
Interesting. So, theE
in the method declarationpublic E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
â Ray
55 mins ago
add a comment |Â
up vote
6
down vote
accepted
This is because overload resolution resolved your println
call to println(Object)
, since there is no println(Integer)
.
Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo"
are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.
In other words, no casts are performed inside getFoo
. The language spec supports this:
Section 5.5.2 Checked Casts and Unchecked Casts
The cast is a completely unchecked cast.
No run-time action is performed for such a cast.
After erasure, getFoo
returns Object
. And that gets passed into println(Object)
, which is perfectly fine.
If I call this method and pass foo.getFoo
, I will get an error:
static void f(Integer i)
System.out.println(i);
// ...
f(foo.getFoo()); // ClassCastException
because this time it needs to be casted.
Think that new rule should be introduced inlint
that highlights generics usage with compile-time constants
â Maxim
1 hour ago
Interesting. So, theE
in the method declarationpublic E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
â Ray
55 mins ago
add a comment |Â
up vote
6
down vote
accepted
up vote
6
down vote
accepted
This is because overload resolution resolved your println
call to println(Object)
, since there is no println(Integer)
.
Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo"
are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.
In other words, no casts are performed inside getFoo
. The language spec supports this:
Section 5.5.2 Checked Casts and Unchecked Casts
The cast is a completely unchecked cast.
No run-time action is performed for such a cast.
After erasure, getFoo
returns Object
. And that gets passed into println(Object)
, which is perfectly fine.
If I call this method and pass foo.getFoo
, I will get an error:
static void f(Integer i)
System.out.println(i);
// ...
f(foo.getFoo()); // ClassCastException
because this time it needs to be casted.
This is because overload resolution resolved your println
call to println(Object)
, since there is no println(Integer)
.
Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo"
are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.
In other words, no casts are performed inside getFoo
. The language spec supports this:
Section 5.5.2 Checked Casts and Unchecked Casts
The cast is a completely unchecked cast.
No run-time action is performed for such a cast.
After erasure, getFoo
returns Object
. And that gets passed into println(Object)
, which is perfectly fine.
If I call this method and pass foo.getFoo
, I will get an error:
static void f(Integer i)
System.out.println(i);
// ...
f(foo.getFoo()); // ClassCastException
because this time it needs to be casted.
edited 1 hour ago
answered 1 hour ago
Sweeper
55.8k962119
55.8k962119
Think that new rule should be introduced inlint
that highlights generics usage with compile-time constants
â Maxim
1 hour ago
Interesting. So, theE
in the method declarationpublic E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
â Ray
55 mins ago
add a comment |Â
Think that new rule should be introduced inlint
that highlights generics usage with compile-time constants
â Maxim
1 hour ago
Interesting. So, theE
in the method declarationpublic E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
â Ray
55 mins ago
Think that new rule should be introduced in
lint
that highlights generics usage with compile-time constantsâ Maxim
1 hour ago
Think that new rule should be introduced in
lint
that highlights generics usage with compile-time constantsâ Maxim
1 hour ago
Interesting. So, the
E
in the method declaration public E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.â Ray
55 mins ago
Interesting. So, the
E
in the method declaration public E getFoo()
does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.â Ray
55 mins ago
add a comment |Â
up vote
2
down vote
System.out.println
does not have an overload that takes Integer
. So this statement:
System.out.println(foo.getFoo());
Is calling System.out.println(Object);
.
To verify that it would otherwise fail, try:
Foo<Integer> foo = new Foo<Integer>();
Integer fooInt = foo.getFoo(); //class cast exception
The following will fail in the same way:
public static void main(String args) throws Exception
Foo<Integer> foo = new Foo<Integer>();
print(foo.getFoo()); //Would also fail with a class cast exception
static void print(Integer in)
System.out.println(in);
And this is failing compilation for obvious reasons:
String fooString = foo.getFoo(); //can't work
foo
is Foo<Integer>
, and foo.getFoo()
returns an Integer
and the compiler can pick this up.
add a comment |Â
up vote
2
down vote
System.out.println
does not have an overload that takes Integer
. So this statement:
System.out.println(foo.getFoo());
Is calling System.out.println(Object);
.
To verify that it would otherwise fail, try:
Foo<Integer> foo = new Foo<Integer>();
Integer fooInt = foo.getFoo(); //class cast exception
The following will fail in the same way:
public static void main(String args) throws Exception
Foo<Integer> foo = new Foo<Integer>();
print(foo.getFoo()); //Would also fail with a class cast exception
static void print(Integer in)
System.out.println(in);
And this is failing compilation for obvious reasons:
String fooString = foo.getFoo(); //can't work
foo
is Foo<Integer>
, and foo.getFoo()
returns an Integer
and the compiler can pick this up.
add a comment |Â
up vote
2
down vote
up vote
2
down vote
System.out.println
does not have an overload that takes Integer
. So this statement:
System.out.println(foo.getFoo());
Is calling System.out.println(Object);
.
To verify that it would otherwise fail, try:
Foo<Integer> foo = new Foo<Integer>();
Integer fooInt = foo.getFoo(); //class cast exception
The following will fail in the same way:
public static void main(String args) throws Exception
Foo<Integer> foo = new Foo<Integer>();
print(foo.getFoo()); //Would also fail with a class cast exception
static void print(Integer in)
System.out.println(in);
And this is failing compilation for obvious reasons:
String fooString = foo.getFoo(); //can't work
foo
is Foo<Integer>
, and foo.getFoo()
returns an Integer
and the compiler can pick this up.
System.out.println
does not have an overload that takes Integer
. So this statement:
System.out.println(foo.getFoo());
Is calling System.out.println(Object);
.
To verify that it would otherwise fail, try:
Foo<Integer> foo = new Foo<Integer>();
Integer fooInt = foo.getFoo(); //class cast exception
The following will fail in the same way:
public static void main(String args) throws Exception
Foo<Integer> foo = new Foo<Integer>();
print(foo.getFoo()); //Would also fail with a class cast exception
static void print(Integer in)
System.out.println(in);
And this is failing compilation for obvious reasons:
String fooString = foo.getFoo(); //can't work
foo
is Foo<Integer>
, and foo.getFoo()
returns an Integer
and the compiler can pick this up.
answered 1 hour ago
ernest_k
14.5k41429
14.5k41429
add a comment |Â
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%2f52458668%2fwhy-does-this-use-of-generics-not-throw-a-runtime-or-compile-time-exception%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