【问题标题】:Is there a form of "type safe" casting in Java?Java中是否有一种“类型安全”的强制转换形式?
【发布时间】:2011-12-27 22:32:47
【问题描述】:

假设我有两个派生自第三个抽象类的类:

public abstract class Parent{
    public Parent(){
    }
}

public class ChildA extends Parent {
    public ChildA {
    }
}

public class ChildB extends Parent {
    public ChildB {
    }
}

在 C# 中,我可以通过以下方式以某种类型安全的方式处理转换:

ChildA child = obj as ChildA;

如果它不是 ChildA 类型的对象,这会使 child == null 。如果我这样做:

ChildA child = (ChildA)obj;

...在 C# 中,如果类型不正确,这将引发异常。

所以基本上,有没有办法在 Java 中进行第一种类型的转换?谢谢。

【问题讨论】:

标签: java casting


【解决方案1】:

在 java 8 中,您还可以使用带有 Optional 的流语法:

    Object o = new Integer(1);

    Optional.ofNullable(o)
            .filter(Number.class::isInstance)
            .map(Number.class::cast)
            .ifPresent(n -> System.out.print("o is a number"));

【讨论】:

  • Number.class::cast 太棒了!这个太棒了!
【解决方案2】:

我想不出语言本身的方法,但你可以像这样轻松地模仿它:

ChildA child = (obj instanceof ChildA ? (ChildA)obj : null);

【讨论】:

  • obj instanceof List 怎么样? (List)obj:空?您不能将实例用于泛型类型,因为它会在运行时消失。
  • @vajanko 你是对的,如果你还需要检查项目的类型,你不能用泛型类型来做到这一点。您仍然可以使用List ? (List)obj : null - 但您会收到编译时警告。这个问题没有提到泛型。
【解决方案3】:

你可以使用这个兼容所有java类型的方法:

public static <T> T safeCast(Object o, Class<T> clazz) {
    return clazz != null && clazz.isInstance(o) ? clazz.cast(o) : null;
}

例子:

// A given object obj
Integer i = safeCast(obj, Integer.class);

【讨论】:

    【解决方案4】:

    我认为处理这个问题的最好方法是使用泛型方法,这是一个可重用/安全的选项,如下例所示:

    @SuppressWarnings("unchecked")
    public <E> E coerceTo(Object o, Class<E> target) throws IllegalArgumentException {
      if(target.isInstance(o)) return (E)o;
      String msg = "expected "+target.getName()+" but was "+o.getClass().getName();
      throw new IllegalArgumentException(msg);
    }
    

    请注意,这里的强制转换仅在安全时发生,添加 suppressWarnings 注释是正确的。

    这里是一个如何调用方法的例子:

     Object o = 1;
     int a = coerceTo(o, Integer.class);
    

    【讨论】:

      【解决方案5】:

      您可以使用instanceof 运算符。

      if(obj instanceof ChildA){
           final ChildA child = (ChildA) obj;
      }
      

      【讨论】:

        【解决方案6】:

        你总是可以先检查:

        if (child instanceof ChildA) {
            ChildA child = (ChildA) child;
            // Do stuff.
        }
        

        或者只是做一个快速的方法:

        public ChildA getInstance(Parent p) {
            if (child instanceof ChildA) {
                return (ChildA) p;
            } else {
                return null;
            }
        }
        

        【讨论】:

          【解决方案7】:

          在现代 Java 中你会使用

          if (obj instanceof ChildA childa) {
          
          }
          

          这在现代 C# 中几乎相同

          if (animal is Dog dog)
          {
              // Use dog here
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-20
            • 2021-08-11
            • 1970-01-01
            • 1970-01-01
            • 2015-12-19
            • 1970-01-01
            相关资源
            最近更新 更多