简体   繁体   English

Java泛型和方法签名

[英]Java Generics and Method signature

Im trying to create overloading methods in java: 我正在尝试在Java中创建重载方法:

private BasesResponse getResponse(List<ClassA> classA) {
...
}

private BasesResponse getResponse(List<ClassB> classB) {
    ...
}

But eclipse is complaining about: Method getResponse(List<ClassA>) has the same erasure getResponse(List<E>) as another method in type BasisInformationEndpoint. 但是eclipse抱怨:方法getResponse(List<ClassA>)与类型BasisInformationEndpoint中的另一个方法具有相同的擦除getResponse(List<E>)

I thought method signature is method name + parmeter list.... but how can List<ClassA> be the same as List<ClassB> ? 我认为方法签名是方法名称+参数列表...。但是List<ClassA>如何与List<ClassB>相同? Doesnt make sense to me. 对我没有意义。

Java generic type erasure will make it Java 泛型类型擦除将使它成为现实

private BasesResponse getResponse(List classA) {
...
}

private BasesResponse getResponse(List classB) {
    ...
}

After type erasure it is the same for compiler. 类型擦除后,对于编译器是相同的。

The generic types ( <...> ) are present only before compilation stage, to be used for static typing. 泛型类型( <...> )仅在编译阶段之前存在,用于静态类型化。

Once compiled, those types are "erased" and List<ClassA> essentially becomes List . 编译后,这些类型将被“擦除”,并且List<ClassA>本质上成为List Thus you can see that when this happens, your two functions become identical. 因此,您可以看到,当发生这种情况时,您的两个功能将变得相同。

This is called type erasure, as has been mentioned by the commenter. 正如评论者所提到的,这称为类型擦除。

This is not possible. 这是不可能的。 For backwards compatibility, generic parameters are discarded at runtime (unlike in, for instance, C#). 为了向后兼容,一般参数在运行时会被丢弃(与C#不同)。 This is called type erasure. 这称为类型擦除。

Therefore a List<Whatever> , at runtime, is just a List . 因此, List<Whatever>在运行时只是List Which means both of your methods have a prototype of BasesResponse getResponse(List) , which is a compile error. 这意味着您的两个方法都具有BasesResponse getResponse(List)的原型,这是一个编译错误。

The Java compiler also erases type parameters in generic method arguments. Java编译器还会擦除通用方法参数中的类型参数

You might see the two parameters as different type, but when the <> is removed the JVM will see two methods as the type of their parameters. 您可能会看到这两个参数是不同的类型,但是当除去<>时,JVM将把两个方法视为它们的参数类型。

So overloading fails. 因此重载失败。

Generic type erasure: 通用类型擦除:

The reason for this is actually due to Generics, List<ClassA> and List<ClassB> Before java 1.5 there weren't any Generics, List were declared as is. 这样做的原因实际上是由于泛型, List<ClassA>List<ClassB>在Java 1.5之前,没有任何泛型,所以List被声明为是。 just as List . 就像List Which means that you can put anything in specified list, before it would be legal to add Object , String , ClassA , Listener , etc to one List only. 这意味着您可以将任何内容放入指定的列表中,然后才可以将ObjectStringClassAListener等仅添加到一个列表中。 Generics were introduced for specifying the collections which type they would be getting. 引入了泛型来指定集合将要获得的类型。 This is where: List<ClassA> , List<String> , etc comes in to play. 在这里: List<ClassA>List<String>等开始播放。

However in order preserve the legacy systems of those who created their system pre-generics time this would be an issue, Generics are only imposed compile time, but in runtime it will still be the same underlying List before. 但是,为了保留创建系统前泛型时间的那些人的遗留系统,这将是一个问题,泛型仅被强加编译时间,但在运行时,它仍将是以前的基础List。

So to answer your question, to Eclipse this is both the same method signature receiving one parameter: 因此,要回答您的问题,对于Eclipse,这是接收一个参数的两个方法签名:

private BasesResponse getResponse(List classX) { ... }

This is because after going through type erasure both methods will come out to be like this: 这是因为经过类型擦除后,这两种方法都会像这样:

private BasesResponse getResponse(List classA) {
...
}

private BasesResponse getResponse(List classB) {
    ...
}

Two same methods with same signature. 具有相同签名的两种相同方法。 Which ofcourse is not overloading , but a compile time error. 当然,这不是重载,而是编译时错误。

Because for java the List<ClassA> and the List<ClassB> type parameter is the same as the List<E> . 因为对于JavaList<ClassA>List<ClassB>类型参数与List<E>

You can resolve this problem only using different method names or, if ClassA and ClassB have the same parent, use getResponse(List<? extends ClassABParent> param) . 您只能使用不同的方法名称来解决此问题,或者,如果ClassAClassB具有相同的父代,请使用getResponse(List<? extends ClassABParent> param)

这是因为编译器仍支持旧版代码,这就是为什么它考虑删除通用类型的原因。您可以在此处找到相同的问题

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

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