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

有没有办法避免Java';s awkard对象强制转换语法?,java,syntax,casting,Java,Syntax,Casting,例如,我有一个对象“假装”为字符串: Object o = new String("dsadsa"); 如果要使用该对象的字符串函数,首先必须将其转换为如下字符串: ((String)o).indexOf("sad"); 当有这么多括号时,这真的很烦人而且不可读!特别是当它必须在IF语句或函数中出现时 if (((String)o).equals("dsadsa")) {} 避免这种情况的最佳方法是什么?将对象投射到一行中 在另一行中使用浇铸对象。解决方案是确保您的对象是以前的精确类,例如

例如,我有一个
对象
“假装”为
字符串

Object o = new String("dsadsa");
如果要使用该对象的字符串函数,首先必须将其转换为如下字符串:

((String)o).indexOf("sad");
当有这么多括号时,这真的很烦人而且不可读!特别是当它必须在IF语句或函数中出现时

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

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

将对象投射到一行中


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

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

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

使用参数化类(泛型)会越来越容易


否则说:如果代码中有很多强制转换,那么可能存在设计问题。但是我们需要更多的代码来建议解决方案。

实际上,正确使用泛型可以消除您在代码中看到的大多数强制转换

但是,如果由于某种原因您不能这样做(较旧的Java版本、遗留库),请创建一个局部变量,以便尽早执行强制转换


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

标准做法是始终将对象捕获到较窄类型的变量中,在您的示例中是
字符串str
变量,然后使用该变量

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


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

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

String str;

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

你可以利用泛型做一些危险的事情,比如

public static <T> T cast(Object o){
    return (T) o;
}
这真的很烦人,但你可以这样做

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

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

我假设您的意思是说您的
字符串
假装是
对象

您的句柄的类型为Object,它不必是Object

如果您使用对象类型,因为这是您的方法得到的参数,请考虑将参数类型更改为String,如果您实际上期望字符串。
  • 如果这是从集合中收集的,请考虑将集合更改为使用泛型,以便可以将集合定义为String。
  • 如果由于某种原因,您无法更改传入的对象的类型,请验证它实际上是一个字符串,并将其转换为另一个字符串类型的变量
  • 对于第三个选项,代码就是这样的

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

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


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

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

    您也不需要强制转换来调用
    equals()


    除此之外,您可以使用泛型,但它们的语法过于冗长,特别是当涉及到
    T selectfoobred之类的东西时(列表列表,此解决方案的比较问题,除了更难读取外,如果o不是
    String
    ,则您得到NPE而不是
    ClassCastException
    ,这对于代码维护人员来说非常混乱。如果要测试
    o instanceof String
    (注意:instanceof中的小'o's),之前单独测试
    o!=null
    是没有意义的。
    null实例无论什么
    都将是
    false
    (除此之外,我不太确定您在这里实际指的是什么。)如果你知道它是一个
    字符串,为什么你有一个
    对象
    ?顺便说一句,你不需要在这里或其他任何地方使用
    新字符串(字符串)
    。是的,我知道,
    新字符串()
    只是一个例子,可以真正说明对象是字符串,而且,我很乐意避免这种情况,但是当我使用
    向量时,例如,我想存储字符串,它们都是对象,所以我没有选择。:/t如果您使用的是Vector,除非您使用的是j2me或java 1.4,否则您可以使用Vector,甚至ArrayList(可能)会更好地为您服务您应该尝试[Lisp](,只有一个
    String
    分配给类型为
    Object
    +1的变量,用于发现示例中甚至不需要强制转换。我认为,虽然泛型确实很冗长,但它们更易于阅读和解释。@biziclop它随用例而变化——集合类型是一种胜利,尤其是在combinati中另一方面,在使用增强的for.Callbacks作为lambda函数的情况下,由于弱类型推断,这是相当失败的。至少在java 7中,它没有引用为verbose:List List List=new ArrayList()变为List List=new arrarylist()@Matt true,这很有帮助,但只有在类型推断真正起作用时才有用。我已经在很多失败的例子上撞了头。@MarkoTopolnik:我通常在处理泛型时会撞到墙上。我知道他们想要向后兼容,但这会引起很多该死的麻烦,不值得。看起来像e泛型比我以前认为的要重要得多。可惜我不能使用它,因为我实际上是用JavaME编程的,它不支持泛型。x_x我认为我应该使用第二个选项。我
    String s;
    if (o instanceof String) {
        s = (String) o;
    } else {
        s = null;
        throw new IllegalArgumentException();
        // Or take some corrective action.
    }
    
    String.class.cast(o).indexOf("sad");