如何在 Java 中模拟 C# as-operator

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

How to emulate C# as-operator in Java

javacasting

提问by VoidPointer

There are situations, where it is practical to have a type-cast return a null value instead of throwing a ClassCastException. C# has the asoperator to do this. Is there something equivalent available in Java so you don't have to explicitly check for the ClassCastException?

在某些情况下,让类型转换返回空值而不是抛出 ClassCastException 是可行的。C# 有as操作符可以做到这一点。Java 中是否有等效的东西,因此您不必显式检查 ClassCastException?

采纳答案by Aaron Maenpaa

Here's an implementation of as, as suggested by @Omar Kooheji:

这是 @Omar Kooheji 建议的 as 实现:

public static <T> T as(Class<T> clazz, Object o){
    if(clazz.isInstance(o)){
        return clazz.cast(o);
    }
    return null;
}

as(A.class, new Object()) --> null
as(B.class, new B())  --> B

回答by Chris Marasti-Georg

You can use the instanceofkeyword in place of C#'s is, but there is nothing like as.

您可以使用instanceof关键字代替 C# 的is,但没有像as.

Example:

例子:

if(myThing instanceof Foo) {
   Foo myFoo = (Foo)myThing; //Never throws ClassCastException
   ...
}

回答by toolkit

I'd think you'd have to roll your own:

我认为你必须自己动手:

return (x instanceof Foo) ? (Foo) x : null;

EDIT: If you don't want your client code to deal with nulls, then you can introduce a Null Object

编辑:如果您不希望您的客户端代码处理空值,那么您可以引入一个空对象

interface Foo {
    public void doBar();
}
class NullFoo implements Foo {
    public void doBar() {} // do nothing
}
class FooUtils {
    public static Foo asFoo(Object o) {
        return (o instanceof Foo) ? (Foo) o : new NullFoo();
    }
}
class Client {
    public void process() {
        Object o = ...;
        Foo foo = FooUtils.asFoo(o);
        foo.doBar(); // don't need to check for null in client
    }
}

回答by Omar Kooheji

I'm speculating you could propably creas an as operator

我推测你可以创建一个 as 操作符

something like

就像是

as<T,Type> (left, right)  
which evaluates to 
if (typeof(left) == right)
   return (right)left
else
    return null

I'm not sure how you'd do it, I'm a c# at the moment and my Java hat has gotten a bit dusty since I left university.

我不确定你会怎么做,我现在是 ac#,自从我离开大学以来,我的 Java 帽子已经变得有点尘土飞扬。

回答by Mike Deck

You could write a static utility method like this. I don't think it's terribly readable, but it's the best approximation of what you're trying to do. And if you use static imports it wouldn't be too bad in terms of readability.

您可以编写这样的静态实用程序方法。我认为它的可读性不是很强,但它是您尝试做的最好的近似。如果您使用静态导入,那么在可读性方面也不会太差。

package com.stackoverflow.examples;
public class Utils {
    @SuppressWarnings("unchecked")
    public static <T> T safeCast(Object obj, Class<T> type) {
        if (type.isInstance(obj)) {
            return (T) obj;
        }
        return null;
    }
}

Here's a test case that demonstrates how it works (and that it does work.)

这是一个测试用例,演示了它是如何工作的(并且确实有效。)

package com.stackoverflow.examples;
import static com.stackoverflow.examples.Utils.safeCast;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;

import org.junit.Test;

public class UtilsTest {

    @Test
    public void happyPath() {
        Object x = "abc";
        String y = safeCast(x, String.class);
        assertNotNull(y);
    }

    @Test
    public void castToSubclassShouldFail() {
        Object x = new Object();
        String y = safeCast(x, String.class);
        assertNull(y);
    }

    @Test
    public void castToUnrelatedTypeShouldFail() {
        Object x = "abc";
        Integer y = safeCast(x, Integer.class);
        assertNull(y);
    }
}

回答by Dmitry Klochkov

In java 8 you can also use stream syntax with Optional:

在 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"));