简体   繁体   中英

Generics and varargs java

Below is my set up

public interface Test<T extends MyInterface> 
{
    someMethod(T... a)
}

public class TestImpl implements Test<MyInterfaceImpl> 
{
    someMethod(MyInterfaceImpl... a)
}

public class MyInterfaceImpl implements MyInterface {}

public someClass { @Autowired TestFactory testfactory 

......

// getting an error --  Type mismatch Can't assign non-array value to an array 
testfactory.getTest(Type type).someMethod(new MyInterfaceImpl()) 

}

public class TestFactoryImpl implements TestFactory { Test getTest(Type type) { return registry.get(type)}}

which in turn is results in java.lang.ClassCastException: [Lcom.test.MyInterface; cannot be cast to [Lcom.test.Impl.MyInterfaceImpl;

but the below works

testfactory.getTest(Type type).someMethod(new MyInterfaceImpl[]{new MyInterfaceImpl()}) 

Not sure what is happening. Help please

Ok .. the problem is within the design of your already existing code (which you can't change). Having public interface Test<T extends MyInterface> and then public class TestImpl implements Test<MyInterfaceImpl> is wrong.

TestImpl is implementing Test with MyInterfaceImpl whereas the original Test interface only expects an object that extends MyInterface and not implement it.

There will be a type confusion at runtime when executing the code. Not only does the following line throw a ClassCastException

test.someMethod(new MyInterfaceImpl()); 

but also test.someMethod(); by itself throws an exception. So let's say if you factory called this method passing no argument, you would still get an exception as the original designed is flawed. In a normal situation test.someMethod(); should not throw an exception to begin with. You will need to talk to the appropriate party to put a fix to this serious issue.

Below is a sample solution:

The method someMethod(MyInterface...) belongs to the raw type Test . References to generic type Test<T> should be parameterized.

This means you should Test<MyInterfaceImpl> test to avoid getting this error with only the new operator.

Test<MyInterfaceImpl> test
...
test.someMethod(new MyInterfaceImpl()); 

The above code will work with no problem.

A better solution is in your TestImpl class do the following

public class TestImpl implements Test<MyInterface>{...}

instead of

public class TestImpl implements Test<MyInterfaceImpl>{...}

That way you don't need to explicitly parameterize your object instance (ie you could just do

Test test
...
test.someMethod(new MyInterfaceImpl());

)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM