扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
java.nio.channels.FileLock。
import java.io.*;
import java.util.Iterator;
public class TextFile implements Iterable<String> {
File f;
String charsetName;
public TextFile(File f, String charsetName)
throws IOException
{
this.f = f;
this.charsetName = charsetName;
if (!f.exists())
throw new FileNotFoundException(f.getPath());
if (!f.canRead())
throw new IOException("Can't read: " +
f.getPath());
}
public Iterator<String> iterator() {
try {
return new TextFileIterator(f, charsetName);
}
catch(IOException e) {
throw new IllegalArgumentException(e);
}
}
static class TextFileIterator
implements Iterator<String>
{
BufferedReader in;
String nextline;
boolean closed = false;
public TextFileIterator(File f, String charsetName)
throws IOException
{
InputStream fis = new FileInputStream(f);
Reader isr =
new InputStreamReader(fis, charsetName);
in = new BufferedReader(isr);
getNextLine();
}
public boolean hasNext() {
return nextline != null;
}
public String next() {
String returnValue = nextline;
getNextLine();
return returnValue;
}
public void remove() {
throw new UnsupportedOperationException();
}
void getNextLine() {
if (!closed) {
try { nextline = in.readLine(); }
catch(IOException e) {
throw new IllegalArgumentException(e);
}
if (nextline == null) {
try { in.close(); }
catch(IOException ignored) {}
closed = true;
}
}
}
}
}
Iterable是到目前为止最重要的新能力接口,但是其它的也是非常的漂亮。接下来,我们碰到java.lang.Appendable。一个Appendable对象可以追加字符或字符序列(或者一个字符序列的子序列)。实现者包括StringBuffer和StringBuilder(如果你还没有听说过它,一定要看一看),Writer(及其子类),PrintStream,还有java.nio.CharBuffer。将可追加性从这些类中分离出来成为Appendable接口,使得新的java.util.Formatter类更强大:它能将文本格式化为任何可追加的对象,包括你自己的实现。(练习留给读者:你能否将上面的TextFile类变得既可迭代又可追加么?)。
java.lang.Readable接口和Appendable相反:一个可读对象可以将字符传输给给定的CharBuffer。java.io.Reader和它的全部子类都是可读的(当然了),CharBuffer本身也一样。就像Appendable是为了java.util.Formatter的利益而创造,Readable是为了java.util.Scanner的利益而创造。(Java5.0增加了Scanner,连同Formatter。这是Java对C的scanf()函数的适应,但是它(Scanner)不像Formatter之对应于printf()的关系那样密切。)
我想讨论的最后两个能力接口是java.io.Closeable和java.io.Flushable。如它们的名字暗示的,它们趋向于被任何类实现,通过一个close()或者flush()方法。Closeable被所有的输入和输出流类,RandomAccessFile和Formatter实现。Flushable被输出流类和Formatter实现。这些接口也是为了Formatter类的利益而定义。注意,Appendable对象(像StringBuilder)不总是可关闭或者可冲刷(flushable)。通过将可关闭性和可冲刷性分解出来成为这些接口,Formatter的close()和flush()方法能够决定它们操作的Appendable对象是否需要被关闭或被冲刷。(Java5.0还增加了第六个能力接口,并且它也是有关Formatter类的。那些想要控制它们的实例怎样被格式化的类可以实现java.util.Formattable接口。然而这个接口的API是难用的,我不想谈论它。)
@Override
毫无疑问,你已经听说过能用元数据标注Java5.0的类型和方法。但是你可能不熟悉增加到java.lang的标准标注类型。我喜欢的第四个特性就是java.lang.Override标注。当你写一个方法准备覆盖另一个的方法时,用@Override来标注它,这样编译器会进行检查来确保你确实,实际上,覆盖了你想覆盖的方法。
如果你拼写错了方法名字或者弄错了方法参数,那么你实际上并没有覆盖那个你认为你覆盖了的方法。这样就造成了一个如果不用@Override很难捕捉的臭虫。我所以知道是因为我的关于Java1.4的新API特性的文章就讲到了这个臭虫,并且这个错误至少有一年一直没被检测到(至少没有被报告)。在那篇文章中,你可以在第一页结尾看到我犯的错误。那篇文章现在包含一个链接到我的博客入口,在那里我改正了这个臭虫并且在代码中增加了@Override声明。
MatchResult
我喜欢的Java5.0的最后一个特性是java.util.regex.MatchResult。对于用于正则表达式的模式/匹配API我从来没有真正非常满意。Java5.0增加的MatchResult在让我大大地更加满意。当使用一个不太平凡的模式(Pattern),每次调用匹配者(Matcher)的find()方法会生成许多状态:开始位置,结束位置,匹配的文本,同时还有模式的开始,结束,每个子表达式的文本。在Java5.0以前,你只能从Matcher获取它们,通过在调用find()后再调用start(),end(),还有group(),如果需要的话。
然而,到了Java5.0,你可以只调用toMatchResult()来获取MatchResult对象再获取全部的状态,MatchResult对象可以保存并且可以以后再检查。MatchResult像Matcher一样有start(),end(),以及group()方法,并且,实际上,Matcher现在实现了MatchResult。
这里是一个有用的返回MatchResult的方法:
public static List<MatchResult> findAll(Pattern pattern,
CharSequence text) {
List<MatchResult> results =
new ArrayList<MatchResult>();
Matcher m = pattern.matcher(text);
while(m.find()) results.add(m.toMatchResult());
return results;
}
还有使用这个方法的代码:
List<MatchResult> results = findAll(pattern, text);
for(MatchResult r : results) {
System.out.printf("Found '%s' at (%d,%d)%n",
r.group(), r.start(), r.end());
}
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者