Basit
Basit

Reputation: 8606

How to find ArrayList containing Object

I have a method from which i am returning object like

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()

Now i am testing it like

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);
}

It returns me result like

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

I want to ask i am using condition like ArrayList<?>. How can i check that ArrayList that contain LoginCredentialsBean object. Like when i use

if (result instanceof ArrayList<LoginCredentialsBean>) {

}

i get error that

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

I want to check instanceof ArrayList and arraylist has LoginCredentialsBean ?

Thank you.

Upvotes: 0

Views: 791

Answers (6)

Andrzej Doyle
Andrzej Doyle

Reputation: 103797

The short answer is that you can't. Generics are implemented via type erasure - they're effectively a compile-time syntactic sugar to ensure you don't put an Integer into a List<String>.

The runtime objects themselves, however, are just the raw types. An instance of ArrayList doesn't know that it's an ArrayList<String> (or rather, that it was assigned to a variable with that generic type). So when you interrogate it with reflection, you cannot get any generic type info.

There are two broad types of solution I can think of. One is to iterate over the list contents and check their dynamic type - if the first element is a LoginCredentialsBean, for example, then it's reasonable to assume that you have a List<LoginCredentialsBean>. This won't work for empty lists though, which could be a problem, and can potentially give false positives (e.g. a List<Object> allParameters might happen to have a LoginCredentialsBean as its first element...)

The other is to explicitly pass metadata objects around - so in this case you'd return the Object from the login method, along with a token which describes what type of object it is. This could be a simple enum constant; or going to the other extreme you could make the tokens generically typed, such that the compiler can check this against the type of what you're returning and ensure that the tokens are type-correct.

But in any case, instanceof is too little (information), too late.


Mind you, your login method looks... odd. I don't think it should return an Object at all, as that's just lazy and completely subverting the static type system which would help you here. Rather, I think it should just return a List<LoginCredentialsBean> containing the credentials that pertain to the given login.

You have three different paths where you return. The first is if an exception is encountered when connecting to the database - in which case you should throw an exception! Returning a string with the error details is very atypical and confusing - an exceptional condition should be handled as an Exception, that's what they're for.

The other two situations are ones where you're able to look up definitive results. For the failed login case, I would just return an empty list (i.e. this username/password has no credentials whatsoever), while returning the populated list during a successful login.

If you strongly want to be able to distinguish between a login failure, and a successful login (with no credentials), then perhaps return a compound object instead, such as:

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

Either way, the caller knows exactly what they're getting back, and can call methods on it appropriately without having to call instanceof and typecast.

Upvotes: 1

Piotr Gwiazda
Piotr Gwiazda

Reputation: 12212

If your login method returns an Object type there is no way to check this the way you try. Type parameters exist only on compile-time due to type erasure. You need to check if retuned object is a List or Collection or just Iterable, then iterate throuh it and check every item, if it is a instance of LoginCredentialsBean.

However, your code is an example of bad design. A method that returns a String or a list is just wrong. To make it right:

  • make it return List<LoginCredentialsBean>
  • throw a checked exception if authentication fails

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

Note: Use boolean to keep logical data instead of "true" or "false" strings.

Upvotes: 0

clinton
clinton

Reputation: 612

you can use the contains(Object o) to check whether the ArrayList contains your object. With the instanceof List to check whether the given object is a List. Because of type erasure at runtime the generic type of the List wont be available

Upvotes: 0

shem
shem

Reputation: 4712

There is no such thing like "ArrayList that contain LoginCredentialsBean" ArrayList contains Objects, all the time.

you must iterate over the list and check each object:

for (Object o: result) {
     if (!(o instanceof LoginCredentialsBean)) {
           //Fail
     }
}

Upvotes: 0

Russell Gutierrez
Russell Gutierrez

Reputation: 1385

You have to check it twice.

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

Upvotes: 0

Anders R. Bystrup
Anders R. Bystrup

Reputation: 16060

Parameterized type info is erased at compile time and instanceof is resolved at (fanfare) runtime - that is why you get that error.

What you could do is iterate over the elements in the List and instanceof them.

Cheers,

Upvotes: 1

Related Questions