- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Problem with Java Generics and Wildcards in Scala
Wed, 2011-08-17, 21:30
Hi Scala users,
I'm not able to solve a problem with Java Generics and Wildcards in
Scala, maybe some experts can help me here. Or maybe it's a bug - I
don't know...
I'm trying to implement an extension of the DefaultListCellRenderer
(Swing), which is needed for a List in my Swing application. There were
no problems with Java 6.
I needed to change to Java 7, which has introduced a minor change in the
API of the interface ListCellRenderer and the class
DefaultListCellRenderer - Java Generics were added.
Here's the API-excerpt of DefaultListCellRenderer.java:
public class DefaultListCellRenderer extends JLabel
implements ListCellRenderer, Serializable {
public Component getListCellRendererComponent(JList<?> list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {...}
...
}
And here's the API-excerpt of ListCellRenderer.java:
public interface ListCellRenderer {
Component getListCellRendererComponent(JList<? extends E> list,
E value, int index, boolean isSelected, boolean cellHasFocus);
...
}
And here is my extension of class DefaultListCellRenderer, which can't
be compiled (tested with Scala 2.8.1 and 2.9.0.1):
import java.awt.Component
import javax.swing.{DefaultListCellRenderer, JList}
class ScalaListCellRenderer extends DefaultListCellRenderer {
override def getListCellRendererComponent(
list: JList[_ <: Object], value: Object, index: Int,
isSelected: Boolean, cellHasFocus: Boolean): Component = {
val component = super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus)
// ... do some component customization here ...
component
}
}
The compiler error is:
ambiguous reference to overloaded definition, both method
getListCellRendererComponent in class DefaultListCellRenderer of type
(x$1: javax.swing.JList[_], x$2: Any, x$3: Int, x$4: Boolean, x$5:
Boolean)java.awt.Component and method getListCellRendererComponent in
trait ListCellRenderer of type (x$1: javax.swing.JList[_ <:
java.lang.Object], x$2: java.lang.Object, x$3: Int, x$4: Boolean, x$5:
Boolean)java.awt.Component match argument types
(javax.swing.JList[_$1],java.lang.Object,Int,Boolean,Boolean)
I've also tried to change the Generics wildcard to JList[_]:
class ScalaListCellRenderer extends DefaultListCellRenderer {
override def getListCellRendererComponent(
list: JList[_], value: Object, index: Int, isSelected: Boolean,
cellHasFocus: Boolean): Component = {
val component = super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus)
// ... do some component customization here ...
component
}
}
But then I'm getting this compiler error:
class ScalaListCellRenderer needs to be abstract, since method
getListCellRendererComponent in trait ListCellRenderer of type (x$1:
javax.swing.JList[_ <: java.lang.Object], x$2: java.lang.Object, x$3:
Int, x$4: Boolean, x$5: Boolean)java.awt.Component is not defined
I can't find a solution for this problem. Does somebody has an idea or
is it not possible to solve the problem?
Thanks in advance,
Stefan
Thu, 2011-08-18, 17:47
#2
Problem with Java Generics and Wildcards in Scala
Yes, for me it seems that Scala is not able to handle this Java<->Scala
Generics conflict. But I'm not sure whether this is a Scala problem /
bug or not...
Am 18.08.2011 18:18, schrieb John Cheng:
> Its weird that these posts are not showing up in the user group. I did
> download J7SE and test out the scenario and started seeing the same
> problem you did.
>
> Scala is recognizing DefaultListCellRenderer and ListCellRenderer as
> having separate method signatures.
>
> On Thu, Aug 18, 2011 at 8:32 AM, Stefan Saring wrote:
>> Hi John,
>>
>> thanks for your feedback. But it doesn't help. When I change the method
>> signature to
>>
>> override def getListCellRendererComponent(list: JList[Object],
>> value: Object, index: Int, isSelected: Boolean,
>> cellHasFocus: Boolean): Component = { ... }
>>
>> then I get this error:
>>
>> "method getListCellRendererComponent overrides nothing"
>>
>> Another ideas?
>>
>> Bye, Stefan
>>
>>
>> Am 18.08.2011 00:28, schrieb John L. Cheng:
>>> I don't have Java 8 installed, but since DefaultListCellRenderer
>>> implements ListCellRenderer instead of ListCellRenderer<?>,
>>> does that mean you need to parameterise with "Object" as well?
>>>
>>> class ScalaListCellRenderer extends DefaultListCellRenderer {
>>> override def getListCellRendererComponent(
>>> list: JList[Object], value: Object, index: Int, isSelected:
>>> Boolean,
>>> cellHasFocus: Boolean): Component = {
>>> val component = super.getListCellRendererComponent(
>>> list, value, index, isSelected, cellHasFocus)
>>> // ... do some component customization here ...
>>> component
>>> }
>>> }
>>>
>>> Note JList[Object} in the method signature
>>>
>>> On Aug 17, 1:30 pm, Stefan Saring wrote:
>>>> Hi Scala users,
>>>>
>>>> I'm not able to solve a problem with Java Generics and Wildcards in
>>>> Scala, maybe some experts can help me here. Or maybe it's a bug - I
>>>> don't know...
>>>>
>>>> I'm trying to implement an extension of the DefaultListCellRenderer
>>>> (Swing), which is needed for a List in my Swing application. There were
>>>> no problems with Java 6.
>>>>
>>>> I needed to change to Java 7, which has introduced a minor change in the
>>>> API of the interface ListCellRenderer and the class
>>>> DefaultListCellRenderer - Java Generics were added.
>>>>
>>>> Here's the API-excerpt of DefaultListCellRenderer.java:
>>>>
>>>> public class DefaultListCellRenderer extends JLabel
>>>> implements ListCellRenderer, Serializable {
>>>>
>>>> public Component getListCellRendererComponent(JList<?> list,
>>>> Object value, int index, boolean isSelected,
>>>> boolean cellHasFocus) {...}
>>>> ...
>>>>
>>>> }
>>>>
>>>> And here's the API-excerpt of ListCellRenderer.java:
>>>>
>>>> public interface ListCellRenderer {
>>>>
>>>> Component getListCellRendererComponent(JList<? extends E> list,
>>>> E value, int index, boolean isSelected, boolean cellHasFocus);
>>>> ...
>>>>
>>>> }
>>>>
>>>> And here is my extension of class DefaultListCellRenderer, which can't
>>>> be compiled (tested with Scala 2.8.1 and 2.9.0.1):
>>>>
>>>> import java.awt.Component
>>>> import javax.swing.{DefaultListCellRenderer, JList}
>>>>
>>>> class ScalaListCellRenderer extends DefaultListCellRenderer {
>>>>
>>>> override def getListCellRendererComponent(
>>>> list: JList[_ <: Object], value: Object, index: Int,
>>>> isSelected: Boolean, cellHasFocus: Boolean): Component = {
>>>>
>>>> val component = super.getListCellRendererComponent(
>>>> list, value, index, isSelected, cellHasFocus)
>>>> // ... do some component customization here ...
>>>> component
>>>> }
>>>>
>>>> }
>>>>
>>>> The compiler error is:
>>>>
>>>> ambiguous reference to overloaded definition, both method
>>>> getListCellRendererComponent in class DefaultListCellRenderer of type
>>>> (x$1: javax.swing.JList[_], x$2: Any, x$3: Int, x$4: Boolean, x$5:
>>>> Boolean)java.awt.Component and method getListCellRendererComponent in
>>>> trait ListCellRenderer of type (x$1: javax.swing.JList[_ <:
>>>> java.lang.Object], x$2: java.lang.Object, x$3: Int, x$4: Boolean, x$5:
>>>> Boolean)java.awt.Component match argument types
>>>> (javax.swing.JList[_$1],java.lang.Object,Int,Boolean,Boolean)
>>>>
>>>> I've also tried to change the Generics wildcard to JList[_]:
>>>>
>>>> class ScalaListCellRenderer extends DefaultListCellRenderer {
>>>>
>>>> override def getListCellRendererComponent(
>>>> list: JList[_], value: Object, index: Int, isSelected: Boolean,
>>>> cellHasFocus: Boolean): Component = {
>>>>
>>>> val component = super.getListCellRendererComponent(
>>>> list, value, index, isSelected, cellHasFocus)
>>>> // ... do some component customization here ...
>>>> component
>>>> }
>>>>
>>>> }
>>>>
>>>> But then I'm getting this compiler error:
>>>>
>>>> class ScalaListCellRenderer needs to be abstract, since method
>>>> getListCellRendererComponent in trait ListCellRenderer of type (x$1:
>>>> javax.swing.JList[_ <: java.lang.Object], x$2: java.lang.Object, x$3:
>>>> Int, x$4: Boolean, x$5: Boolean)java.awt.Component is not defined
>>>>
>>>> I can't find a solution for this problem. Does somebody has an idea or
>>>> is it not possible to solve the problem?
>>>>
>>>> Thanks in advance,
>>>> Stefan
>>>
>>
>>
>
>
>
Thu, 2011-08-18, 17:57
#3
Problem with Java Generics and Wildcards in Scala
Does this mean that it's not possible to solve the problem at the
moment? Or is there any workaround without patching the JDK 7 ?
Bye, Stefan
Am 18.08.2011 18:35, schrieb Paul Phillips:
> https://issues.scala-lang.org/browse/SI-3634
> https://github.com/scala/scala/tree/openjdk
>
> Remedies are presently under discussion on scala-internals.
>
Thu, 2011-08-18, 18:17
#4
Problem with Java Generics and Wildcards in Scala
OK, but how should it be possible to compile against Java 7 only?
I'm not able to extend the class DefaultListCellRenderer of Java 7 (as
shown in the first post of this topic).
Am 18.08.2011 19:02, schrieb Paul Phillips:
> On 8/18/11 9:56 AM, Stefan Saring wrote:
>> Does this mean that it's not possible to solve the problem at the
>> moment? Or is there any workaround without patching the JDK 7 ?
>
> It means it is not at present possible to compile against jdk6 and jdk7
> with the same scala source base if you use one of the classes which
> acquired type parameters.
>
Thu, 2011-08-18, 19:37
#5
Problem with Java Generics and Wildcards in Scala
Finally I was able to solve the problem with a simple workaround. Here's
the solution for extending the DefaultListCellRenderer (Task is my
domain class):
object TaskCellRenderer extends ListCellRenderer[Task] {
val peerRenderer: ListCellRenderer[Task] = (new
DefaultListCellRenderer).asInstanceOf[ListCellRenderer[Task]]
override def getListCellRendererComponent (
list: JList[_ <: Task], task: Task, index: Int,
isSelected: Boolean, cellHasFocus: Boolean): Component = {
val component = peerRenderer.getListCellRendererComponent(
list, task, index, isSelected, cellHasFocus)
.asInstanceOf[JComponent]
// ... do some component customization here ...
component
}
}
Instead of extending the DefaultListCellRenderer directly I implement
the ListCellRenderer interface. This has a casted
DefaultListCellRenderer as a peer which is beeing used as a delegate in
the implementation of getListCellRendererComponent(...).
This works without problems with the unmodified Java 7 and the
unmodified Scala 2.9.0.1.
Thanks to all for the help!
Bye, Stefan
Am 18.08.2011 19:39, schrieb Paul Phillips:
> On 8/18/11 10:08 AM, Stefan Saring wrote:
>> OK, but how should it be possible to compile against Java 7 only?
>> I'm not able to extend the class DefaultListCellRenderer of Java 7 (as
>> shown in the first post of this topic).
>
> That's why I sent you the links. Scala can't build against both of them
> simultaneously any better than you can, which means you need a build of
> scala against java7.
>
> https://github.com/scala/scala/tree/openjdk
>
Hi John,
thanks for your feedback. But it doesn't help. When I change the method
signature to
override def getListCellRendererComponent(list: JList[Object],
value: Object, index: Int, isSelected: Boolean,
cellHasFocus: Boolean): Component = { ... }
then I get this error:
"method getListCellRendererComponent overrides nothing"
Another ideas?
Bye, Stefan
Am 18.08.2011 00:28, schrieb John L. Cheng:
> I don't have Java 8 installed, but since DefaultListCellRenderer
> implements ListCellRenderer instead of ListCellRenderer<?>,
> does that mean you need to parameterise with "Object" as well?
>
> class ScalaListCellRenderer extends DefaultListCellRenderer {
> override def getListCellRendererComponent(
> list: JList[Object], value: Object, index: Int, isSelected:
> Boolean,
> cellHasFocus: Boolean): Component = {
> val component = super.getListCellRendererComponent(
> list, value, index, isSelected, cellHasFocus)
> // ... do some component customization here ...
> component
> }
> }
>
> Note JList[Object} in the method signature
>
> On Aug 17, 1:30 pm, Stefan Saring wrote:
>> Hi Scala users,
>>
>> I'm not able to solve a problem with Java Generics and Wildcards in
>> Scala, maybe some experts can help me here. Or maybe it's a bug - I
>> don't know...
>>
>> I'm trying to implement an extension of the DefaultListCellRenderer
>> (Swing), which is needed for a List in my Swing application. There were
>> no problems with Java 6.
>>
>> I needed to change to Java 7, which has introduced a minor change in the
>> API of the interface ListCellRenderer and the class
>> DefaultListCellRenderer - Java Generics were added.
>>
>> Here's the API-excerpt of DefaultListCellRenderer.java:
>>
>> public class DefaultListCellRenderer extends JLabel
>> implements ListCellRenderer, Serializable {
>>
>> public Component getListCellRendererComponent(JList<?> list,
>> Object value, int index, boolean isSelected,
>> boolean cellHasFocus) {...}
>> ...
>>
>> }
>>
>> And here's the API-excerpt of ListCellRenderer.java:
>>
>> public interface ListCellRenderer {
>>
>> Component getListCellRendererComponent(JList<? extends E> list,
>> E value, int index, boolean isSelected, boolean cellHasFocus);
>> ...
>>
>> }
>>
>> And here is my extension of class DefaultListCellRenderer, which can't
>> be compiled (tested with Scala 2.8.1 and 2.9.0.1):
>>
>> import java.awt.Component
>> import javax.swing.{DefaultListCellRenderer, JList}
>>
>> class ScalaListCellRenderer extends DefaultListCellRenderer {
>>
>> override def getListCellRendererComponent(
>> list: JList[_ <: Object], value: Object, index: Int,
>> isSelected: Boolean, cellHasFocus: Boolean): Component = {
>>
>> val component = super.getListCellRendererComponent(
>> list, value, index, isSelected, cellHasFocus)
>> // ... do some component customization here ...
>> component
>> }
>>
>> }
>>
>> The compiler error is:
>>
>> ambiguous reference to overloaded definition, both method
>> getListCellRendererComponent in class DefaultListCellRenderer of type
>> (x$1: javax.swing.JList[_], x$2: Any, x$3: Int, x$4: Boolean, x$5:
>> Boolean)java.awt.Component and method getListCellRendererComponent in
>> trait ListCellRenderer of type (x$1: javax.swing.JList[_ <:
>> java.lang.Object], x$2: java.lang.Object, x$3: Int, x$4: Boolean, x$5:
>> Boolean)java.awt.Component match argument types
>> (javax.swing.JList[_$1],java.lang.Object,Int,Boolean,Boolean)
>>
>> I've also tried to change the Generics wildcard to JList[_]:
>>
>> class ScalaListCellRenderer extends DefaultListCellRenderer {
>>
>> override def getListCellRendererComponent(
>> list: JList[_], value: Object, index: Int, isSelected: Boolean,
>> cellHasFocus: Boolean): Component = {
>>
>> val component = super.getListCellRendererComponent(
>> list, value, index, isSelected, cellHasFocus)
>> // ... do some component customization here ...
>> component
>> }
>>
>> }
>>
>> But then I'm getting this compiler error:
>>
>> class ScalaListCellRenderer needs to be abstract, since method
>> getListCellRendererComponent in trait ListCellRenderer of type (x$1:
>> javax.swing.JList[_ <: java.lang.Object], x$2: java.lang.Object, x$3:
>> Int, x$4: Boolean, x$5: Boolean)java.awt.Component is not defined
>>
>> I can't find a solution for this problem. Does somebody has an idea or
>> is it not possible to solve the problem?
>>
>> Thanks in advance,
>> Stefan
>