此方法应该是阻塞方法,但为什么有时候没有阻塞。当运行时输入b,就会报错:
package ch5.s5_9;import java.util.Scanner;
public class InterIterApp {
    public static void main(String[] args) {
        LinkList list=new LinkList();
        ListIterator iter1=list.getIterator();        long value;        iter1.insertAfter(20);
        iter1.insertAfter(40);
        iter1.insertAfter(80);
        iter1.insertBefore(60);        Scanner in=new Scanner(System.in);
        while (true){
            System.out.print("Enter first leffer of show ,reset,next,get,before,after,delete: ");            int choice=in.nextLine().charAt(0);            switch(choice){
                case 's':
                    if (!list.isEmpty()){
                        list.displayList();
                    } else {
                        System.out.println("List is empty");
                    }
                    break;
                case 'r':
                    iter1.reset();
                    break;
                case 'n':
                    if (!list.isEmpty() && !iter1.atEnd()){
                        iter1.nextLink();
                    } else {
                        System.out.println("Can't go to next link");
                    }
                    break;
                case 'g':
                    if (!list.isEmpty()){
                        value=iter1.getCurrent().dData;
                        System.out.println("Returened "+value);
                    } else {
                        System.out.println("List is empty");
                    }
                    break;
                case 'b':
                    System.out.print("Enter value to insert: ");
                    value=in.nextLong();
                    in.reset();
                    iter1.insertBefore(value);
                    break;
                case 'a':
                    System.out.print("Enter value to insert: ");
                    value=in.nextInt();
                    iter1.insertAfter(value);
                    break;
                case 'd':
                    if (!list.isEmpty()){
                        value=iter1.deleteCurrent();
                        System.out.println("Deleted "+value);
                    } else {
                        System.out.println("Can't delete");
                    }
                    break;
                default:
                    System.out.println("Invalid entry");
            }
        }
    }
}class Link{
    public long dData;
    public Link next;    Link(long dData) {
        this.dData = dData;
    }    public void displayLink(){
        System.out.print(dData+" ");
    }
}class LinkList{
    private Link first;    LinkList() {
    }    public Link getFirst(){
       return first;
    }    public void setFirst(Link f){
        first=f;
    }    public boolean isEmpty(){
        return first==null;
    }    public ListIterator getIterator(){
        return new ListIterator(this);
    }    public void displayList(){
        Link current=first;
        while (current!=null){
            current.displayLink();
            current=current.next;
        }        System.out.println("");
    }
}class ListIterator{
    private Link current;
    private Link previous;
    private LinkList ourList;    ListIterator(LinkList ourList) {
        this.ourList = ourList;
        reset();
    }    public void reset() {
        current=ourList.getFirst();
        previous=null;
    }    public boolean atEnd(){
        return current.next==null;
    }    public void nextLink(){
        previous=current;
        current=current.next;
    }    public Link getCurrent(){
        return current;
    }    public void insertAfter(long dd){
        Link newLink=new Link(dd);        if (ourList.isEmpty()){
            ourList.setFirst(newLink);
            current=newLink;
        }else {
            newLink.next=current.next;
            current.next=newLink;
            nextLink();
        }
    }    public void insertBefore(long dd){
        Link newLink=new Link(dd);        if (previous==null){
            newLink.next=ourList.getFirst();
            ourList.setFirst(newLink);
            reset();
        } else {
            newLink.next=previous.next;
            previous.next=newLink;
            current=newLink;
        }
    }    public long deleteCurrent(){
        long value=current.dData;        if (previous==null){
            ourList.setFirst(current.next);
            reset();
        } else {
            previous.next=current;
            if (atEnd()){
                reset();
            } else {
                current=current.next;
            }
        }        return value;
    }
}

解决方案 »

  1.   

    我不明白你说的阻塞是什么意思。而且你的程序输入b也没出现问题,是再输入一个数之后才会有问题。
    原因是那个数单独占了一行,你下一个nextLine()读进来的是空行,于是charAt(0)就溢出了。
      

  2.   


    value = in.nextLong();
    这句改为
    value = Long.parseLong(in.nextLine());
    另外输入 a 也有一样的问题,按上面方法改为
    value = Integer.parseInt(in.nextLine());
      

  3.   

    我的意思就是当输入一个数字后,执行完链表的插入后,又循环到了: System.out.print("Enter first leffer of show ,reset,next,get,before,after,delete: ");,此时程序应该等待输入一个选择后再进行下一项,而实际上它没有直接阻塞住,直接去读了,当然读不到东西。
      

  4.   

    甚至System.out.println("Enter first leffer of show ,reset,next,get,before,after,delete: ");这句都没执行就直接执行后面的int choice=in.nextLine().charAt(0);了,所以我很奇怪,虽然把int choice=in.nextLine().charAt(0);改成int choice=in.next().charAt(0);可以解决问题,但我却不知为什么。
      

  5.   

    当输入 b 执行到
    System.out.print("Enter value to insert: ");
    value=in.nextLong();
    这句时在 Enter value to insert: 提示信息后在执行 nextLong 方法时缓冲区是空的,这将导致线程被阻塞在 nextLong 方法等待输入新字符到缓冲区。假如输入 96[回车换行符],在敲回车后 9 6 [回车换行符]会被装入缓冲区并通知阻塞于 nextLong 方法的线程继续往下运行,nextLong 方法只会从缓冲区中取出 96 两个字符将它们转换为 long 类型值并插入链表。至此这次循环结束进入下一次循环(此时缓冲区里还有一个[回车换行符])。
    System.out.print("Enter first leffer of show ,reset,next,get,before,after,delete: ");
    int choice=in.nextLine().charAt(0);
    执行到这两句,提示信息打印出后,nextLine 方法同样会检测缓冲区是否为空,如果不为空就不会被阻塞,此时上次输入的[回车换行符]还在缓冲区里,nextLine 不会阻塞而会到缓冲区里直接去读取字符一直读到遇到的第一个[回车换行符]为止(nextLine 会把[回车换行符]从缓冲区中移除),并将[回车换行符]前的所有字符装入 String 对象并返回。因为缓冲区里仅有一个[回车换行符]所以 nextLine 方法会返回一个空串,此时在对空串调用 charAt(0) 就会抛出 StringIndexOutOfBoundsException 异常。
      

  6.   

    你说的是对的,我在sun的论坛也问了,回答和你一样,但没你说的详细,谢谢,还想问一下,我如果不想nextLine强转成long,是不是只能nextLong之后,再nextLine一遍(只为了清缓存,不是为了读)才可解决此问题,有没有一个方法调用nextLong后自动清缓存呢。好像是没有。
      

  7.   

    value = Long.parseLong(in.nextLine());