2015-10-13 18 views
8

Sagen, ich habe diese beiden Arraylisten:Passing unbekannt Arraytyp Methode

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

Book und Journal zwei verschiedene Klassen sind.

Beide Book und Journal Objekte haben eine getYear() Methode. Ich möchte eine Methode erstellen, die einen unbekannten ArrayList-Typ übergibt und ein übergebenes Jahr mit einem Objekt in der Liste vergleicht. Der folgende Code ist in Haupt:

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

Wenn eine unbekannte Art in die Methode übergeben wird, kann ich nicht dieses Objekt Methoden (getYear()) verwenden kann. Wie kann ich dies tun, ohne zwei Methoden zu machen, die dasselbe tun (eine für Book und eine für Journal)?

+4

Haben 'Book' und' Journal' eine Oberklasse oder Schnittstelle, die 'getYear()' definiert? – JonK

+0

Meine Methodensignatur war falsch, ich habe die Frage bearbeitet. – MortalMan

+1

Was @JonK gefragt ... Wenn es nicht ist, sollten Sie einen machen und das würde Ihr Problem lösen – 3kings

Antwort

13

Sie können eine Schnittstelle machen (wenn es nicht bereits vorhanden) (möglicherweise HasYear genannt), die die getYear() Methode deklariert und haben Book und Journal es umzusetzen.

Dann können Sie Ihre fooBar Methode eine ArrayList von einem Typ Parameter, der eine HasYear ist.

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

Die ? extends ist aufgrund der Tatsache, dass es ein Verbraucher ist und kein Produzent.

+0

Ich lerne Java in der Schule und ich habe nicht gelernt, was eine Schnittstelle ist. Warum kann Java nicht einfach den Listentyp ableiten, den ich an die Methode sende, damit ich die Methoden dieses Objekts verwenden kann? – MortalMan

+3

Mit einem 'List ' Parameter können Sie eine Liste von allem, z. 'Liste ', 'Liste ', 'Liste ', etc., die nicht unbedingt eine 'getYear()' Methode haben. Der Compiler erlaubt es Ihnen nicht, eine Methode aufzurufen, die nicht garantiert werden kann. – rgettman

+0

Ihre Liste wird in der Methode als 'List ' angegeben, also könnte sie alles enthalten. – khelwood

4

Wie JonK sagte, wenn sie eine Oberklasse oder Schnittstelle teilen, die getYear() definiert, dann wird dies erleichtert werden. Eigentlich haben die , um eine dieser beiden Beziehungen zu haben, um Ihre vorgeschlagene Beziehung zu machen.

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*/} 
} 

Jetzt können Sie erstellen und die Arraylist wie folgt verwenden:

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

Haben beide Book und Journal erweitern eine gemeinsame übergeordnete Klasse (? Publication vielleicht) oder eine gemeinsame Schnittstelle implementieren, die die getYear() Methode definiert:

public abstract class Publication { 
    private int year; 

    public int getYear() { 
     return year; 
    } 

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

Wenn Sie dann Ihre Book und Journal Klassendeklarationen und Konstrukteuren ändern:

public class Book extends Publication { 

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

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

Sie könnten dann eine Liste von Publication Objekte weitergeben:

Da es Publication ist, das die getYear() Methode definiert, können Sie es frei für Objekte verwenden, die in list enthalten sind.

+0

Wie andere Antworten gezeigt haben, können Sie auch eine Schnittstelle verwenden, um dasselbe auf die gleiche Weise zu erreichen. – JonK

+2

mit 'List ' als Argument erlaubt es Ihnen, 'list.add (new Book())' unabhängig vom tatsächlichen Typ des Inhalts von 'list' aufzurufen, was sehr gefährlich ist. '? Extends Publication' verhindert das. – njzk2

+0

@ njzk2 Ich nehme an, es hängt wirklich davon ab, was Sie mit der Liste machen, aber ja, Punkt genommen. Ich werde die Antwort aktualisieren. – JonK

1

Jeder diskutiert über den richtigen Weg, es zu tun, wie Sie Ihr Objekt mit einer Superklasse zuordnet Ihre gewünschte Methode enthält, aber wenn man ohne Verwendung von Super-Klasse einige ausgefallene Implementierung möchten, können Sie Lambda-Ausdruck versuchen:

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

Ich weiß, das ist nicht das, was Sie wollten, aber Sie haben die richtige Lösung aus anderen Kommentaren.

Verwandte Themen