有没有办法避免Java的awkard对象强制转换语法?



例如,我有一个Object"假装"为String:

Object o = new String("dsadsa");

如果我想使用该对象的String函数,首先我必须将其转换为如下字符串:

((String)o).indexOf("sad");

当有这么多括号的时候,这真的很烦人,很难阅读!尤其是当它必须出现在IF语句或函数中时!

if (((String)o).equals("dsadsa")) {}

避免这种情况的最佳方法是什么?

解决方案是确保您的对象以前是精确的类,例如在方法的原型中。

这是最佳实践,因为它也有助于避免运行时错误。

参数化类(泛型)越来越容易做到这一点。

换句话说:如果您的代码中有很多类型转换,那么可能存在设计问题。但我们需要更多的代码来提出解决方案。

将对象投射到一行中。

在另一行中使用投射的对象。

在实践中,正确使用泛型可以消除代码中的大多数类型转换。

但是,如果由于某些原因(较旧的Java版本、遗留库)无法执行此操作,请创建一个本地变量,以便尽早执行强制转换。

特殊情况是将对象从接口类型转换为其实现。这几乎总是错误的,意味着接口设计得很糟糕。

标准做法是始终将对象捕获到较窄类型的变量中,在您的情况下是String str变量,然后使用它。

请注意,在第三个示例中,您不需要向下转换:o.equals(o2)也可以。

如果你决定学习Java泛型,你可能很快就会失望:它们通常只是将冗长的内容从下转换为类型声明。当重写到泛型中时,许多代码片段都是一样长的,有些甚至更长

我假设你的意思是说你的String假装是Object

你的句柄是Object类型,它不必是。

  1. 如果您使用的是Object类型,因为这是您的方法获得的参数,如果您实际期望的是String,请考虑将参数类型更改为String
  2. 如果它来自集合,请考虑将集合更改为使用泛型,以便可以将集合定义为String类型
  3. 如果由于某些原因,您无法更改传入对象的类型,请验证它实际上是一个String,并将其强制转换为另一个String类型的变量

对于第三个选项,这就是代码的样子。

String s;
if (o instanceof String) {
    s = (String) o;
} else {
    s = null;
    throw new IllegalArgumentException();
    // Or take some corrective action.
}

您可以利用等泛型做一些危险的事情

public static <T> T cast(Object o){
    return (T) o;
}

这可以让你做之类的事情

Object o="";
String s = cast(o);

这真的很难,但你可以做一些类似的事情

public static String s(Object o){
    return (String) o;
}

然后

    Object o = "";
    s(o).indexOf("sad");

我不推荐,但可以这样做:

String.class.cast(o).indexOf("sad");

我不这么认为。你必须显式地将超类转换为子类。

String str;
if(o instanceOf String){
   str =(String)o;
   str.indexOf("sad");
   ...
}

您似乎不希望进行编译时类型检查。然后只需使用脚本语言,例如Groovy,它也在JVM上运行,但不需要静态类型。

"dsadsa".equals(someString)就是这样做的——有效地消除了NPE的任何机会,并确保即使someString实际上被声明为对象,也不会进行虚拟调用。

此外,您不需要强制转换即可调用equals()

除此之外,你可以使用泛型,但它们的语法过于冗长,尤其是当涉及到像<T extends Foo &Bar> T selectFooBared(List<java.lang.ref.Reference<T>> list, Comparator<? super T> c); 这样的东西时

最新更新