java 我怎样才能让这个java泛型转换?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/314108/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:54:20  来源:igfitidea点击:

How can I make this java generic cast?

java

提问by ?ukasz Bownik

How can I make this java generic cast ?

我怎样才能让这个 java 通用转换?

public interface IField {

}


class Field implements IField { // package private class

}

public class Form {
  private List<Field> fields;


  public List<IField> getFields() {
    return this.fields;

  }

}

The return statement throws a compiler error (I know the reason - I read the generics tutorial) but it would be very handy to write such code.

return 语句会引发编译器错误(我知道原因 - 我阅读了泛型教程)但是编写这样的代码会非常方便。

If I declared "fields" as List I would need to use a lot of casts to Field in other methods of a Form class .

如果我将“字段”声明为 List,我将需要在 Form 类的其他方法中对 Field 进行大量强制转换。

Can I force that damn compiler to bend it's rules and compile that return statement ?

我可以强迫那个该死的编译器改变它的规则并编译返回语句吗?

Thanks in advance.

提前致谢。

回答by Jon Skeet

A better solution, IMO, is to change the signature of your method to use a bounded wildcard:

IMO 更好的解决方案是更改方法的签名以使用有界通配符:

public List<? extends IField> getFields()

This will let the caller treat anything coming "out" of the list as an IField, but it won't let the caller add anything into the list (without casting or warnings), as they don't know what the "real" type of the list is.

这将使调用者将列表中“输出”的任何内容视为 IField,但它不会让调用者将任何内容添加到列表中(没有强制转换或警告),因为他们不知道“真实”类型是什么名单是。

回答by Sunlight

As it happens, you can, because Java generics are just grafted on, not part of the type system.

碰巧,你可以,因为 Java 泛型只是嫁接,而不是类型系统的一部分。

You can do

你可以做

return (List<IField>)(Object)this.fields;

because all List<T>objects are the same underlying type.

因为所有List<T>对象都是相同的底层类型。

Bear in mind that this allows anyone to put any type implementing IFieldin your list, so if your collection is not read-only, you may run into difficulties.

请记住,这允许任何人将任何类型的实现IField放入您的列表中,因此如果您的集合不是只读的,您可能会遇到困难。

回答by David Rodríguez - dribeas

Don't do it.

不要这样做。

A List<Field>is not a List<IField>. You can try to force the compiler into accepting (I thought it was not possible, I wish it was not possible), but that will get you into trouble. The compiler will allow a user to introduce AnotherField deriving from IField into the given List breaking your invariants, and breaking into the type safety that generics provide. Later use of the List<Field>will break as extraction of the strange element will fail the implicit cast to Field where you will not expect it to happen.

AList<Field>不是List<IField>。您可以尝试强制编译器接受(我认为这是不可能的,但我希望这是不可能的),但这会给您带来麻烦。编译器将允许用户将从 IField 派生的 AnotherField 引入到给定的 List 中,从而打破你的不变量,并打破泛型提供的类型安全。稍后使用List<Field>will break 作为奇怪元素的提取将使隐式转换到 Field 失败,您不会期望它发生。

If you do need to return a List<IField>instead of List<Field>, then I will recommend generating a new list filled with the same elements. If you can modify your interface go for Jon Skeetssolution.

如果您确实需要返回 aList<IField>而不是List<Field>,那么我将建议生成一个填充相同元素的新列表。如果您可以修改您的界面,请选择Jon Skeets解决方案。

回答by Nicolas Barbier

If the caller does not need to be able to modify the list:

如果调用者不需要能够修改列表:

return Collections.<IField>unmodifiableList(this.fields);

回答by Dan Vinton

Sunlight is right, you can just cast it.

阳光是对的,你可以投射它。

Another fix is to double-check that you really need a List<Field>, or whether you can change your internal fieldsvariable to List<IField>.

另一个解决方法是仔细检查您是否真的需要List<Field>,或者您是否可以将内部fields变量更改为List<IField>

As long as you only ever use methods on the contents of the list that are on the IFieldinterface, you should be able to do a strightforward swap.

只要您只对IField接口上的列表内容使用方法,您就应该能够进行直接的交换。