0

我有一个方法,我从中返回对象

public static Object login(DataManager dataManager, String userName, String password)       
    ArrayList<LoginCredentialsBean> loginCredentialsList = new ArrayList<LoginCredentialsBean>();       
    String authenticated = "false";     
    Connection connection = null;       
    try {           
        connection  = dataManager.getConnection();          
    } catch (Exception e) {         
         return ("Having problem in connectiong to databaste: " + e.getMessage());          
    }       
    if (connection != null) {           
         try {                                       
             ...                     
             try {                   
                 ResultSet rs = prepStatement.executeQuery();                   

                 try {                      
                     while (rs.next()) {
                         ...                             
                         loginCredentialsList.add(new LoginCredentialsBean(roleId, orgaCode, passwordExpiryDate, date, status, language));                                                          
                        authenticated = "true";                          
                     } //end of while()                                                  
                 } finally {                     
                     rs.close();                     
                 }                   
             } finally {
                 prepStatement.close();                  
             }                
             if (authenticated.equals("true")) {                     
                updateUserLogByInserting(connection, userName);                  
             }

         } catch(SQLException e) {               
             System.out.println("Could not login from dataabse:" + e.getMessage());              
         } finally {                 
             dataManager.putConnection(connection);                          
         }                  
    }       
    if (authenticated.equals("true")) {                 
        return loginCredentialsList;            
    } else {        
        return authenticated;           
    }       
} //end of login()

现在我正在测试它

public static void main(String... args) {

    MoneyTreeServices moneyTreeServices = new MoneyTreeServices();

    Object result = moneyTreeServices.login("Admin", "cbas1234");       
    if (result instanceof ArrayList<?>) {

        System.out.println("ArrayList instance");           
    }       
    System.out.println(result);
}

它返回我的结果就像

ArrayList instance
[pk.mazars.moneyTree.bean.LoginCredentialsBean@b7ec5d]

我想问我正在使用类似的条件ArrayList<?>。我如何检查包含 LoginCredentialsBean 对象的 ArrayList。就像我使用时一样

if (result instanceof ArrayList<LoginCredentialsBean>) {

}

我得到错误

Can not perform instanceof check against parameterized type ArrayList<LoginCredentialsBean>. Use the form ArrayList<?>

我想检查 instanceof ArrayList 和 arraylist 有 LoginCredentialsBean 吗?

谢谢你。

4

6 回答 6

1

参数化类型信息在编译时被删除,并instanceof在(大张旗鼓)运行时被解析——这就是你得到那个错误的原因。

你可以做的是迭代Listinstanceof它们中的元素。

干杯,

于 2012-10-23T08:27:03.990 回答
1

简短的回答是你不能。泛型是通过类型擦除实现的——它们实际上是编译时语法糖,以确保您不会IntegerList<String>.

然而,运行时对象本身只是原始类型。的实例ArrayList知道它是一个ArrayList<String>(或者更确切地说,它被分配给具有该泛型类型的变量)。因此,当您通过反射询问它时,您无法获得任何泛型类型信息。

我能想到两种广泛的解决方案。一种是遍历列表内容并检查它们的动态类型——例如,如果第一个元素是 a LoginCredentialsBean,那么假设你有 a 是合理的List<LoginCredentialsBean>。但是,这不适用于空列表,这可能是一个问题,并且可能会产生误报(例如,aList<Object> allParameters可能恰好将 aLoginCredentialsBean作为其第一个元素......)

另一种是显式传递元数据对象 - 因此在这种情况下,您Object将从login方法返回 ,以及描述它是什么类型的对象的标记。这可以是一个简单的枚举常量;或者走向另一个极端,您可以使标记成为通用类型,以便编译器可以根据您返回的类型检查它并确保标记是类型正确的。

但无论如何,instanceof太少(信息),太晚了。


请注意,您的login方法看起来……很奇怪。我认为它根本不应该返回一个Object,因为这只是懒惰并且完全颠覆了静态类型系统,这将帮助你。相反,我认为它应该只返回一个List<LoginCredentialsBean>包含与给定登录名相关的凭据。

你有三个不同的返回路径。第一个是在连接数据库时遇到异常——在这种情况下你应该抛出异常!返回带有错误详细信息的字符串是非常不典型且令人困惑的 - 应将异常情况处理为Exception,这就是它们的用途。

其他两种情况是您可以查找确定结果的情况。对于登录失败的情况,我将只返回一个空列表(即此用户名/密码没有任何凭据),同时在成功登录期间返回填充列表。

如果您强烈希望能够区分登录失败和成功登录(没有凭据),那么可能会返回一个复合对象,例如:

class LoginStatus {
    final boolean authenticated;
    final List<LoginCredentialsBean> credentials;
}

无论哪种方式,调用者都知道他们要返回什么,并且可以适当地调用它的方法,而无需调用instanceof和类型转换。

于 2012-10-23T08:27:42.493 回答
0

你必须检查两次。

if (result instanceof ArrayList<?>) {
 System.out.println("ArrayList instance");
 //cast
 ArrayList<LoginCredentialsBean> list = (ArrayList<LoginCredentialsBean>) result;

  ///..check if list contains LoginCredentialsBean
 for(int i=0; i<list.size(); i++){
  if(list.get(i) instanceof LoginCredentialsBean){
   System.out.println("LoginCredentialsBean instance");
  }  
 }
}     
于 2012-10-23T08:27:52.743 回答
0

没有像“包含 LoginCredentialsBean 的 ArrayList”这样的东西,ArrayList 始终包含对象。

您必须遍历列表并检查每个对象:

for (Object o: result) {
     if (!(o instanceof LoginCredentialsBean)) {
           //Fail
     }
}
于 2012-10-23T08:28:55.533 回答
0

您可以使用contains(Object o)来检查 ArrayList 是否包含您的对象。用instanceof List来检查给定的对象是否是一个列表。由于在运行时类型擦除,List 的泛型类型将不可用

于 2012-10-23T08:29:01.107 回答
0

如果您的login方法返回一个Object类型,则无法按照您尝试的方式进行检查。由于类型擦除,类型参数仅存在于编译时。您需要检查重新调整的对象是ListorCollection还是 just Iterable,然后遍历它并检查每个项目,如果它是LoginCredentialsBean.

但是,您的代码是糟糕设计的一个例子。返回一个String或一个列表的方法是错误的。为了使它正确:

  • 让它返回List<LoginCredentialsBean>
  • 如果身份验证失败,则抛出已检查异常

public static List<LoginCredentialsBean> login(DataManager dataManager, String userName, String password) throws AuthenticationException {...}

注意:boolean用于保留逻辑数据而不是"true""false"字符串。

于 2012-10-23T08:32:04.660 回答