简体   繁体   English

Java泛型-通配符

[英]Java Generics - wildcards

I'm new to Java and have gotten myself into a situation where it's evident that I'm misunderstanding something about how it handles Generics, but reading tutorials and searching stackoverflow hasn't (at least so far) given me clarity beyond that I suspect I'm misusing wildcards. 我是Java的新手,我陷入了一种情况,很明显我对它如何处理泛型有误解,但阅读教程和搜索stackoverflow并没有(至少到目前为止)没有使我更加清楚我滥用通配符。 As a heads up I have a C++ background, so how it deals with templates is probably coloring how I've approached this. 请注意,我具有C ++背景,因此它与模板的处理方式可能会为我的处理方式着色。

Here's the basic structure of my inheritance using representative classes 这是我使用代表类进行继承的基本结构

abstract class PacketHeader{
   // some stuff
}

class TypeOfPacketHeader extends PacketHeader{
   // extended stuff
}

abstract class Packet<T extends PacketHeader>{
    T mHeader;
    // some methods treating T as a type of PacketHeader
    // some abstract methods
}

class TypeOfPacket extends Packet<TypeOfPacketHeader>{
    static TypeOfPacket obtain {
        return new TypeOfPacket();
    }
    // overriden abstract functions that call specific TypeOfPacketHeader methods on mHeader
}

interface PacketParser<T extends Packet<? extends PacketHeader>>{
T obtainPacket();
        void parse(T packet);
}

class ImplementedPacketParser implements PacketParser<TypeOfPacket>{
     TypeOfPacket obtainPacket(){
         return TypeOfPacket.obtain();
     }
     void parse(TypeOfPacket packet){
         // code that relies on TypeOfPacket specific functions
     }
}

That seems to all be correct (or at least eclipse isn't complaining), issues seem to arise when I'm attempting to make use of them. 这似乎都是正确的(或者至少是日食没有抱怨),当我尝试使用它们时似乎出现了问题。 My first attempt was: 我的第一次尝试是:

class User{
    PacketParser mParser;

    User(PacketParser parser){
        mParser = parser;
    }

    void DoSomething(){
         Packet packet = mParser.obtainPacket();
         // do some stuff with the packet
         mParser.parse(packet);
    }
}

and led to warnings of Raw types. 并引发了Raw类型的警告。 So I tried... 所以我尝试了...

class User{
    PacketParser<? extends Packet<? extends PacketHeader>> mParser;

    User(PacketParser<? extends Packet<? extends PacketHeader>> parser){
        mParser = parser;
    }

    void DoSomething(){
         Packet<? extends PacketHeader> packet = parser.obtainPacket();
         // do some stuff with the packet
         mParser.parse(packet);
    }
}

But this leads to an error that 但这会导致错误

The method parse(capture#9-of ? extends Packet) in the type PacketParser> is not applicable for the arguments (Packet) 类型为PacketParser>的方法parse(capture#9-of扩展Packet)不适用于参数(Packet)

At this point I've decided that I'm misunderstanding something about how the generics are working, so I've turned to stackoverflow to hopefully point me to where I've gone wrong and maybe point me in the right direction. 在这一点上我已经决定,我误解一些关于泛型是如何工作的,所以我转向StackOverflow的,希望能够指向我,我已经走了错,也许我指出正确的方向。

I have made some changes to your code.It compiling now.Try using this. 我对您的代码进行了一些更改。现在可以编译。尝试使用此代码。

   abstract class PacketHeader {
    // some stuff
   } 
   class TypeOfPacketHeader extends PacketHeader {
        // extended stuff
    }

    abstract class Packet<T extends PacketHeader> {
        T mHeader;
        // some methods treating T as a type of PacketHeader
        // some abstract methods
    }

    class TypeOfPacket extends Packet<TypeOfPacketHeader> {
        static TypeOfPacket obtain() {
            return new TypeOfPacket();
        }
        // overriden abstract functions that call specific TypeOfPacketHeader
        // methods on mHeader
    }

    interface PacketParser<T extends Packet<? extends PacketHeader>> {
        T obtainPacket();

        void parse(T packet);
    }

    class ImplementedPacketParser implements PacketParser<TypeOfPacket> {
        public TypeOfPacket obtainPacket() {
            return TypeOfPacket().obtain();
        }

        private TypeOfPacket TypeOfPacket() {
            // TODO Auto-generated method stub
            return null;
        }

        public void parse(TypeOfPacket packet) {
            // code that relies on TypeOfPacket specific functions
        }
    }

Your User Class. 您的用户类别。

class User{
    private PacketParser mParser;

    User(PacketParser parser) {
        mParser = parser;
    }

    void DoSomething() {
        Packet packet = mParser.obtainPacket();
        // do some stuff with the packet
        mParser.parse(packet);
    }
}

In your User code, the compiler doesn't know that the ? extends Packet<? extends PacketHeader> 在您的User代码中,编译器不知道? extends Packet<? extends PacketHeader> ? extends Packet<? extends PacketHeader> ? extends Packet<? extends PacketHeader> on the mParser field is the same type as the Packet<? extends PacketHeader> packet mParser字段上的mParser ? extends Packet<? extends PacketHeader>Packet<? extends PacketHeader> packet类型相同Packet<? extends PacketHeader> packet Packet<? extends PacketHeader> packet local variable. Packet<? extends PacketHeader> packet局部变量。

You need to bind the type of packet that will be used by making User generic: 您需要通过使User通用来绑定将使用的数据包类型:

class User<T extends Packet<?>> {
    PacketParser<T> mParser;

    User(PacketParser<T> parser){
        mParser = parser;
    }

    void DoSomething(){
         T packet = parser.obtainPacket();
         // do some stuff with the packet
         mParser.parse(packet);
    }
}

// and then when instantiating your User, specify the packet type:
new User<TypeOfPacket>(new ImplementedPacketParser())

Now the compiler knows that the T s it sees represent the same type of Packet<?> , whereas each time it sees ? extends Packet<?> 现在,编译器知道它看到的T表示相同类型的Packet<?> ,而每次看到? extends Packet<?> ? extends Packet<?> could be different subtypes of Packet<?> . ? extends Packet<?>可能是不同亚型Packet<?>

Edit: An additional note: the " ? extends PacketHeader " is not needed in the PacketParser interface declaration, because the Packet class already limits its T to PacketHeader and its subtypes. 编辑:附加说明: PacketParser接口声明中不需要“ ? extends PacketHeader ”,因为Packet类已经将其T限制为PacketHeader及其子类型。

// ? is implicitly constrained to "extends PacketHeader" because of
// the way Packet's generic is defined
interface PacketParser<T extends Packet<?>> {

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

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