简体   繁体   English

Java:带有类型参数的泛型类型?

[英]Java : generic type with type parameters?

I have a class like this:我有一个像这样的 class :

public class MyClass <T extends Model1, X extends Model2> {

    private CommonMessage<T,X> someMethod() {
        ....
    }
}

Now I have a customized message type MyMessage extends CommonMessage , so I want to know how to have generic type that still having T and X as parameters?现在我有一个自定义的消息类型MyMessage extends CommonMessage ,所以我想知道如何拥有仍然具有 T 和 X 作为参数的泛型类型? For example:例如:

public class MyClass <M extends CommonMessage, T extends Model1, X extends Model2> {

    private M<T,X> someMethod() {
        ....
    }
}

Short answer:简短的回答:

First of all as CommonMessage is generic, extending it in a non-generic way is very bad so you should have done M extends CommonMessage<T, X> And this way because type parameter passed to CommonMessage at class declaration you should not mention this parameter type again at method return type so method return type should be M.首先,由于CommonMessage是通用的,以非通用方式扩展它是非常糟糕的,所以你应该做M extends CommonMessage<T, X>并且这种方式因为在 class 声明中传递给 CommonMessage 的类型参数你不应该提到这个参数在方法返回类型处再次键入,因此方法返回类型应为 M。

Long answer:长答案:

I know you do know this definitions but sometimes we as human forget simple things.我知道您确实知道这些定义,但有时我们作为人类会忘记简单的事情。 First we should consider what generics are created for, with generics we can create classes with different parameter types, this parameter types will be provided when they are extended by another class or when we create new instance of them with new() operator, so when we are writing our class we don't know the exact type for those parameter and we want to delay this decision until later, it is contradictory to something you are doing in your class because here your method is private and you can't change its implementation in your child class(the class which inherited from your class).首先我们应该考虑创建 generics 是为了什么,使用 generics 我们可以创建具有不同参数类型的类,当它们被另一个 class 扩展时会提供这些参数类型,或者当我们使用 new() 运算符创建它们时我们正在编写我们的 class 我们不知道这些参数的确切类型,我们希望将这个决定推迟到以后,这与您在 class 中所做的事情相矛盾,因为这里您的方法是私有的,您无法更改它在您的子类中实现(从您的类继承的 class)。 But know we can change your implementation to something like this which will be compiled well:但是要知道我们可以将您的实现更改为这样的东西,这样可以很好地编译:

public  class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
    private  M method1(){
        ...
    }
}

public class CommonMessage<T, X>{

}

public class MyMessage<T, X> extends CommonMessage<T, X>{

}
public class Model1{

}
public class Model2{

}

although this implementation will be compiled the problem is that when you are writing your private method(method1) you don't know what is the type of M at the time of writing this class because it will be passed when we want to create new instance of this class or when we inherit another class from this class.尽管此实现将被编译,但问题是当您编写私有方法(method1)时,您在编写此 class 时不知道 M 的类型是什么,因为它将在我们想要创建新实例时传递这个 class 或当我们从这个 class 继承另一个 class 时。 so what type of Object do you want to create and return in your method1?那么你想在你的方法1中创建并返回什么类型的Object? the only thing that you know here is that its type is M which extends CommonMessage but you don't know what the exact type of M is at the time of writing your private method(method1)!您在这里唯一知道的是它的类型是 M,它扩展了 CommonMessage,但是在编写私有方法(方法 1)时您不知道 M 的确切类型是什么!

And on the top of that you can't delegate this decision to your subclass(because this method is private).最重要的是,您不能将此决定委托给您的子类(因为此方法是私有的)。 Now the question is that why it is allowed and compiled well when we don't know the exact type of M?现在的问题是,当我们不知道 M 的确切类型时,为什么它被允许并编译得很好? for a moment forget this question I will make it clear after explaining correct approach.暂时忘记这个问题,我会在解释正确的方法后说清楚。 so what is the correct approach?那么正确的方法是什么? Think about it, the person who write subclass does know exactly what the type of parameter M is and they can create appropriate instance of M in implementation of method1 to return from this method.想想看,编写子类的人确实知道参数 M 的类型是什么,他们可以在方法 1 的实现中创建适当的 M 实例以从该方法返回。 so why not delegate this decision to subclass and making this method abstract?那么为什么不把这个决定委托给子类并使这个方法抽象呢? This completely make senses.这完全有道理。 in a nutshell we have some implementation like this:简而言之,我们有一些这样的实现:

public abstract  class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
    public abstract M method1();
}

public class CommonMessage<T, X>{

}

public class MyMessage<T, X> extends CommonMessage<T, X>{

}
public class Model1{

}
public class Model2{

}

now lets get back to our question why first program that I suggested to you compiled well?现在让我们回到我们的问题,为什么我建议给你的第一个程序编译得很好? why we are allowed to have private method that its return type is generic that will be passed at instanciation or inheritance time?为什么我们被允许拥有其返回类型是通用的私有方法,该方法将在实例化或 inheritance 时间传递? because there are a lot of situations that make it correct and appropriate.因为有很多情况使它正确和适当。 one situation is that our private method call another public method which return the appropriate type, like this:一种情况是我们的私有方法调用另一个返回适当类型的公共方法,如下所示:

public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
    private  M method1(){
        return method2();
    }
     abstract M method2();
}

public class CommonMessage<T, X>{

}

public class MyMessage<T, X> extends CommonMessage<T, X>{

}
public class Model1{

}
public class Model2{

}

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

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