MortalMan
MortalMan

Reputation: 2612

Passing unknown ArrayList type to method

Say I have these two ArrayLists:

ArrayList<Book> book = new ArrayList<>();
ArrayList<Journal> journal = new ArrayList<>();

Book and Journal are two different classes.

Both Book and Journal objects have a getYear() method. I want to make a method that passes in an unknown ArrayList type and compares a passed in year to an object in the list. The following code is in main:

public static void fooBar(int year, ArrayList<?> list)
{
    if(list.get(0).getYear() == year) // does not work!
    {
    }
}

If an unknown type is passed into the method, I cannot use that object's methods (getYear()). How can I do this without making two methods that do the same thing (one for Book and one for Journal)?

Upvotes: 9

Views: 3084

Answers (4)

Manish Kumar
Manish Kumar

Reputation: 7179

Everyone discussed about the right way of doing it, such as associating your object with a super class containing your desired method, but if you want some fancy implementation without using super class, you can try lambda expression:

ArrayList<Book> book = new ArrayList<>();
book.stream().limit(1).filter(s->s.getYear()==year).forEach(yourcode)

I know this is not what you wanted but you have right solution from other comments.

Upvotes: 1

JonK
JonK

Reputation: 2108

Have both Book and Journal extend a common superclass (Publication perhaps?) or implement a common interface which defines the getYear() method:

public abstract class Publication {
    private int year;

    public int getYear() {
        return year;
    }

    public Publication(int year) {
        this.year = year;
    }
}

If you then change your Book and Journal class declarations and constructors:

public class Book extends Publication {

     public Book(int year, ...) {
         super(year);
         ...
     }
public class Journal extends Publication {

     public Journal(int year, ...) {
         super(year);
         ...
     }

You could then pass around a list of Publication objects:

public void fooBar(int year, List<? extends Publication> list) { ... }

Because it's Publication that defines the getYear() method, you can freely use it on objects contained within list.

Upvotes: 3

Michael
Michael

Reputation: 2773

Like JonK said, if they share a superclass or interface that defines getYear() then this will be made easier. Actually, the have to have either of those two relationships to make your proposed relationship.

interface HasYear {
    public int getYear();
}

Book.java

public class Book implements HasYear{
    //...
    public int getYear(){/*YOUR IMPLEMENTATION*/}
}

Journal.java

public class Journal implements HasYear{
    //...
    public int getYear(){/*YOUR IMPLEMENTATION*/}
}

Now, you can create and use your ArrayList like this:

public static void fooBar(int year, ArrayList<? extends HasYear> list){
    if(list.get(0).getYear() == year){
        //yay
    }
}

Upvotes: 4

rgettman
rgettman

Reputation: 178253

You can make an interface (if it doesn't already exist) (possibly named HasYear) that declares the getYear() method, and have Book and Journal implement it.

Then you can have your fooBar method take an ArrayList of some type parameter that is a HasYear.

public static void fooBar(int year, ArrayList<? extends HasYear> list)

The ? extends is due to the fact it's a consumer and not a producer.

Upvotes: 14

Related Questions