Why doesn't type inference work?

Suppose I have the following classes:

interface MyS<T extends MyT<S, T>, S extends MyS<T, S>> { } interface MyT<S extends MyS<T, S>, T extends MyT<S, T>> { } public class MySImpl implements MyS<MyTImpl, MySImpl> { } public class MyTImpl implements MyT<MySImpl, MyTImpl> { } 

I can create the following test file that compiles and runs without warning:

 public class STTest { @Test public void test() throws Exception { createInstance(MyTImpl.class); } public static<T extends MyT<S, T>, S extends MyS<T, S>> void createInstance( final Class<? extends MyT<S, T>> beanClass) throws Exception { final MyT<S, T> bean = beanClass.newInstance(); } } 

Good Excellent. But I expected this to have the same effect:

 public class STTest { @Test public void test() throws Exception { createInstance(MyTImpl.class); } public static<T extends MyT<S, T>, S extends MyS<T, S>> void createInstance( final Class<T> beanClass) throws Exception { final T bean = beanClass.newInstance(); } } 

However, this is a compilation error:

invalid deduced types for S; supposed type does not match declared bounds (s): mySImpl bound (s): MyS

Why is this?

UPDATE:

I noticed that the behavior is compiler dependent. I used the OpenJDK 1.6 compiler (javac 1.6.0_27) to compile the code. And it breaks. But:

  • OpenJDK 1.7 compiler (javac 1.7.0_21) and
  • Oracle 1.6 compiler (javac 1.6.0_37)

both work fine in the second example.

However: Is this a bug in the OpenJDK 1.6 compiler or is it an ambiguity in the Java language specification?

+4
source share
1 answer

The argument type does not mention S in the second example. The compiler tells you that therefore it cannot do this.

To develop. In the first example, you are requesting Class<? extends MyT<S, T>> Class<? extends MyT<S, T>> . In test() you give it a Class<MyTImpl> . Since the compiler checks the boundaries, it matches MyT<S, T> with MyTImpl and finds that MyTImpl implements MyT<MySImpl, MyTImpl> , so it can output MySImpl for S and MyTImpl for T by simply MyTImpl these two things together.

He then checks the restrictions on S and T for MySImpl and MyTImpl , which succeeds.

In the second example, you are querying for Class<T> . The compiler sees Class<MyTImpl> , displays MyTImpl for T and is executed. If you do not conclude S , it will be an error.

Checking constraints for T , which can provide information that S does not occur.

+3
source

Source: https://habr.com/ru/post/1486068/


All Articles