Java 迭代列表中的特定实例

Java 迭代列表中的特定实例,java,class,oop,Java,Class,Oop,我有一个ArrayList,它包含不同类的一些实例,我想在for循环中迭代特定类型的类(例如扩展OnRender.class的类); 我有一个正常工作的代码,但是代码违反了OO规则,导致了一些警告。 我能做到这一点吗?否则我将永远被沮丧打破 回顾我写的东西,我发现我没有很好地解释它,所以检查下面的代码来了解我的意思 代码: public class ListenerManager{ List<Object> listeners=new ArrayList<Object&

我有一个ArrayList,它包含不同类的一些实例,我想在for循环中迭代特定类型的类(例如扩展OnRender.class的类); 我有一个正常工作的代码,但是代码违反了OO规则,导致了一些警告。 我能做到这一点吗?否则我将永远被沮丧打破

回顾我写的东西,我发现我没有很好地解释它,所以检查下面的代码来了解我的意思

代码

public class ListenerManager{
    List<Object> listeners=new ArrayList<Object>();
    int it;
    Class clazz;
    public <T extends Object> T begin(Class<T> clazz){
        it=-1;
        this.clazz=clazz;
        return next();
    }
    public <T extends Object> T next(){
        while((++it)<listeners.size()){
            if (clazz.isInstance(listeners.get(it))){
                return (T)listeners.get(it);
            }
        }
        return null;
    }
    public void add(Object listener){
        listeners.add(listener);
    }
}
ListenerManager lm=new ListenerManager();
lm.add(new OnRenderListener(){
    ........
});
for(OnRenderListener orl=lm.begin(OnRenderListener.class);orl!=null;orl=lm.next){
    .......
}
我收到的警告

public class ListenerManager{
    List<Object> listeners=new ArrayList<Object>();
    int it;
    Class clazz;
    public <T extends Object> T begin(Class<T> clazz){
        it=-1;
        this.clazz=clazz;
        return next();
    }
    public <T extends Object> T next(){
        while((++it)<listeners.size()){
            if (clazz.isInstance(listeners.get(it))){
                return (T)listeners.get(it);
            }
        }
        return null;
    }
    public void add(Object listener){
        listeners.add(listener);
    }
}
ListenerManager lm=new ListenerManager();
lm.add(new OnRenderListener(){
    ........
});
for(OnRenderListener orl=lm.begin(OnRenderListener.class);orl!=null;orl=lm.next){
    .......
}
类clazz->类是原始类型。泛型类型类的引用应该参数化

return(T)listeners.get(it)->类型安全:未选中从对象到T的强制转换


我不想只使用Suspecnd注释来挂起警告,我希望遵循OO规则。

如果要标识特定的类或接口,请使用以下实例:

然而,这一点都不是很好。您确实希望利用语言的继承性和多态性。我的第一个想法是,您的列表应该只包含
侦听器
或子类型,例如

listeners = new ArrayList<Listener>();
这也是一种选择。您可以将访问者对象传递给每个侦听器,每个侦听器将根据其类型决定要执行的操作。优点是,当您添加子类型时,您必须添加适当的方法——没有从类声明序列中省略类型的危险

Visitor v = new OnlyInterestedInOneTypeOfListener();
for (Listener l : listeners) {
   l.useVisitor(v);  // different subclasses will call different methods
                     // on the visitor. Some may be no-ops for different visitor
                     // implementations
}

(顺便说一句,我注意到您希望发现实现特定方法的条目。这是调用的,Java不支持它。其他语言(如Scala)也支持它)

如果您想识别特定的类或接口,请使用instanceof:

然而,这一点都不是很好。您确实希望利用语言的继承性和多态性。我的第一个想法是,您的列表应该只包含
侦听器
或子类型,例如

listeners = new ArrayList<Listener>();
这也是一种选择。您可以将访问者对象传递给每个侦听器,每个侦听器将根据其类型决定要执行的操作。优点是,当您添加子类型时,您必须添加适当的方法——没有从类声明序列中省略类型的危险

Visitor v = new OnlyInterestedInOneTypeOfListener();
for (Listener l : listeners) {
   l.useVisitor(v);  // different subclasses will call different methods
                     // on the visitor. Some may be no-ops for different visitor
                     // implementations
}
(顺便说一句,我注意到您希望发现实现特定方法的条目。这是调用的,Java不支持它。其他语言(如Scala)也支持它)

您可以使用Guava的方法。它将只在您想要的子类型上迭代

for (YourType filteredElement : Iterables.filter(listeners, YourType.class)) {
    doSomething(filteredElement);
}
你可以用番石榴的方法。它将只在您想要的子类型上迭代

for (YourType filteredElement : Iterables.filter(listeners, YourType.class)) {
    doSomething(filteredElement);
}

您的
ListenerManager
应该返回一个java
迭代器,或者返回一个经过筛选的
集合(或者
列表
)。不要自己重建迭代器概念。特别是在manager类中设置
begin
next
会引入不必要的状态

使用Java 8,您的
ListenerManager
可以轻松编写为:

public class ListenerManager {
    private final List<Object> listeners = new ArrayList<Object>();

    public <T> Collection<T> listenersOf(Class<T> type) {
        return listeners.stream()
            .filter(type::isInstance)
            .map(type::cast)
            .collect(Collectors.toList());
    }

    public void add(Object listener) {
        listeners.add(listener);
    }
}

您的
ListenerManager
应该返回一个java
迭代器,或者返回一个经过筛选的
集合(或者
列表
)。不要自己重建迭代器概念。特别是在manager类中设置
begin
next
会引入不必要的状态

使用Java 8,您的
ListenerManager
可以轻松编写为:

public class ListenerManager {
    private final List<Object> listeners = new ArrayList<Object>();

    public <T> Collection<T> listenersOf(Class<T> type) {
        return listeners.stream()
            .filter(type::isInstance)
            .map(type::cast)
            .collect(Collectors.toList());
    }

    public void add(Object listener) {
        listeners.add(listener);
    }
}
这只是一种粗略的(不可编译的)方法

public interface Listener{ public boolean canHandle(Event ev); public void handle(Event ev); } public class OnRenderListener implements Listener { public boolean canHandle(Event ev){ return ev instanceOf OnRenderEvent; // or look for the classname } public void handle(Event ev); } public class KeyPressListener implements Listener { public boolean canHandle(Event ev){ return ev instanceOf KeyPressEvent; // or look for the classname } public void handle(Event ev){ keyPressed(((KeyPressEvent)ev).getKey()); } keyPressed(int key){....} } public class Event{} public class KeyPressEvent extends Event{ int key; } public class OnRenderEvent extends Event{ //other stuff } //Loop to fire an event for(Listener lis : listeners){ if(lis.canHandle(currentEvent){ lis.handle(currentEvent); } } 公共接口侦听器{ 公共布尔canHandle(事件ev); 公共无效句柄(事件ev); } 公共类OnRenderListener实现侦听器{ 公共布尔canHandle(事件ev){ 返回ev instanceOf OnRenderEvent;//或查找类名 } 公共无效句柄(事件ev); } 公共类KeyPressListener实现监听器{ 公共布尔canHandle(事件ev){ 返回keypress事件的ev instanceOf;//或查找类名 } 公共无效句柄(事件ev){ 按键(((按键事件)ev.getKey()); } 按键(输入键){…} } 公共类事件{} 公共类KeyPressEvent扩展事件{ int键; } 公共类OnRenderEvent扩展事件{ //其他东西 } //循环以触发事件 for(侦听器lis:侦听器){ if(lis.canHandle(currentEvent){ lis.handle(currentEvent); } } 这只是一种粗略的(不可编译的)方法

public interface Listener{ public boolean canHandle(Event ev); public void handle(Event ev); } public class OnRenderListener implements Listener { public boolean canHandle(Event ev){ return ev instanceOf OnRenderEvent; // or look for the classname } public void handle(Event ev); } public class KeyPressListener implements Listener { public boolean canHandle(Event ev){ return ev instanceOf KeyPressEvent; // or look for the classname } public void handle(Event ev){ keyPressed(((KeyPressEvent)ev).getKey()); } keyPressed(int key){....} } public class Event{} public class KeyPressEvent extends Event{ int key; } public class OnRenderEvent extends Event{ //other stuff } //Loop to fire an event for(Listener lis : listeners){ if(lis.canHandle(currentEvent){ lis.handle(currentEvent); } } 公共接口侦听器{ 公共布尔canHandle(事件ev); 公共无效句柄(事件ev); } 公共类OnRenderListener实现侦听器{ 公共布尔canHandle(事件ev){ 返回ev instanceOf OnRenderEvent;//或查找类名 } 公共无效句柄(事件ev); } 公共类KeyPressListener实现监听器{ 公共布尔canHandle(事件ev){ 返回keypress事件的ev instanceOf;//或查找类名 } 公共无效句柄(事件ev){ 按键(((按键事件)ev.getKey()); } 按键(输入键){…} } 公共类事件{} 公共类KeyPressEvent扩展事件{ int键; } 公共类OnRenderEvent扩展事件{ //其他东西 } //循环以触发事件 for(侦听器lis:侦听器){ if(lis.canHandle(currentEvent){ lis.handle(currentEvent); } }
那么所有监听器都实现的通用监听器接口呢?那么OnRenderListener实现/扩展监听器呢?@HankLapidez,我仍然需要强制转换,因为所有监听器都没有相同的方法,有使用touch(float x,float y y)方法的OnTouchListener和使用按键(int键)的OnKeyPressListener方法在循环中要触发事件吗?一般侦听器int如何