繁体   English   中英

使用ArrayList的IndexOutOfBoundsException

[英]IndexOutOfBoundsException using ArrayList

用户可以选择一个月。 我为包含月份列表的ComboBox设置了一个侦听器ItemListener 我有一个设定的条件,如果用户选择“二月”的天列表,最多只能有29天, “四月”,“六月” ,依此类推,则ComboBox上将有30天。 但是,当我选择“ 2月”时,它可以正常工作,但是当我选择另一个月时,我会收到一个错误消息。

IndexOutOfBoundsException: Index: 30, Size: 29

我知道发生此错误是因为另一个月份的索引为30。我有点困惑,应该删除ArrayList或ComboBox的内容吗? 有什么帮助我该如何消除呢?

private ItemHandler handler = new ItemHandler();

ArrayList<String> daysList = new ArrayList<String>();

String[] daysObj = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15",
        "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"};
 DefaultComboBoxModel daysModel = new DefaultComboBoxModel(daysObj);

public AddEmployee() 
{
  setMonths();
  setDays();
  cbMonths.addItemListener(handler);
}

private void setDays()
{   
    for(int i = 0; i < daysObj.length; i++)
    {
        daysList.add(daysObj[i]);
    }

    cbDays.setModel((ComboBoxModel)daysModel);   
}

private class ItemHandler implements ItemListener
{
    int removeDays[] = {29,30};//array
    int remove[] = {30};
    @Override
    public void itemStateChanged(ItemEvent e) 
    {
        if(e.getSource() == cbMonths)//Check where combobox occured.
        {
            if(cbMonths.getSelectedItem().equals("February"))
            {
                for(int i = removeDays.length-1; i >= 0; i--)
                {
                    daysList.remove(removeDays[i]);//Remove given array from ArrayList using removeDays[]
                    System.out.println("NEW ELEMENT: "+daysList);
                }

                for(String s : daysList)//Update ArrayList
                {
                    cbDays.addItem(s);
                    System.out.println("NEW LIST OF ARRAY: "+s);
                }

            }
            else if(cbMonths.getSelectedItem().equals("April") || cbMonths.getSelectedItem().equals("June") || 
                    cbMonths.getSelectedItem().equals("September") || cbMonths.getSelectedItem().equals("November"))
            {
                for(int i = remove.length-1; i >= 0; i--)
                {
                    daysList.remove(remove[i]);
                    System.out.println(daysList);
                }

                for(String a : daysList)//Update ArrayList
                {
                    cbDays.addItem(a);
                    System.out.println("NEW LIST OF ARRAY: "+a);
                }

            }
      }
}

我尝试了方法removeAllItems()但它似乎不起作用。 cbDays.removeAllItems();

与其每次用户选择另一个月(这很难读取且容易出错),都执行复杂的计算,而是更好地初始化一些涵盖所有情况的静态模型。 然后,您的StateChaged处理程序只需选择正确的模型。 下面的示例基于新的java 8 datetime API:

private static String[] initDays( int number )
{
    String[] result = new String[ number];

    for ( int i = 0; i < result.length; i++ )
    {
        result[i] = "" + ( i+1);
    }

    return result;
}

private static final String[] days28 = initDays( 28);
private static final String[] days29 = initDays( 29);
private static final String[] days30 = initDays( 30);
private static final String[] days31 = initDays( 31);

private static final ComboBoxModel<String> model28 = new DefaultComboBoxModel<>(days28);
private static final ComboBoxModel<String> model29 = new DefaultComboBoxModel<>(days29);
private static final ComboBoxModel<String> model30 = new DefaultComboBoxModel<>(days30);
private static final ComboBoxModel<String> model31 = new DefaultComboBoxModel<>(days31);

private static final Set<Month> month30 = EnumSet.of(
         Month.FEBRUARY,
         Month.APRIL,
         Month.JUNE,
         Month.SEPTEMBER,
         Month.NOVEMBER
     );
private static final Set<Month> month31 = EnumSet.of(
         Month.JANUARY,
         Month.MARCH,
         Month.MAY,
         Month.JULY,
         Month.AUGUST,
         Month.OCTOBER,
         Month.DECEMBER
     );
private JComboBox<String> cbMonths = new JComboBox<>();
private JComboBox<String> cbDays = new JComboBox<>();

public void itemStateChanged(ItemEvent e)
{
    if(e.getSource() == cbMonths)//Check where combobox occured.
    {
        if(cbMonths.getSelectedItem().equals("February"))
        {
            Month selectedMonth = Month.valueOf( cbMonths.getItemAt( cbMonths.getSelectedIndex() ) );

            if ( month31.contains( selectedMonth ) )
            {
                cbDays.setModel( model31 );
            }
            else if ( month30.contains( selectedMonth ) )
            {
                cbDays.setModel( model30 );
            }
            else
            {
                if ( Year.isLeap( Instant.now().getLong( ChronoField.YEAR ) ) )
                {
                    cbDays.setModel( model29 );
                }
                else
                {
                    cbDays.setModel( model28 );
                }
            }
        }
    }
}

进一步的增强可能是使用由Month枚举直接键入的cbMonth,并提供一个单元格渲染器,该渲染器在用户的语言环境中显示月份。

通过setDays()初始化后, daysList包含31个元素。 选择February ,将删除索引为2930两个元素:

    daysList.remove(removeDays[i])

daysList现在有29元素。 选择另一个月后,将删除索引为30一个元素

    daysList.remove(remove[i]);

但是dayslist只有29个元素,因此抛出IndexOutOfBoundsException

因此,一种解决方案可能是每次触发itemStateChanged重新初始化daysList

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM