Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #35482 > unrolled thread
| Started by | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| First post | 2016-08-27 23:50 -0700 |
| Last post | 2016-09-02 15:18 -0700 |
| Articles | 14 — 4 participants |
Back to article view | Back to comp.lang.java.programmer
Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-08-27 23:50 -0700
Re: Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-08-28 00:02 -0700
Re: Java 8 Lambda with generic types Arne Vajhøj <arne@vajhoej.dk> - 2016-08-28 07:46 -0400
Re: Java 8 Lambda with generic types Steven Simpson <ss@my.domain.invalid> - 2016-08-28 15:00 +0100
Re: Java 8 Lambda with generic types Lew <lewbloch@gmail.com> - 2016-08-30 22:25 -0700
Re: Java 8 Lambda with generic types Steven Simpson <ss@my.domain.invalid> - 2016-08-31 17:19 +0100
Re: Java 8 Lambda with generic types Steven Simpson <ss@my.domain.invalid> - 2016-08-28 08:19 +0100
Re: Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-08-28 03:26 -0700
Re: Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-08-28 07:45 -0700
Re: Java 8 Lambda with generic types Arne Vajhøj <arne@vajhoej.dk> - 2016-08-28 13:22 -0400
Re: Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-08-28 07:57 -0700
Re: Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-08-28 10:43 -0700
Re: Java 8 Lambda with generic types Arne Vajhøj <arne@vajhoej.dk> - 2016-08-30 20:35 -0400
Re: Java 8 Lambda with generic types Stone Zhong <stone.zhong@gmail.com> - 2016-09-02 15:18 -0700
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-08-27 23:50 -0700 |
| Subject | Java 8 Lambda with generic types |
| Message-ID | <df44fc1a-9d48-4ba8-890e-a687d24062a9@googlegroups.com> |
Hi there,
It seems sometimes, the compiler is not smart enough to decide the generic parameter type based on labmda argument types, here is an example:
I have a interface, say Toy:
public interface Toy<E> {
List<E> get();
}
Now I have a method to process toys, such as:
public static void checkToy(Toy<?> toy) {
}
Now, the following code works
checkToy(new Toy<Integer>() {
@Override
public List<Integer> get() {
List<Integer> ret = Arrays.asList(10);
return ret;
}
});
However, if I have
checkToy(() -> {
return Arrays.<Integer>asList(10);
});
I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
Thanks,
Stone
[toc] | [next] | [standalone]
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-08-28 00:02 -0700 |
| Message-ID | <cf527430-e940-4ba7-9579-096d1c80bd84@googlegroups.com> |
| In reply to | #35482 |
On Saturday, August 27, 2016 at 11:50:40 PM UTC-7, Stone Zhong wrote:
> Hi there,
>
> It seems sometimes, the compiler is not smart enough to decide the generic parameter type based on labmda argument types, here is an example:
>
> I have a interface, say Toy:
>
> public interface Toy<E> {
> List<E> get();
> }
>
>
> Now I have a method to process toys, such as:
> public static void checkToy(Toy<?> toy) {
> }
>
> Now, the following code works
> checkToy(new Toy<Integer>() {
> @Override
> public List<Integer> get() {
> List<Integer> ret = Arrays.asList(10);
> return ret;
> }
> });
>
> However, if I have
> checkToy(() -> {
> return Arrays.<Integer>asList(10);
> });
>
> I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
>
> Thanks,
> Stone
I just learned if I put all generic parameter in the method parameter even if you do not use it, it helps the compiler to find the right generic parameter type when instantiate the instance. for example:
public interface Toy<E> {
List<E> get(E dummy);
}
did kind of solve the problem, but I do feel bit clumsy doing such thing.
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-28 07:46 -0400 |
| Message-ID | <npuiub$1a5i$1@gioia.aioe.org> |
| In reply to | #35483 |
On 8/28/2016 3:02 AM, Stone Zhong wrote:
> On Saturday, August 27, 2016 at 11:50:40 PM UTC-7, Stone Zhong wrote:
>> It seems sometimes, the compiler is not smart enough to decide the
>> generic parameter type based on labmda argument types, here is an example:
>>
>> I have a interface, say Toy:
>>
>> public interface Toy<E> {
>> List<E> get();
>> }
>>
>>
>> Now I have a method to process toys, such as:
>> public static void checkToy(Toy<?> toy) {
>> }
>>
>> Now, the following code works
>> checkToy(new Toy<Integer>() {
>> @Override
>> public List<Integer> get() {
>> List<Integer> ret = Arrays.asList(10);
>> return ret;
>> }
>> });
>>
>> However, if I have
>> checkToy(() -> {
>> return Arrays.<Integer>asList(10);
>> });
>>
>> I got compiling error: "List<Integer> cannot be converted to
>> List<Object>", it seems compiler tried to create a instance of
>> Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait
>> to tell the compiler it is Toy<Integer> explicitly with the lambda
>> expression?
>
> I just learned if I put all generic parameter in the method
> parametereven if you do not use it, it helps the compiler to find the
> right generic parameter type when instantiate the instance.
> for example:
>
> public interface Toy<E> {
> List<E> get(E dummy);
> }
>
> did kind of solve the problem, but I do feel bit clumsy doing such thing.
I think the problem really is in your checkToy method.
The following works fine:
import java.util.Arrays;
import java.util.List;
public class GenFun {
public static interface Toy<E> {
public List<E> get();
}
public static <E> void checkToy(Toy<E> toy) {
for(E o : toy.get()) {
System.out.println(o);
}
}
public static void main(String[] args) {
checkToy(new Toy<Integer>() {
@Override
public List<Integer> get() {
List<Integer> ret = Arrays.asList(10);
return ret;
}
});
checkToy(() -> { return Arrays.<Integer>asList(10); });
}
}
Arne
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@my.domain.invalid> |
|---|---|
| Date | 2016-08-28 15:00 +0100 |
| Message-ID | <jd7b9d-imi.ln1@s.simpson148.btinternet.com> |
| In reply to | #35486 |
On 28/08/16 12:46, Arne Vajhøj wrote:
> I think the problem really is in your checkToy method.
>
> The following works fine:
>
> import java.util.Arrays;
> import java.util.List;
>
> public class GenFun {
> public static interface Toy<E> {
> public List<E> get();
> }
> public static <E> void checkToy(Toy<E> toy) {
I found that worked too, but what is the difference between that and
<?>, when E is only referenced once?
--
ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | Lew <lewbloch@gmail.com> |
|---|---|
| Date | 2016-08-30 22:25 -0700 |
| Message-ID | <74d17a27-7891-4de2-963d-387108bb6874@googlegroups.com> |
| In reply to | #35487 |
On Sunday, August 28, 2016 at 7:15:11 AM UTC-7, Steven Simpson wrote:
> On 28/08/16 12:46, Arne Vajhøj wrote:
> > I think the problem really is in your checkToy method.
> >
> > The following works fine:
> >
> > import java.util.Arrays;
> > import java.util.List;
> >
> > public class GenFun {
> > public static interface Toy<E> {
> > public List<E> get();
> > }
> > public static <E> void checkToy(Toy<E> toy) {
>
> I found that worked too, but what is the difference between that and
> <?>, when E is only referenced once?
When you use a wildcard in lieu of the generic type parameter, you are losing the information that the type in the <?> is the same as `E`. There is no way for the compiler to know that the type of the `Toy<?> toy` argument is compatible with `E`.
The problem is not with lambdas, but with your incorrect generics.
--
Lew
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@my.domain.invalid> |
|---|---|
| Date | 2016-08-31 17:19 +0100 |
| Message-ID | <skcj9d-c56.ln1@s.simpson148.btinternet.com> |
| In reply to | #35509 |
On 31/08/16 06:25, Lew wrote:
> On Sunday, August 28, 2016 at 7:15:11 AM UTC-7, Steven Simpson wrote:
>> On 28/08/16 12:46, Arne Vajhøj wrote:
>>> public class GenFun {
>>> public static interface Toy<E> {
>>> public List<E> get();
>>> }
>>> public static <E> void checkToy(Toy<E> toy) {
>> I found that worked too, but what is the difference between that and
>> <?>, when E is only referenced once?
> When you use a wildcard in lieu of the generic type parameter, you are losing the information that the type in the <?> is the same as `E`. There is no way for the compiler to know that the type of the `Toy<?> toy` argument is compatible with `E`.
It's possible I've conflated Arne's portion of the discussion with my
own (my mistake), so I'm not sure which E you're referring to.
I mean, if we have:
interface Toy<F> { List<F> get(); }
static <E> void checkToy1(Toy<E> toy) { }
static void checkToy2(Toy<?> toy) { }
static List<Integer> makeList() { ... }
...why does the compiler accept checkToy1(() -> makeList()), but not
checkToy2(() -> makeList())?
Is there a simpler case to demonstrate the distinction? Is there one
without lambdas/method references?
--
ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@my.domain.invalid> |
|---|---|
| Date | 2016-08-28 08:19 +0100 |
| Message-ID | <usfa9d-k75.ln1@s.simpson148.btinternet.com> |
| In reply to | #35482 |
On 28/08/16 07:50, Stone Zhong wrote:
> However, if I have
> checkToy(() -> {
> return Arrays.<Integer>asList(10);
> });
>
> I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
Do you need the <Integer> qualification on asList? It seems to work
without:
import java.util.*;
import java.util.function.*;
public class Funk {
interface Toy<E> {
List<E> get();
}
static void checkToy(Toy<?> toy) { }
public void test() {
checkToy(new Toy<Integer>() {
@Override
public List<Integer> get() {
return Arrays.asList(10);
}
});
checkToy(() -> Arrays.asList(10));
checkToy(() -> { return Arrays.asList(10); });
}
}
--
ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-08-28 03:26 -0700 |
| Message-ID | <08a42ed5-5dc2-4e56-a104-6f72ffb75ab8@googlegroups.com> |
| In reply to | #35482 |
On Saturday, August 27, 2016 at 11:50:40 PM UTC-7, Stone Zhong wrote:
> Hi there,
>
> It seems sometimes, the compiler is not smart enough to decide the generic parameter type based on labmda argument types, here is an example:
>
> I have a interface, say Toy:
>
> public interface Toy<E> {
> List<E> get();
> }
>
>
> Now I have a method to process toys, such as:
> public static void checkToy(Toy<?> toy) {
> }
>
> Now, the following code works
> checkToy(new Toy<Integer>() {
> @Override
> public List<Integer> get() {
> List<Integer> ret = Arrays.asList(10);
> return ret;
> }
> });
>
> However, if I have
> checkToy(() -> {
> return Arrays.<Integer>asList(10);
> });
>
> I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
>
> Thanks,
> Stone
<quote>
Do you need the <Integer> qualification on asList?
</quote>
The point is not to use asList or not, replace "Arrays.<Integer>asList(10)" with any function that returns a List<Integer> will fail as well, you can explicit cast the type, which looks very ugly.
- Stone
[toc] | [prev] | [next] | [standalone]
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-08-28 07:45 -0700 |
| Message-ID | <9ff6ad3e-bb82-4207-91d8-f03c707a1dcf@googlegroups.com> |
| In reply to | #35482 |
On Saturday, August 27, 2016 at 11:50:40 PM UTC-7, Stone Zhong wrote:
> Hi there,
>
> It seems sometimes, the compiler is not smart enough to decide the generic parameter type based on labmda argument types, here is an example:
>
> I have a interface, say Toy:
>
> public interface Toy<E> {
> List<E> get();
> }
>
>
> Now I have a method to process toys, such as:
> public static void checkToy(Toy<?> toy) {
> }
>
> Now, the following code works
> checkToy(new Toy<Integer>() {
> @Override
> public List<Integer> get() {
> List<Integer> ret = Arrays.asList(10);
> return ret;
> }
> });
>
> However, if I have
> checkToy(() -> {
> return Arrays.<Integer>asList(10);
> });
>
> I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
>
> Thanks,
> Stone
<quote>
public static <E> void checkToy(Toy<E> toy) {
</quote>
Having checkToy take generic parameter is a workaround, but it does not solve the problem which it does not work with <?>. For example, if you have:
public static void checkToys(Toy<?> ... toys) {
}
You cannot put a generic type here for checkToys, and you cannot call
checkToys(
() -> Arrays.<Integer>asList(10),
() -> Arrays.<String>asList("hello")
);
But you can do
checkToys(
new Toy<Integer>() {
@Override
public List<Integer> get() {
return Arrays.<Integer>asList(1, 2, 3);
}
},
new Toy<String>() {
@Override
public List<String> get() {
return Arrays.<String>asList("a", "b", "c");
}
}
);
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-28 13:22 -0400 |
| Message-ID | <npv6l1$9c8$1@gioia.aioe.org> |
| In reply to | #35488 |
On 8/28/2016 10:45 AM, Stone Zhong wrote:
> Having checkToy take generic parameter is a workaround, but it does not solve the problem which it does not work with <?>. For example, if you have:
>
>
> public static void checkToys(Toy<?> ... toys) {
> }
>
> You cannot put a generic type here for checkToys, and you cannot call
>
> checkToys(
> () -> Arrays.<Integer>asList(10),
> () -> Arrays.<String>asList("hello")
> );
>
> But you can do
>
> checkToys(
> new Toy<Integer>() {
> @Override
> public List<Integer> get() {
> return Arrays.<Integer>asList(1, 2, 3);
> }
> },
> new Toy<String>() {
> @Override
> public List<String> get() {
> return Arrays.<String>asList("a", "b", "c");
> }
> }
> );
@SuppressWarnings("rawtypes")
public static void checkToys(Toy ... toys) {
Arne
[toc] | [prev] | [next] | [standalone]
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-08-28 07:57 -0700 |
| Message-ID | <b0188e32-5d1c-42ff-b670-a25f52314e49@googlegroups.com> |
| In reply to | #35482 |
On Saturday, August 27, 2016 at 11:50:40 PM UTC-7, Stone Zhong wrote:
> Hi there,
>
> It seems sometimes, the compiler is not smart enough to decide the generic parameter type based on labmda argument types, here is an example:
>
> I have a interface, say Toy:
>
> public interface Toy<E> {
> List<E> get();
> }
>
>
> Now I have a method to process toys, such as:
> public static void checkToy(Toy<?> toy) {
> }
>
> Now, the following code works
> checkToy(new Toy<Integer>() {
> @Override
> public List<Integer> get() {
> List<Integer> ret = Arrays.asList(10);
> return ret;
> }
> });
>
> However, if I have
> checkToy(() -> {
> return Arrays.<Integer>asList(10);
> });
>
> I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
>
> Thanks,
> Stone
I wish java8 allows syntax like
checkToy(<Integer>() -> {
return Arrays.<Integer>asList(10);
});
to help the compiler resolve the generic type when the type has wildcard.
- Stone
[toc] | [prev] | [next] | [standalone]
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-08-28 10:43 -0700 |
| Message-ID | <335820fa-8b00-4bb3-8f0a-8f7c7463364c@googlegroups.com> |
| In reply to | #35482 |
<quote>
@SuppressWarnings("rawtypes")
public static void checkToys(Toy ... toys) {
</quote>
It is not always possible or the best approach to use rawtypes,
for example,
say you have a interface called Duck
public interface Duck {
void squeak();
}
And you need
public static void checkDuckToys(Toy<? extends Duck> ... toys) {
for (Toy<? extends Duck> toy : toys) {
for (Duck duck : toy.get()) {
duck.squeak();
}
}
}
You can make it
public static void checkDuckToys(Toy ... toys) {
Toy<? extends Duck>[] duckToys = (Toy<? extends Duck>[])toys;
for (Toy<? extends Duck> toy : duckToys) {
for (Duck duck : toy.get()) {
duck.squeak();
}
}
}
But it looks pretty ugly.
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-08-30 20:35 -0400 |
| Message-ID | <nq58nu$1qha$1@gioia.aioe.org> |
| In reply to | #35492 |
On 8/28/2016 1:43 PM, Stone Zhong wrote:
> <quote>
> @SuppressWarnings("rawtypes")
> public static void checkToys(Toy ... toys) {
> </quote>
>
> It is not always possible or the best approach to use rawtypes,
> for example,
> say you have a interface called Duck
>
> public interface Duck {
> void squeak();
> }
>
> And you need
> public static void checkDuckToys(Toy<? extends Duck> ... toys) {
> for (Toy<? extends Duck> toy : toys) {
> for (Duck duck : toy.get()) {
> duck.squeak();
> }
> }
> }
True.
And I can not see any easy workarounds.
But I also think that the case is too rare to consider it a real
problem with Java 8 lambda type inference.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Stone Zhong <stone.zhong@gmail.com> |
|---|---|
| Date | 2016-09-02 15:18 -0700 |
| Message-ID | <811d2fe8-04f6-4784-842c-1e5fb2f7765f@googlegroups.com> |
| In reply to | #35482 |
On Saturday, August 27, 2016 at 11:50:40 PM UTC-7, Stone Zhong wrote:
> Hi there,
>
> It seems sometimes, the compiler is not smart enough to decide the generic parameter type based on labmda argument types, here is an example:
>
> I have a interface, say Toy:
>
> public interface Toy<E> {
> List<E> get();
> }
>
>
> Now I have a method to process toys, such as:
> public static void checkToy(Toy<?> toy) {
> }
>
> Now, the following code works
> checkToy(new Toy<Integer>() {
> @Override
> public List<Integer> get() {
> List<Integer> ret = Arrays.asList(10);
> return ret;
> }
> });
>
> However, if I have
> checkToy(() -> {
> return Arrays.<Integer>asList(10);
> });
>
> I got compiling error: "List<Integer> cannot be converted to List<Object>", it seems compiler tried to create a instance of Toy<Object> instead of Toy<Integer> based on the lambda. Is there a wait to tell the compiler it is Toy<Integer> explicitly with the lambda expression?
>
> Thanks,
> Stone
Just figured you can force type conversion for lambda expression like below and it fixed the problem:
checkToy(
(Toy<Integer>) () -> {
return Arrays.<Integer>asList(1, 2);
}
);
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web