如何使用泛型为我的方法使用变量返回值?

时间:2014-05-14 03:48:07

标签: java xml class generics

我有一个匿名类XMLHandler,带有" parseXML"方法。此方法负责解析XML。 XML是测验问题的来源。我有不同类型的XML用于不同的测验。 parseXML()提供了一个包含特定问题的ArrayList。问题是带有问题,答案等字符串的对象。由于测验不同,我有几个课程。我想要的是为每个XML使用这个parseXML。你在下面看到的是我目前的状态。但是在行

currentQuestion = new ...

我需要类似的东西:

currentQuestion = new T;

但这并不奏效。那么,我该怎么办?

XMLHandler xmlHandler = new XMLHandler(activity.getApplicationContext(), "source_quiz.xml"){

        @Override
        public <T> ArrayList<T> parseXML() throws XmlPullParserException, IOException {
            ArrayList<T> questions = null;
            int eventType = parser.getEventType();
            T currentQuestion = null;

            while(eventType != XmlPullParser.END_DOCUMENT){
                String name = null;
                switch (eventType){
                case XmlPullParser.START_DOCUMENT:
                    questions = new ArrayList<T>();
                    break;
                case XmlPullParser.START_TAG:
                    name = parser.getName();
                    if(name.equals("question")){
                        currentQuestion = new ...// new QuizQuestion();
                    } else if(currentQuestion != null){
                        if(name.equals("q")) {
                            currentQuestion.setQuestion(parser.nextText());
                        } else if(name.equals("a")){
                            currentQuestion.addAnswer(parser.nextText());
                        } else if(name.equals("c")){
                            currentQuestion.setCategory(parser.nextText());
                        } else if(name.equals("p")){
                            currentQuestion.setPage(parser.nextText());
                        } else if(name.equals("u")){
                            currentQuestion.setUnit(parser.nextText());
                        }
                    }

                    break;
                case XmlPullParser.END_TAG:
                    name = parser.getName();
                    if(name.equalsIgnoreCase("question") && currentQuestion != null){
                        questions.add(currentQuestion);
                    }
                    break;
                }
                eventType = parser.next();
            }
            return questions;
        }
    };      

2 个答案:

答案 0 :(得分:1)

不允许这样做。作为解决方法,您可以这样做

public <T> ArrayList<T> parseXML(Class<T> cls) throws ...
...
        T currentQuestion = cls.newInstance();
...

答案 1 :(得分:1)

第一个问题是您是否有权修改方法签名并且您愿意这样做吗?如果答案为否,则除非您将调出子类化并在参数中取一个额外值以实际设置您感兴趣的对象类型,否则无法执行此操作。

如果你可以修改方法签名,那么这可能有用。

public <T extends IQuestion> ArrayList<T> parseXML(IQuestionFactory<T> factory) {
   //code
   T currentQuestion = factory.create();
   //code
}

这将采用可以创建新对象的界面

public interface IQuestionFactory<T extends IQuestion> {
   public T create();
}

如果您使用的是Java 8,则可以使用lambdas,但我假设您没有使用java 8.因此您必须以这种方式调用它:

xmlHandler.parseXml(new IQuestionFactory<SpecialQuestion>() {
   @Override
   public SpecialQuestion create() {
      return new SpecialQuestion();
   }
});

如果你不能改变方法签名,你应该研究如下子类化XmlHandler

public class QuestionXmlHandler<T extends IQuestion> extends XmlHandler {
    private IQuestionFactory<T> factory;

    public QuestionXmlHandler(IQuestionFactory<T> factory) {
       this.factory = factory;
    }

    public ArrayList<T> parseXML() throws XmlPullParserException, IOException {
        //code
        T currentQuestion = factory.create();
        //code
    }
}

但是,对于每种问题类型,您都需要一个新的XmlHandler。

请注意,您需要将IQuestion定义为一个接口,用于处理您在currentQuestion上调用的方法(即setQuestion,setCategory,setPage,setUnit)。