2012-08-22 122 views
3

比如我有一个Object“假装”是String有没有办法避免Java的awkard对象转换语法?

Object o = new String("dsadsa"); 

如果我想使用该对象的字符串函数,首先我必须将它转化成一个像这样的字符串:

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

当有这么多的括号时,这会变得非常烦人和难以理解!特别是当它必须进入IF语句或函数时!

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

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

+4

为什么你有一个'Object'如果你知道它的一个'String'?顺便说一句,你不需要在这里或其他地方使用'new String(String)'。 –

+0

是的,我知道,'新的String()'只是一个例子,真正表明该对象是一个字符串,而且,我很乐意避免这个,但是当我使用'Vector'例如,我想存储字符串,他们都是对象,所以我没有选择。 :/ – SmRndGuy

+0

如果您使用Vector来存储_store_字符串,则不需要转换。一个字符串是一个对象,所以它会工作。但是如果你使用的是矢量,除非你使用j2me或者java 1.4,你可以使用矢量,或者甚至ArrayList 将(可能)更好地为你服务 –

回答

8

将该对象投射到一行中。

在另一行中使用铸造对象。

9

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

这是最好的做法,因为它也有助于避免运行时错误。

参数化类(泛型)越来越容易。

否则表示:如果您的代码中有很多强制转换,则可能存在设计问题。但是我们需要更多代码来提出解决方案。

7

在实践中,正确使用泛型会摆脱您在代码中看到的大多数表演。

但是,如果由于某种原因,你不能这样做(较旧的Java版本,旧版库),创造一个你尽早投一个局部变量。

一个特殊情况是当您将一个对象从接口类型转换为其实现时。这几乎总是错误的,并且意味着界面设计得不好。

+0

似乎泛型比我以前认为的重要得多。太糟糕了我无法使用它,因为我实际上是在不支持泛型的JavaME中进行编程。 x_x 我相信我应该使用第二个选项。 – SmRndGuy

+0

我假设你真的摆脱了括号后。如果你想完全摆脱这些演员阵容,仿制药就是你所追求的(如果他们对你有用)。 – Hbcdev

5

的标准做法是始终捕捉对象插入到窄类型的变量,在你的情况下,String str变量,并使用它之后。

请注意,在你的第三个例子中,你不需要downcast:o.equals(o2)也可以。

如果您决定学习Java泛型,您可能会很快失望:他们通常会将冗长度从向下转换为类型声明。当重写到泛型时,许多代码片段都很长,并且有些代码段甚至更长。

+1

+1表示在示例中甚至不需要铸造。我认为尽管泛型确实是冗长的,但它们更易于阅读和解释。 – biziclop

+0

@biziclop它随使用情况而变化 - 集合类型是一种胜利,尤其是与增强型相结合。另一方面,用作lambda函数的回调是相当失败的,因为类型推断很弱。 –

+0

至少在java 7中,它不是详细描述:列表 list = new ArrayList ()成为列表 list = new ArrayList <>(); – Matt

1

我不这么认为。您必须明确地将超类转换为子类。

String str; 

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

这个解决方案的麻烦,除了更难阅读的是,如果o不是'String',你会得到一个NPE而不是'ClassCastException',这对代码维护者来说是非常混乱的。 – biziclop

+0

如果您要测试'instanceof String'(注意:instanceof中的'o'小),那么之前单独测试'o!= null'没有意义。无论按照预期情况,“无论什么”都是“假”。 (除此之外,我不太清楚你在这里实际处理的是什么。) –

+0

@ arne.b - 谢谢纠正 –

1

你可以做一些危险的事情,趁着泛型像

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

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

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

  1. 如果您使用的是Object类型,因为这是你的方法获取参数,考虑更改参数类型为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. 
} 
1

我不建议这样做,但你可以此:

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

看来你不想编译时类型检查。 然后,只需使用脚本语言,例如Groovy也运行在JVM上,但不需要静态类型。

0

"dsadsa".equals(someString)是如何完成的 - 即使someString实际上被声明为对象,它也会有效地消除NPE的机会并确保不会发生虚拟呼叫。

另外你不需要剧组就可以致电equals()

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

相关问题