Аккумулятор Java Vector Field (private member) не хранит моих коров! - PullRequest
1 голос
/ 26 октября 2008

Редактировать: Этот код в порядке. Я нашел логическую ошибку где-то, чего нет в моем псевдокоде. Я обвинял в этом отсутствие опыта Java.

В псевдокоде ниже я пытаюсь разобрать показанный XML. Глупый пример, может быть, но мой код был слишком большим / конкретным, чтобы кто-то мог извлечь какую-то реальную пользу, увидев его и изучив опубликованные ответы. Так что это более увлекательно, и, надеюсь, другие могут узнать из ответа так же, как и я.

Я новичок в Java, но опытный программист C ++, который заставляет меня поверить, что моя проблема заключается в моем понимании языка Java.

Проблема: Когда анализатор завершает работу, мой Вектор полон неинициализированных Коров. Я создаю Vector of Cows с емкостью по умолчанию (которая не должна влиять на его «размер», если он похож на C ++ STL Vector). Когда я распечатываю содержимое коровьего вектора после разбора, он дает правильный размер вектора, но кажется, что все значения никогда не были установлены.

Информация: я успешно сделал это с другими синтаксическими анализаторами, у которых нет полей Vector , но в этом случае я хотел бы использовать Vector для накопления свойств Cow.

MoreInfo: Я не могу использовать дженерики (Vector ), поэтому, пожалуйста, не указывайте меня там. :)

Заранее спасибо.

<pluralcow>
        <cow>
            <color>black</color>
            <age>1</age>
        </cow>
        <cow>
            <color>brown</color>
            <age>2</age>
        </cow>
        <cow>
            <color>blue</color>
            <age>3</age>
        </cow>
</pluralcow>

public class Handler extends DefaultHandler{
    // vector to store all the cow knowledge
    private Vector  m_CowVec;

    // temp variable to store cow knowledge until
    // we're ready to add it to the vector
    private Cow     m_WorkingCow;

    // flags to indicate when to look at char data
    private boolean m_bColor;
    private boolean m_bAge;

    public void startElement(...tag...)
    {
        if(tag == pluralcow){   // rule: there is only 1 pluralcow tag in the doc
                // I happen to magically know how many cows there are here.             
                m_CowVec = new Vector(numcows);
        }else if(tag == cow ){  // rule: multiple cow tags exist
            m_WorkingCow = new Cow();
        }else if(tag == color){ // rule: single color within cow
            m_bColor = true;
        }else if(tag == age){   // rule: single age within cow
            m_bAge = true;
        }
    }

    public void characters(...chars...)
    {
        if(m_bColor){
            m_WorkingCow.setColor(chars);   
        }else if(m_bAge){
            m_WorkingCow.setAge(chars);
        }
    }

    public void endElement(...tag...)
    {
        if(tag == pluralcow){
            // that's all the cows
        }else if(tag == cow ){
            m_CowVec.addElement(m_WorkingCow);      
        }else if(tag == color){
            m_bColor = false;
        }else if(tag == age){
            m_bAge = false;
        }
    }
}

Ответы [ 4 ]

3 голосов
/ 26 октября 2008

Когда вы говорите, что Коровы неинициализированы, свойства String инициализируются нулем? Или пустые строки?

Я знаю, что вы упомянули, что это псевдокод, но я просто хотел указать на несколько потенциальных проблем:

public void startElement(...tag...)
    {
        if(tag == pluralcow){   // rule: there is only 1 pluralcow tag in the doc
                // I happen to magically know how many cows there are here.                     
                m_CowVec = new Vector(numcows);
        }else if(tag == cow ){  // rule: multiple cow tags exist
                m_WorkingCow = new Cow();
        }else if(tag == color){ // rule: single color within cow
                m_bColor = true;
        }else if(tag == age){   // rule: single age within cow
                m_bAge = true;
        }
    }

Вы действительно должны использовать tag.equals (...) вместо tag == ... здесь.

public void characters(...chars...)
{
    if(m_bColor){
            m_WorkingCow.setColor(chars);   
    }else if(m_bAge){
            m_WorkingCow.setAge(chars);
    }
}

Я предполагаю, что вы знаете об этом, но этот метод на самом деле вызывается с символьным буфером с начальным и конечным индексами.

Также обратите внимание, что символы (...) могут вызываться несколько раз для одного текстового блока, возвращая небольшие фрагменты в каждом вызове: http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html#characters(char[],%20int,%20int)

"... SAX-парсеры могут возвращать все смежные символьные данные в одном блоке, или они могут разбить его на несколько кусков ... "

Я сомневаюсь, что вы столкнетесь с этой проблемой в приведенном вами простом примере, но вы также упомянули, что это упрощенная версия более сложной проблемы. Если в вашей исходной задаче ваш XML состоит из больших текстовых блоков, это нужно учитывать.

Наконец, как уже упоминали другие, если вы могли бы, это хорошая идея рассмотреть библиотеку XML-маршалинга (например, JAXB, Castor, JIBX, XMLBeans, XStream и другие).

1 голос
/ 26 октября 2008

Код выглядит хорошо для меня. Я говорю: установите точки останова в начале каждой функции и просмотрите их в отладчике или добавьте несколько операторов печати. Моя интуиция говорит мне, что либо characters() не вызывается, либо setColor() и setAge() работают неправильно, но это только предположение.

0 голосов
/ 26 октября 2008

Также, если у меня есть схема, я буду использовать JaxB или другой генератор кода для ускорения разработки кода интерфейса XML. Генераторы кода скрывают большую сложность работы напрямую с SAX или DOM4J.

0 голосов
/ 26 октября 2008

Я должен сказать, что я не большой поклонник этого дизайна. Тем не менее, вы уверены, что ваши персонажи когда-либо называются? (может быть, несколько system.outs помогут). Если его никогда не вызывать, вы получите неинициализированную корову.

Кроме того, я бы не стал сам реализовывать синтаксический анализатор XML, поскольку вам нужно быть более устойчивым к проблемам проверки.

Вы можете использовать SAX или DOM4J, или, что еще лучше, использовать Apache Digester.

...