简体   繁体   English

Java泛型-在这种用例中我可以摆脱原始类型吗

[英]Java Generics - can I get rid of the raw type in this use case

I'm working with the following jaxb class hierarchy: 我正在使用以下jaxb类层次结构:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(...)
public class RecordModifyType extends RecordBaseType
{
    ...
    public List<FieldModifyType> getField() { ... }
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(...)
public class RecordAddType extends RecordBaseType
{
    ...
    public List<FieldAddType> getField() { ... }
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(...)
public class FieldModifyType extends FieldBaseType
{
    ...
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(...)
public class FieldAddType extends FieldBaseType
{
    ...
}

I stumbled upon a method in some other class with the following signature ( please note the raw types ): 我偶然发现了其他类中带有以下签名的方法( 请注意原始类型 ):

private void createFields(FTPPartner user, 
                          String addressMasterDataID, 
                          String connectionMasterDataID, 
                          CRTypeEnum crType, 
                          List addrFields, 
                          List connFields)

This method is called from different parts of the class sometimes with List<FieldAddType> as arguments and other times with List<FieldModifyType> . 这种方法是从类有时与不同部分称为List<FieldAddType>作为参数和其它次List<FieldModifyType>

Now I'm trying to get rid of the raw types in its signature. 现在,我试图摆脱其签名中的原始类型。

Following the get-put principle , I decided to change the signature to 按照获取量原则 ,我决定将签名更改为

 private void createFields(FTPPartner user, 
                              String addressMasterDataID, 
                              String connectionMasterDataID, 
                              CRTypeEnum crType, 
                              List<? super FieldBaseType> addrFields, 
                              List<? super FieldBaseType> connFields)
 {
     ...
     FieldBaseType someField = new buildField(...);
     addrFields.add(someField);
     ...
 }

... since the createFields implementation is only putting stuff in these collections. ...因为createFields实现只会将内容放入这些集合中。 The problem is that since RecordModifyType#getFields() returns List<FieldModifyType> and RecordAddType#getFields() returns List<FieldAddType> , I now can not invoke the method, since it only allows for super types of FieldBaseType, not subtypes: 问题在于,由于RecordModifyType#getFields()返回List<FieldModifyType>而RecordAddType#getFields()返回List<FieldAddType> ,我现在无法调用该方法,因为它仅允许FieldBaseType的超类型,而不允许子类型:

RecordAddType addrRecord = getRecordAddType(...);
RecordAddType connRecord = getRecordAddType(...);
List<FieldAddType> addrFields = addrRecord.getFields();
List<FieldAddType> connFields = connRecord.getFields();
createFields(user, 
             addressMasterDataID,
             connectionMasterDataID,
             crType
             addFields, // This won't compile
             connFields); // This won't compile
marshalRecord(addrRecord);
marshalRecord(connRecord);

Using raw types is working as expected - there are no compile errors and marshalling works. 使用原始类型按预期方式工作-没有编译错误和编组工作。

So my question is - is there a way to preserve the behaviour but get rid of the raw types? 所以我的问题是-有没有办法保留行为但摆脱原始类型?

If I understand your problem correctly, the compiler is complaining because it doesn't know that the type ? super FieldBaseType 如果我正确理解了您的问题,则编译器会抱怨,因为它不知道类型? super FieldBaseType ? super FieldBaseType for the call is the the same type for each parameter. 调用的? super FieldBaseType 每个参数的类型相同 Also, because both concrete types are subclasses of FieldBaseType , that's how the type needs to be bound IMHO. 另外,由于这两种具体类型都是FieldBaseType子类, FieldBaseType需要将类型绑定为恕我直言。

Try typing the method: 尝试输入方法:

private <T extends FieldBaseType> void createFields(FTPPartner user, 
                          String addressMasterDataID, 
                          String connectionMasterDataID, 
                          CRTypeEnum crType, 
                          List<T> addrFields, 
                          List<T> connFields) {
    // during the call, the compiler knows that addrFields and connFields
    // hold the same type as each other
}

Now the type is inferred at the call point. 现在,在调用点推断类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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