代码之家  ›  专栏  ›  技术社区  ›  Michael Mao

在对JSP隐式对象的属性进行强制转换时,我应该添加try/catch-around吗?

  •  1
  • Michael Mao  · 技术社区  · 14 年前

    基本上我的意思是:

    List<String[]> routes = (List<String[]>)application.getAttribute("routes");
    

    对于上述代码,它尝试从JSP隐式对象应用程序中获取名为“routes”的属性。但是众所周知,在这行代码之后,routes很可能包含一个空值——这意味着这个应用程序没有名为“routes”的属性。

    在Java中这个“空的铸造”好的编程实践吗?

    基本上,我尽量避免异常,如java.io.InvalidcastException

    我认为,当泛型类型没有被引入到这种语言中时,这种情况更像Java 1.4的“遗产”。所以我猜所有存储在应用程序属性中的东西都是对象(类似于传统的arraylist)。当你做“向下投射”时,可能会有无效的投射。

    在这种情况下你会怎么做?

    更新:

    刚发现,虽然在隐式对象应用程序中,我确实存储了一个字符串数组列表,但当我执行此操作时:

    List<double[]> routes = (List<double[]>)application.getAttribute("routes");
    

    它不会产生任何错误…我已经不舒服了…

    即使有了这个代码:

    out.print(routes.get(0));
    

    它确实打印出了一些奇怪的东西:

    [Ljava.lang.String;@18b352f
    

    我正在打印“指向字符串的指针”吗?我终于可以得到这样一个例外:

    out.print(routes.get(0)[1]);
    

    错误:

    java.lang.ClassCastException: [Ljava.lang.String;
    

    因为是我添加了application属性,所以我知道应该将其强制转换为哪种类型。我觉得这“不够好”,如果我忘记了确切的类型呢? 我知道仍然有一些情况会发生这种情况,比如在JSP/servlet中,当您对会话属性进行强制转换时。有更好的方法吗?

    在你说:“天哪,为什么不使用servlets???”,我应该证明我的理由:因为我的uni很糟糕,它的服务器只能使用jsp生成的servlet,我不想学习如何解决这样的问题。 look at my previous question on this 这是统一作业,所以我别无选择,把战争、WEB-INF等都忘了,但是“把所有东西直接编码到JSP中”——因为教授们也这么做了。:)

    2 回复  |  直到 14 年前
        1
  •  2
  •   Brian Agnew    14 年前

    爪哇使用 类型消除 存储集合。也就是说,编译器强制类型安全,但将集合减少到 Objects . 所以当您从bean中拉出一个列表对象时,它是 List<Object> 而不是 List<Double> .

    因为它是一个集合,你可以 第n次 元素(如您所做的)。然而,你得到的对象并不是你所期望的。因此,当您从集合中拉出一个元素并将其强制转换为 Double 而不是 String ,运行时将最终对象。

    [Ljava.lang.String;@18b352f 是对字符串数组的引用,btw。(“[”表示数组)。

    出于这个原因(以及其他原因),我不喜欢存储类型集合的集合。我希望创建一个特定的对象类型(容器),然后向该对象请求我需要的元素。因此,从bean中提取对象时只需要强制转换一次,然后在该对象中管理列表中处理双精度数组的复杂性(您可以要求容器对象为您查找元素,提取/转换的逻辑位于一个位置等)。

        2
  •  2
  •   Alexander Pogrebnyak    14 年前

    创建一个类(应用程序),将它存储在ServLeLoad上下文中一次,然后用普通的Java风格调用该类上的方法。

    在该应用程序类中添加一个方法。

    // Make sure that ATTRIBUTE_NAME is somewhat unique.
    private final static String ATTRIBUTE_NAME =
        Application.getClass( ).getName( );
    
    List< String > myList;
    
    public saveToAppContext ( ServletContext context )
    {
        context.setAttribute( ATTRIBUTE_NAME, this );
    }
    
    public static Application getAttribute ( ServletContext context )
    {
        return (Application) context.getAttribute( ATTRIBUTE_NAME );
    }
    
    // Because you store object in application scope, ensure that
    // access methods are thread-safe
    //
    // This is just an example, you may need something with better
    // performance
    synchronized List< String > getStringList ( )
    {
        return new ArrayList<String>(myList);
    }
    

    现在设置 ServletContextListener 在加载/卸载servletContext时初始化并销毁应用程序对象

    这个 contextInitialized 方法应该创建应用程序对象,并将其保存为servletContext上的属性。