Javac compiler inconsistencies

Update: this seems to be related to Eclipse, not Hudson, so I updated this question accordingly.

I get some compiler errors when launching Maven on the command line, but all the developers in our group have code that works fine in Eclipse (some common subtleties, see below for details). How can this differ and what to do about it?

Invalid code is as follows:

299 private <T extends ProductClassDTO> List<T> convertProductClass(List<? extends ProductClassDTO> fromList) { 300 List<T> toList = new ArrayList<T>(); 301 for (ProductClassDTO from : fromList) { 302 T to = convert(from); 303 toList.add(to); 304 } 305 return toList; 306 } 

This is an error on the build server:

 [ERROR] ...java:[302,26] type parameters of <T>T cannot be determined; no unique maximal instance exists for type variable T with upper bounds T,com.volvo.protom.util.dto.ProductClassDTO 

(I know there are other questions + answers to this in SO, but they don't seem to apply to this particular question, since switching to T to = <T>convert(from) does not work, maybe I should do that something else?) I "Assuming that the error refers to the fact that there are several convert methods in this class, and more than one are suitable?

Thanks!

Update 2: - this is the signature of the conversion:

 private void convert(TestObjectDTO from, TestObjectDTO to); private <T extends TestObjectDTO> T convert(TestObjectDTO from); private void convert(ProductClassDTO from, ProductClassDTO to); private <T extends ProductClassDTO> T convert(ProductClassDTO from); private void convert(TestObjectTypeDTO from, TestObjectTypeDTO to); private <T extends TestObjectTypeDTO> T convert(TestObjectTypeDTO from); 
+4
source share
2 answers

Eclipse and javac JDK are slightly different, see @maximdim comment. Always run from the command line for compatibility (although Eclipse javac seems to be more correct).

0
source

I think the signatures of these methods are not what they should be. General methods, when a common parameter is found only in the return type (for example, in <T extends ProductClassDTO> T convert(ProductClassDTO) ), usually not what you want.

This means that there is a legitimate method call for the caller and the result is ProductClassDTO to any possible subtype of ProductClassDTO . Usually there is only one possible value satisfying this requirement: null . Thus, conversion methods would always have to return null in order to be type safe. Otherwise, a ClassCastException may appear in the calling code.

Remember that due to type erasure, the convert methods are not able to find out which type the caller wants T , so they cannot return instances of different types according to the value of T

The same problem occurs for the convertProductClass method, although it is not so bad here. This method is required to return a list that contains only those values ​​that the caller can interpret as any subtype of ProductClassDTO . The only values ​​that match this are null , an empty list, and lists containing only null values. All other cases can ClassCastException somewhere when the list is used.

What can you do:

  • If conversion methods are always returned of the same type, change the return type of the methods for that type.
  • If callers do not care about a particular type, but just need to know that it is a subtype of ProductClassDTO , change the return types to ProductClassDTO and List<ProductClassDTO> respectively.
  • If the convert methods should return type instances according to the caller’s desire, you need to explicitly tell them the return type by passing an instance of Class<T> as an additional parameter to all these methods. Convert methods can then use this object to create new instances of the appropriate types.
-one
source

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


All Articles