黑马程序员技术交流社区

标题: 把StringBufilder定义在函数里面和外面的区别 [打印本页]

作者: 张吉日    时间: 2012-9-6 21:26
标题: 把StringBufilder定义在函数里面和外面的区别
本帖最后由 张吉日 于 2012-9-7 14:37 编辑
  1. /*StringBuilder sb = new StringBuilder();   //此代码在16行处
  2. 为什么我把他定义在 public String myReadLine()throws IOException 方法外就会无限循环..
  3. 放在外面不也是调用的吗?????有什么不同之处
  4. */
  5. import java.io.*;
  6. class MyBufferedReader extends Reader
  7. {
  8.         private Reader r;
  9.         MyBufferedReader(Reader r)
  10.         {
  11.                 this.r=r;
  12.         }
  13.         
  14.         public String myReadLine()throws IOException
  15.         {
  16.                 StringBuilder sb = new StringBuilder();
  17.                 int line = 0;
  18.                 while ((line=r.read())!=-1)
  19.                 {
  20.                         if(line=='\r')
  21.                                 continue;
  22.                         if(line=='\n')
  23.                                 return sb.toString();//一次次循环 当结尾到\n的时候返回.
  24.                         else
  25.                                 sb.append((char)line);//添加元素.你的任务就是添加元素,停止的事交给return
  26.                 }
  27.                 if(sb.length()!=0)
  28.                         return sb.toString();

  29.                 return null;
  30.         }
  31.         public void close()throws IOException
  32.         {
  33.                 r.close();
  34.         }
  35.         public int read(char[] cbuf, int off, int len)throws IOException
  36.         {
  37.                 return read(cbuf,off,len);
  38.         }
  39. }

  40. class  装饰法
  41. {
  42.         public static void main(String[] args)
  43.         {
  44.                 FileReader fr = null;
  45.                 MyBufferedReader mybufr = null;
  46.                 try
  47.                 {
  48.                         fr = new FileReader("FileStream.java");
  49.                         mybufr = new MyBufferedReader(fr);

  50.                         String str = null;
  51.                         while ((str=mybufr.myReadLine())!=null)
  52.                         {
  53.                                 System.out.println(str);
  54.                         }
  55.                         
  56.                 }
  57.                 catch (IOException e)
  58.                 {
  59.                         throw new RuntimeException("失败");
  60.                 }
  61.                 finally
  62.                 {
  63.                         try
  64.                         {
  65.                                 if(mybufr!=null)
  66.                                         mybufr.close();
  67.                         }
  68.                         catch (IOException e)
  69.                         {
  70.                                 throw new RuntimeException("读取失败");
  71.                         }
  72.                 }
  73.         }
  74. }
复制代码

作者: 杨卓儒    时间: 2012-9-6 21:44
把无限循环的代码贴上来 看看
作者: 杨震    时间: 2012-9-6 22:06
你意思是将sb作为对象的一个数据域吧,那样的话你读的数据不都存在sb里面了吗,sb装的是你所读的所有数据,不可能为空的(除非文件为空),所以MyReadLine()方法不会返回空,main里面的while也就不会结束;
但你将sb定义在MyReadLine里面,每天调用此函数,sb都为空,如果最后一次调用没有数据了,sb就为空,就是返回null,while就会结束
作者: 佟亚鹏    时间: 2012-9-7 13:35
呵呵,你的这个错误挺有意思的,StringBuilder sb = new StringBuilder();,这句代码放在方法里面是临时变量,每一次方法执行时都会new出一个新的对象,而放在外面是成员变量,new出来以后sb一直用的都是同一个对象,这两种方式有什么的不同呢?

当 StringBuilder sb = new StringBuilder() 放在你的方法 myReadLine外面作为成员变量时,当第一次执行这个方法时sb的长度已经不为空了,也就是长度不为0的情况(除非你的文件是空文件)。
注意你的 myReadLine 方法里这段代码
  1. if (sb.length() != 0)
  2.       return sb.toString();
复制代码
所以不管文件是否读完,上面这段代码都会被执行,把sb.toString()的内容返回回去,在看看main方法里你的代码
  1. String str = null;
  2. while ((str = mybufr.myReadLine()) != null) {
  3.        System.out.println(str);
  4. }
复制代码
mybufr.myReadLine() 返回的不为空,就是str不为空,所以这个条件永远都成立。。。。。。可怕的死循环到来了




作者: 佟亚鹏    时间: 2012-9-7 13:39
呵呵,你的这个错误挺有意思的,StringBuilder sb = new StringBuilder();,这句代码放在方法里面是临时变量,每一次方法执行时都会new出一个新的对象,而放在外面是成员变量,new出来以后sb一直用的都是同一个对象,这两种方式有什么的不同呢?

当 StringBuilder sb = new StringBuilder() 放在你的方法 myReadLine外面作为成员
作者: 佟亚鹏    时间: 2012-9-7 13:39
呵呵,你的这个错误挺有意思的,StringBuilder sb = new StringBuilder();,这句代码放在方法里面是临时变量,每一次方法执行时都会new出一个新的对象,而放在外面是成员变量,new出来以后sb一直用的都是同一个对象,这两种方式有什么的不同呢?

当 StringBuilder sb = new StringBuilder() 放在你的方法 myReadLine外面作为成员变量时,当第一次执行这个方法时sb的长度已经不为空了,也就是长度不为0的情况(除非你的文件是空文件)。
注意你的 myReadLine 方法里这段代码
  1. if (sb.length() != 0)
  2.       return sb.toString();
复制代码
所以不管文件是否读完,上面这段代码都会被执行,把sb.toString()的内容返回回去,在看看main方法里你的代码
  1. String str = null;
  2. while ((str = mybufr.myReadLine()) != null) {
  3.        System.out.println(str);
  4. }
复制代码
mybufr.myReadLine() 返回的不为空,就是str不为空,所以这个条件永远都成立。。。。。。可怕的死循环到来了




作者: 佟亚鹏    时间: 2012-9-7 13:45
呵呵,网速太卡了,点击了好几次,唉。。。。。。
作者: AngieFans85    时间: 2012-9-7 14:09
sb.delete(0, sb.length());
把以上的一句代码放在你的myReadLine()方法的首行就可以了,可以保证每次调用myReadLine()时,StringBuilder都没有内容,当你FileStream.java文件的内容已经读到末尾时,你若循环调用你的myReadLine()方法,就循环执行以下代码:
  1. if (line == '\n')
  2.                                 return sb.toString();
复制代码
而你的StringBuilder的内容一直为空,所以最后一次myReadLine()方法的时候,就肯定返回null了,就不会再死循环了.
作者: 张吉日    时间: 2012-9-7 14:35
谢谢各位 明白了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2