本文介绍了Java泛型 - 使Generic可扩展2个接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 您如何使此工作: public class Frankenstein< T extends IHuman,IMonster> {} 无需 public interface Weirdo extends Ihuman,IMonster {} public< T> void mapThis( Class< ;? extends MyClass< T>> key,Class< ;? extends T& IDisposable> value){ } 我收到编译器消息标记 Class<?延伸T& IDisposable> 为错误。解决方案 Reimeus已经指出您要求您的编辑是不可能的。 你会认为你可以使用下面的方法: public< T,U extends T& IDisposable> void mapThis( Class< ;? extends MyClass< T>> key, Class< ;? extends U> value ){...} 事实上,这是我第一次看到这篇文章时的想法。但这实际上给出了编译器错误:此限制在一个紧密相关的帖子中进行了探讨:为什么我无法在带有多个边界的类型参数中使用类型参数? 总而言之,限制是为了排除某些尴尬的情况( JLS§4.9)。 什么样的尴尬情况? Chris Povirk的回答描述了一个: Chris还指向 Sun bug 4899305 ,这是一个针对此语言限制的错误。它被关闭作为未修复与以下注释:所以这些是限制背后的原因。具体解决通用方法(你的问题关注),我想进一步指出,类型推论在理论上会导致这样的边界无论如何是无意义的。 如果我们重新检查上述假设签名中声明的类型参数: < T,U extends T& IDisposable> 假设调用者没有明确指定 T 和 U ,可以缩减为以下内容: ; T,U extends Object& IDisposable> 或者这只是微妙的区别,但是另一主题): < T,U extends IDisposable> 这是因为 T 任何边界,因此无论传递什么类型的参数, T 始终可以解析为 Object ,然后可以 U 。 让我们回去说 T 有界: < T extends Foo,U extends T& IDisposable> 这可以以同样的方式减少( Foo 可以是类或接口): < T extends Foo,U extends Foo& IDisposable> 至少基于理论上的推理,你尝试的语法实现是无意义的,直到限制调用者更具体的论点。我几乎可以在这里停止。 但是... 是您尝试执行的用例。 它与编译器推断通用方法类型参数的方式有关,这导致我的理论推理走出窗口。采取以下通用方法: class MyClass { static< T& void foo(T t1,T t2){} } 这是一个常见的初学者尝试创建一个需要两个参数相同类型的方法的错误。当然,由于继承的工作原理,这是无意义的: MyClass.foo(asdf,42) // legal 这里, T Object - 这与之前关于简化 mapThis 类型参数的推理相符。您必须手动指定类型参数才能实现预期的类型检查: MyClass。< String> foo asdf,42); //编译器错误 但进来,这是一个不同的事情与多个类型参数与交错边界: class MyClass { static< T ,U延伸T> void foo(T t,U u){} } MyClass.foo(asdf,42) //编译器错误 表已经改变了 - 我们必须手动放宽类型参数编译: MyClass。< Object,Object> foo(asdf,42); // legal 这是因为编译器推断出方法类型参数的有限方式。因此,你想要实现的是实际上有一个应用程序限制调用者的参数。 How do you make this work:public class Frankenstein<T extends IHuman, IMonster>{}Without making public interface Weirdo extends Ihuman, IMonster{}EditWhy is this not working?public <T> void mapThis( Class<? extends MyClass<T>> key, Class<? extends T & IDisposable> value) {}I am getting compiler message marking Class<? extends T & IDisposable> as an Error. 解决方案 Reimeus already pointed out that what you're asking for in your edit isn't possible. I'd just like to expand a little on why.One would think you could use the following:public <T, U extends T & IDisposable> void mapThis( Class<? extends MyClass<T>> key, Class<? extends U> value) { ... }In fact that's what came to my mind when I first saw this post. But this actually gives a compiler error:To help me explain why, I'd like to quote an Oracle Blogs post by Victor Rudometov about this error:The reasons for this restriction are explored in a closely related post: Why can't I use a type argument in a type parameter with multiple bounds?To summarize, the restriction was imposed in order to "preclude certain awkward situations coming into existence" (JLS §4.9).What kind of awkward situations? An answer by Chris Povirk describes one:Chris also points to Sun bug 4899305, which was a bug contesting this language restriction. It was closed as Won't Fix with the following comment:So those are the reasons behind the restriction. Addressing generic methods specifically (which your question concerns), I'd like to further point out that type inference would theoretically cause such bounds to be pointless anyway.If we reexamine the type parameters declared in the hypothetical signature above:<T, U extends T & IDisposable>Assuming the caller isn't explicitly specifying T and U, this can be reduced to the following:<T, U extends Object & IDisposable>Or just this (subtle difference, but that's another topic):<T, U extends IDisposable>This is because T doesn't have any bounds, so no matter what type of arguments get passed in, T can always resolve to Object at the very least, and so then can U.Let's go back and say T is bounded:<T extends Foo, U extends T & IDisposable>This can be reduced in the same way (Foo could be a class or interface):<T extends Foo, U extends Foo & IDisposable>Based on that theoretical reasoning at least, the syntax you're trying to achieve is pointless as far as restricting the caller to more specific arguments. I could almost stop here. But... there is a use case for what you're trying to do. It has to do with the way the compiler infers generic method type parameters, which causes my theoretical reasoning to go out the window. Take the following generic method:class MyClass { static <T> void foo(T t1, T t2) { }}This is a common beginner's mistake of trying to make a method that takes two parameters of the "same type". Of course it's pointless because of the way inheritance works:MyClass.foo("asdf", 42); //legalHere, T is inferred to be Object - this matches up with earlier reasoning about simplifying the mapThis type parameters. You have to manually specify the type parameters in order to achieve the intended type checking:MyClass.<String>foo("asdf", 42); //compiler errorHowever, and here's where your use case starts to come in, it's a different matter with multiple type parameters with staggered bounds:class MyClass { static <T, U extends T> void foo(T t, U u) { }}Now this call errors:MyClass.foo("asdf", 42); //compiler errorThe tables have turned - we have to manually relax the type parameters to get it to compile:MyClass.<Object, Object>foo("asdf", 42); //legalThis happens because of the limited way in which the compiler infers method type parameters. For this reason, what you wanted to achieve would've actually had an application in restricting the caller's arguments. 这篇关于Java泛型 - 使Generic可扩展2个接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-04 04:50
查看更多