Java 泛型和可变参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3096708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java generics and varargs
提问by Chris
I'd like to implement a function with both generics and varargs.
我想用泛型和可变参数实现一个函数。
public class Question {
public static <A> void doNastyThingsToClasses(Class<A> parent, Class<? extends A>... classes) {
/*** something here ***/
}
public static class NotQuestion {
}
public static class SomeQuestion extends Question {
}
public static void main(String[] args) {
doNastyThingsToClasses(Object.class, Question.class, SomeQuestion.class); // OK
doNastyThingsToClasses(Question.class, SomeQuestion.class); // OK
doNastyThingsToClasses(Question.class, Object.class, SomeQuestion.class); // compilation failure
}
}
The intention here is to assert that all parameters passed to this function are Class objects extending the Class given as the first parameter. So the two first lines of main method would compile and the 3rd one generates an error.
这里的目的是断言传递给这个函数的所有参数都是扩展作为第一个参数给出的类的类对象。所以 main 方法的前两行会编译,第三行会产生错误。
My question is:Why I get "Type safety : A generic array of Class is created for a varargs parameter" message for the first two lines?
我的问题是:为什么我在前两行收到“类型安全:为可变参数参数创建了类的通用数组”消息?
Am I missing something here?
我在这里错过了什么吗?
Additional question:how to redesign it to prevent this warning from being shown on every line calling "doNastyThingsToClasses" function? I can change it to "doNastyThingsToClasses(Class<A> parent, Class<?>... classes)" and get rid of the warnings but this also removes the compilation-time type checking --- not so good if I wanted to assure the right use of this function. Any better solution?
附加问题:如何重新设计它以防止在调用“doNastyThingsToClasses”函数的每一行上显示此警告?我可以将其更改为“doNastyThingsToClasses(Class<A> parent, Class<?>... classes)”并摆脱警告,但这也删除了编译时类型检查——如果我想的话,这不是那么好确保正确使用此功能。有什么更好的解决办法吗?
采纳答案by Jon Skeet
As almost always, Angelika Langer's Java generics FAQ explains it in great detail. (Scroll to "Why does the compiler sometimes issue an unchecked warning when I invoke a "varargs" method?" - the ID doesn't work well.)
与往常一样,Angelika Langer 的 Java 泛型常见问题解答非常详细。(滚动到“为什么当我调用“varargs”方法时编译器有时会发出未经检查的警告?”- ID 不能正常工作。)
Basically, you end up losing information in a worse way than normal. Yet another little pain point in Java generics :(
基本上,您最终会以比正常情况更糟的方式丢失信息。Java泛型的另一个小痛点:(
回答by Brett
The second argument Class<? extends A>
... that must extend the class that the first argument is (ex. argument one is a Question
so the second argument be something that extends Question
.
第二个参数Class<? extends A>
......必须扩展第一个参数所在的类(例如,参数一个是 aQuestion
所以第二个参数是扩展的东西Question
。
The Breakdown: NastyThingsToClasses(Object.class, Question.class, SomeQuestion.class); // OK
Everything extends Object
so the second argument is correct.
细分:NastyThingsToClasses(Object.class, Question.class, SomeQuestion.class); // OK
一切都扩展了,Object
所以第二个论点是正确的。
NastyThingsToClasses(Question.class, SomeQuestion.class); // OK
SomeQuestion
extends Question
so thats fair game.
NastyThingsToClasses(Question.class, SomeQuestion.class); // OK
SomeQuestion
扩展Question
所以那是公平的游戏。
NastyThingsToClasses(Question.class, Object.class, SomeQuestion.class);
Object
does not extend Question
hence error.
NastyThingsToClasses(Question.class, Object.class, SomeQuestion.class);
Object
不扩展Question
因此错误。
hopefully that cleared things up.
希望能解决问题。
-Brett
-布雷特
回答by Cowan
Jon Skeet's answer is (of course) correct; I'll expand on it a little by pointing out that you CAN get rid of this warning, with a big 'if'. You can avoid this warning IF you're willing to commit to having your project build using Java 7.
Jon Skeet 的回答(当然)是正确的;我会稍微扩展一下,指出你可以用一个大的“如果”来摆脱这个警告。如果您愿意承诺使用 Java 7 构建项目,则可以避免此警告。
Bob Lee wrote a proposalto let this warning be suppressed at method-declaration site, rather than usage site, as part of Project Coin.
作为Project Coin 的一部分,Bob Lee 写了一份提案,让这个警告在方法声明站点而不是使用站点上被抑制。
This proposal was accepted for JDK7 (though the syntax changed slightly, to @SuppressWarnings("varargs")
); you can, if you're curious, look at the commit that added this support to the JDK.
这个提议被 JDK7 接受(尽管语法略有变化,改为@SuppressWarnings("varargs")
);如果您好奇,您可以查看将这种支持添加到 JDK 的提交。
Not necessarily helpful for you, but I thought I'd make this a separate answer so it lives on for future readers, who may be lucky enough to live in a post-Java-7 world.
不一定对您有帮助,但我想我会将它作为一个单独的答案,以便未来的读者继续阅读,他们可能有幸生活在后 Java-7 世界中。
回答by Chris
OK, so finally I end up throwing the varargs away:
好的,所以最后我最终扔掉了可变参数:
public class Question {
public static <A, C extends A> void doNastyThingsToClasses(Class<A> parent, List<Class<? extends A>> classes) {
/******/
for(Class<? extends A> clazz : classes) {
System.out.println(clazz);
}
}
public static class NotQuestion {
}
public static class SomeQuestion extends Question {
}
public static void main(String[] args) {
ArrayList<Class<? extends Object>> classes = new ArrayList<Class<? extends Object>>();
classes.add(Question.class);
classes.add(SomeQuestion.class);
classes.add(NotQuestion.class);
doNastyThingsToClasses(Object.class, classes);
ArrayList<Class<? extends Question>> clazzes = new ArrayList<Class<? extends Question>>();
clazzes.add(Question.class);
clazzes.add(SomeQuestion.class);
clazzes.add(NotQuestion.class); // yes, this will _not_ compile
doNastyThingsToClasses(Question.class, clazzes);
}
}
The only flaw is the long code for populating the collection used to carry function's arguments.
唯一的缺陷是用于填充用于携带函数参数的集合的长代码。
回答by Scott
As an aside, the warning can now be suppressed using Java 7's new @SafeVarargs annotation.
顺便说一句,现在可以使用 Java 7 的新 @SafeVarargs 注释来抑制警告。
@SafeVarargs
public static <A> void func( Class<A> parent, Class<? extends A>... classes ) {
// Do func...
}
回答by LuisKarlos
My solution to this problem was to
我对这个问题的解决方案是
- create a class Nastier
- remove ... from doNastyThingsToClasses
- make doNastyThingsToClasses none static method
- make the name short, like do
- return this
move repetitive args to class properties
class Nastier { private final Class<A> parent; public Nastier(Class<A> parent) { this.parent = parent; } public <A, C extends A> Nastier do(Class<? extends A> clazz) { System.out.println(clazz); return this; } } public static void main(String[] args) { Nastier nastier = new Nastier(Object.class); nastier.do(Question.class).do(SomeQuestion.class).do(NotQuestion.class); }
- 创建一个类 Nastier
- 从 doNastyThingsToClasses 中删除 ...
- make doNastyThingsToClasses 非静态方法
- 使名字简短,就像做
- 返回这个
将重复的 args 移动到类属性
class Nastier { private final Class<A> parent; public Nastier(Class<A> parent) { this.parent = parent; } public <A, C extends A> Nastier do(Class<? extends A> clazz) { System.out.println(clazz); return this; } } public static void main(String[] args) { Nastier nastier = new Nastier(Object.class); nastier.do(Question.class).do(SomeQuestion.class).do(NotQuestion.class); }
I believe the code looks clean and I am happy.... :)
我相信代码看起来很干净,我很高兴....:)