Scala error: type mismatch; found : java.util.List[?0] required: java.util.List[B]
up vote
1
down vote
favorite
I have below Scala code.
This function defines type parameter type B
which is subclass of A
. It converts java.util.List[A]
into java.util.List[B]
.
import java.util
import java.util.stream.Collectors
class Animal
class Dog extends Animal
class Cat extends Animal
object ObjectConversions extends App
import java.util.List => JList
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
val a= new util.ArrayList[Animal]()
a.add(new Cat)
convertLowerBound[Cat](a)
When I compile this program I get below error.
<console>:15: error: type mismatch;
found : java.util.List[?0]
required: java.util.List[B]
Note: ?0 >: B, but Java-defined trait List is invariant in type E.
You may wish to investigate a wildcard type such as `_ >: B`. (SLS 3.2.10)
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
What is wrong with my program. How can I resolve this error
scala
add a comment |
up vote
1
down vote
favorite
I have below Scala code.
This function defines type parameter type B
which is subclass of A
. It converts java.util.List[A]
into java.util.List[B]
.
import java.util
import java.util.stream.Collectors
class Animal
class Dog extends Animal
class Cat extends Animal
object ObjectConversions extends App
import java.util.List => JList
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
val a= new util.ArrayList[Animal]()
a.add(new Cat)
convertLowerBound[Cat](a)
When I compile this program I get below error.
<console>:15: error: type mismatch;
found : java.util.List[?0]
required: java.util.List[B]
Note: ?0 >: B, but Java-defined trait List is invariant in type E.
You may wish to investigate a wildcard type such as `_ >: B`. (SLS 3.2.10)
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
What is wrong with my program. How can I resolve this error
scala
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have below Scala code.
This function defines type parameter type B
which is subclass of A
. It converts java.util.List[A]
into java.util.List[B]
.
import java.util
import java.util.stream.Collectors
class Animal
class Dog extends Animal
class Cat extends Animal
object ObjectConversions extends App
import java.util.List => JList
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
val a= new util.ArrayList[Animal]()
a.add(new Cat)
convertLowerBound[Cat](a)
When I compile this program I get below error.
<console>:15: error: type mismatch;
found : java.util.List[?0]
required: java.util.List[B]
Note: ?0 >: B, but Java-defined trait List is invariant in type E.
You may wish to investigate a wildcard type such as `_ >: B`. (SLS 3.2.10)
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
What is wrong with my program. How can I resolve this error
scala
I have below Scala code.
This function defines type parameter type B
which is subclass of A
. It converts java.util.List[A]
into java.util.List[B]
.
import java.util
import java.util.stream.Collectors
class Animal
class Dog extends Animal
class Cat extends Animal
object ObjectConversions extends App
import java.util.List => JList
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
val a= new util.ArrayList[Animal]()
a.add(new Cat)
convertLowerBound[Cat](a)
When I compile this program I get below error.
<console>:15: error: type mismatch;
found : java.util.List[?0]
required: java.util.List[B]
Note: ?0 >: B, but Java-defined trait List is invariant in type E.
You may wish to investigate a wildcard type such as `_ >: B`. (SLS 3.2.10)
implicit def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map(a => a.asInstanceOf[B]).collect(Collectors.toList())
What is wrong with my program. How can I resolve this error
scala
scala
edited Nov 9 at 19:04
asked Nov 9 at 18:18
Rajkumar Natarajan
1,1171237
1,1171237
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
It looks like type erasure happened (from Animal to ?0) when using java.util.stream.Stream.map
, regardless B or concrete type passed in, possibly due to incompatibility between Scala type inference and Java type inference.
When calling Java method and you still want generic type inference, you need to pass the generic type specifically:
def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
Then you can do your operation successfully:
scala> def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
convertLowerBound: [B <: Animal](a: java.util.List[Animal])java.util.List[B]
scala> convertLowerBound[Cat](a)
res30: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
On the other hand, your conversion isn't really useful, because during runtime, all the generic type will be erased so List[A] or List[B] will be the same after compiling (they will become List of Object. You can take a look at the compiled bytecode). You can simply do direct casting on your List instead of on each element:
def convertLowerBound[B <: Animal : TypeTag] (a: JList[Animal]) = a.asInstanceOf[JList[B]]
Then you can do your use case successfully:
scala> a.add(new Cat())
res16: Boolean = true
scala> convertLowerBound[Cat](a)
res17: java.util.List[Cat] = [Cat@6325af19]
However when there is a type mismatch, e.g. you add a Dog in the List and try to cast it as a List of Cat, an error will occur, only when you try to access the element:
scala> a.add(new Dog())
res19: Boolean = true
scala> convertLowerBound[Cat](a)
res20: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
scala> convertLowerBound[Cat](a).get(1)
java.lang.ClassCastException: Dog cannot be cast to Cat
... 28 elided
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
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
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53231319%2fscala-error-type-mismatch-found-java-util-list0-required-java-util-list%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
It looks like type erasure happened (from Animal to ?0) when using java.util.stream.Stream.map
, regardless B or concrete type passed in, possibly due to incompatibility between Scala type inference and Java type inference.
When calling Java method and you still want generic type inference, you need to pass the generic type specifically:
def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
Then you can do your operation successfully:
scala> def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
convertLowerBound: [B <: Animal](a: java.util.List[Animal])java.util.List[B]
scala> convertLowerBound[Cat](a)
res30: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
On the other hand, your conversion isn't really useful, because during runtime, all the generic type will be erased so List[A] or List[B] will be the same after compiling (they will become List of Object. You can take a look at the compiled bytecode). You can simply do direct casting on your List instead of on each element:
def convertLowerBound[B <: Animal : TypeTag] (a: JList[Animal]) = a.asInstanceOf[JList[B]]
Then you can do your use case successfully:
scala> a.add(new Cat())
res16: Boolean = true
scala> convertLowerBound[Cat](a)
res17: java.util.List[Cat] = [Cat@6325af19]
However when there is a type mismatch, e.g. you add a Dog in the List and try to cast it as a List of Cat, an error will occur, only when you try to access the element:
scala> a.add(new Dog())
res19: Boolean = true
scala> convertLowerBound[Cat](a)
res20: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
scala> convertLowerBound[Cat](a).get(1)
java.lang.ClassCastException: Dog cannot be cast to Cat
... 28 elided
add a comment |
up vote
3
down vote
accepted
It looks like type erasure happened (from Animal to ?0) when using java.util.stream.Stream.map
, regardless B or concrete type passed in, possibly due to incompatibility between Scala type inference and Java type inference.
When calling Java method and you still want generic type inference, you need to pass the generic type specifically:
def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
Then you can do your operation successfully:
scala> def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
convertLowerBound: [B <: Animal](a: java.util.List[Animal])java.util.List[B]
scala> convertLowerBound[Cat](a)
res30: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
On the other hand, your conversion isn't really useful, because during runtime, all the generic type will be erased so List[A] or List[B] will be the same after compiling (they will become List of Object. You can take a look at the compiled bytecode). You can simply do direct casting on your List instead of on each element:
def convertLowerBound[B <: Animal : TypeTag] (a: JList[Animal]) = a.asInstanceOf[JList[B]]
Then you can do your use case successfully:
scala> a.add(new Cat())
res16: Boolean = true
scala> convertLowerBound[Cat](a)
res17: java.util.List[Cat] = [Cat@6325af19]
However when there is a type mismatch, e.g. you add a Dog in the List and try to cast it as a List of Cat, an error will occur, only when you try to access the element:
scala> a.add(new Dog())
res19: Boolean = true
scala> convertLowerBound[Cat](a)
res20: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
scala> convertLowerBound[Cat](a).get(1)
java.lang.ClassCastException: Dog cannot be cast to Cat
... 28 elided
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
It looks like type erasure happened (from Animal to ?0) when using java.util.stream.Stream.map
, regardless B or concrete type passed in, possibly due to incompatibility between Scala type inference and Java type inference.
When calling Java method and you still want generic type inference, you need to pass the generic type specifically:
def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
Then you can do your operation successfully:
scala> def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
convertLowerBound: [B <: Animal](a: java.util.List[Animal])java.util.List[B]
scala> convertLowerBound[Cat](a)
res30: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
On the other hand, your conversion isn't really useful, because during runtime, all the generic type will be erased so List[A] or List[B] will be the same after compiling (they will become List of Object. You can take a look at the compiled bytecode). You can simply do direct casting on your List instead of on each element:
def convertLowerBound[B <: Animal : TypeTag] (a: JList[Animal]) = a.asInstanceOf[JList[B]]
Then you can do your use case successfully:
scala> a.add(new Cat())
res16: Boolean = true
scala> convertLowerBound[Cat](a)
res17: java.util.List[Cat] = [Cat@6325af19]
However when there is a type mismatch, e.g. you add a Dog in the List and try to cast it as a List of Cat, an error will occur, only when you try to access the element:
scala> a.add(new Dog())
res19: Boolean = true
scala> convertLowerBound[Cat](a)
res20: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
scala> convertLowerBound[Cat](a).get(1)
java.lang.ClassCastException: Dog cannot be cast to Cat
... 28 elided
It looks like type erasure happened (from Animal to ?0) when using java.util.stream.Stream.map
, regardless B or concrete type passed in, possibly due to incompatibility between Scala type inference and Java type inference.
When calling Java method and you still want generic type inference, you need to pass the generic type specifically:
def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
Then you can do your operation successfully:
scala> def convertLowerBound[ B <: Animal] (a: JList[Animal]): JList[B] = a.stream().map[B](a => a.asInstanceOf[B]).collect(Collectors.toList[B]())
convertLowerBound: [B <: Animal](a: java.util.List[Animal])java.util.List[B]
scala> convertLowerBound[Cat](a)
res30: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
On the other hand, your conversion isn't really useful, because during runtime, all the generic type will be erased so List[A] or List[B] will be the same after compiling (they will become List of Object. You can take a look at the compiled bytecode). You can simply do direct casting on your List instead of on each element:
def convertLowerBound[B <: Animal : TypeTag] (a: JList[Animal]) = a.asInstanceOf[JList[B]]
Then you can do your use case successfully:
scala> a.add(new Cat())
res16: Boolean = true
scala> convertLowerBound[Cat](a)
res17: java.util.List[Cat] = [Cat@6325af19]
However when there is a type mismatch, e.g. you add a Dog in the List and try to cast it as a List of Cat, an error will occur, only when you try to access the element:
scala> a.add(new Dog())
res19: Boolean = true
scala> convertLowerBound[Cat](a)
res20: java.util.List[Cat] = [Cat@6325af19, Dog@6ff6743f]
scala> convertLowerBound[Cat](a).get(1)
java.lang.ClassCastException: Dog cannot be cast to Cat
... 28 elided
edited Nov 9 at 20:15
answered Nov 9 at 20:05
texasbruce
8,27874193
8,27874193
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53231319%2fscala-error-type-mismatch-found-java-util-list0-required-java-util-list%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown