• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Generic method question - see code example

 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


I don't understand why the above code snippet will not compile. I get the following compile error:

javac Generic1.java
Generic1.java:15: error: incompatible types: String cannot be converted to R
R myIntOrString = "string";
^
where R is a type-variable:
R extends Object declared in method <R>aMethod(R)
1 error

I'm passing in a String to the method so shouldn't the compiler infer that and set the Generic R to of type String?? Someone please tell me what concept I am not understanding about generics.

Thanks!
Kirk
 
Marshal
Posts: 28192
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Line 15 has the error because the compiler can't guarantee that R is a superclass of String under all circumstances.

And the fact that you create a Generic1<String> object at line 19, thus identifying T with String for that particular line of code, doesn't even have anything to do with the type parameter R on the aMethod() method, but even if you'd used T there instead of R it still wouldn't have made any difference because there's nothing in your declaration of the Generic1 class which guarantees that T is a superclass of String either.
 
Kirk Rohani
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:Line 15 has the error because the compiler can't guarantee that R is a superclass of String under all circumstances.

And the fact that you create a Generic1<String> object at line 19, thus identifying T with String for that particular line of code, doesn't even have anything to do with the type parameter R on the aMethod() method, but even if you'd used T there instead of R it still wouldn't have made any difference because there's nothing in your declaration of the Generic1 class which guarantees that T is a superclass of String either.



Thanks Paul. My apologies perhaps I didn't ask my question properly. I know where the error is coming from (line 15), I just don't understand why? I also understand that T and R could have different types.

What I am asking is that in Line 9 I call the method and pass in a String which it takes just fine and should that make it so that the compiler infers that the type for R is a String??

 
Paul Clapham
Marshal
Posts: 28192
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The compiler can't do any inferring on a class which doesn't even compile. As I said, there's no way for the compiler to confirm that R is always a superclass of String, so your Generic1 class can't compile.

And even if it did compile, the R parameter of the aMethod method wouldn't have anything to do with creating a Generic1 object -- that's the constructor which would be involved, not the aMethod method.
 
Kirk Rohani
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:The compiler can't do any inferring on a class which doesn't even compile. As I said, there's no way for the compiler to confirm that R is always a superclass of String, so your Generic1 class can't compile.

And even if it did compile, the R parameter of the aMethod method wouldn't have anything to do with creating a Generic1 object -- that's the constructor which would be involved, not the aMethod method.



Paul - Unfortunately that also did not help me very much. Telling me that it won't compile is not helpful at all. I already knew that. I am asking about the the why and the concept that I am missing when using generics. Nice try however, I do appreciate the feedback.

Anyone else have any other thoughts on this?
 
Paul Clapham
Marshal
Posts: 28192
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't get it. The class won't compile, and you already know why. (Or at least I've explained why twice, and it's a pretty simple reason.) So I don't understand why you think that adding unrelated code elsewhere is going to change that fact.
 
Ranch Hand
Posts: 89
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Your code leads to an evident compile time error. Your type parameter 'R' says that the generic method can take any type argument, 'String', 'CharSequence', 'Number', 'Object'. Lets simplify your code with only one type parameter. I'll create a method inside a regular class:



I explicitly say that the generic method has a bounded type parameter 'R extends Object'. Also I explicitly provide a type argument 'Number' to my generic method. As you can see not only strings can be passed to the generic method. It doesn't matter if the generic method is invoked inside class definition or outside it.
 
Kirk Rohani
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Sergei Zhylinski wrote:Hi,

Your code leads to an evident compile time error. Your type parameter 'R' says that the generic method can take any type argument, 'String', 'CharSequence', 'Number', 'Object'. Lets simplify your code with only one type parameter. I'll create a method inside a regular class:



I explicitly say that the generic method has a bounded type parameter 'R extends Object'. Also I explicitly provide a type argument 'Number' to my generic method. As you can see not only strings can be passed to the generic method. It doesn't matter if the generic method is invoked inside class definition or outside it.



Thank you Sergei, that was a bit more helpful!

So my question now is why am I allowed to do almost the same thing when I create a generic for a Class rather than a method. See below:


For some reason (probably the same reason I am not grasping this concept I don't understand why I can create SomeClass<T> and pass in a string literal into the constructor and assign it to a variable of type <T> and it infers/figures out that it is a string but as you proved I cannot create a generic method and assign a string literal it to a variable of type <R>.

That is really what I am wanting to understand, why it works with a generic class but not a generic method??
 
Paul Clapham
Marshal
Posts: 28192
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You are still missing the fact that you can't find out whether the compiler will do type-inference on a method when you don't have any code which calls that method.

Ohhhh.... now I get it. You're expecting the compiler to look at



and infer from that that R must be a superclass of String. No, that isn't where inference takes place. Type inference takes place in code which is creating an instance of a generic type, or which is calling a method of a generic type. It doesn't take place in the declaration of a generic type.
 
Sergei Zhylinski
Ranch Hand
Posts: 89
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Kirk Rohani wrote:

I don't understand why I can create SomeClass<T> and pass in a string literal into the constructor and assign it to a variable of type <T> and it infers/figures out that it is a string but as you proved I cannot create a generic method and assign a string literal it to a variable of type <R>.

That is really what I am wanting to understand, why it works with a generic class but not a generic method??



Type inference works for generic methods and generic class instantiations and is used by a compiler: "Type inference takes place in code which is creating an instance of a generic type, or which is calling a method of a generic type. It doesn't take place in the declaration of a generic type.
".



Reference 'sc' has a raw type. A raw type (in comparson to parameterized type 'SomeClass<String>') is used for legacy code, when a library doesn't support java 5 or higher. The compiler sees that it is a legacy code (not because it uses type inference for a class) and compiles it, but with warnings. But I think there are no such libraries so I suggest not using raw types at all. JVM is not aware of generics. The compiler will replace all type parameters by their bounds (the bound for 'T' or 'T extends Object' is 'Object') in generic types definitions and erase type arguments in parameterized references. All the JVM will see is:



That is why your code will work:



To use type inference during generic class instantiation a diamond should be used:

reply
    Bookmark Topic Watch Topic
  • New Topic