java7的新特性

1.switch语法中引入String类型

  • switch语句是一种高效的多路语句,可以省去很多繁杂的if语句,在java7以前,它所支持的数据类型只有byte,char,short,int这四种基本类型及其包装类,现在则可以直接对String类型做判断,如下:
        String str = "hello";
        switch (str) {
            case "world":
                System.out.println(" this is not true!");
                break;
            case "hello":
                System.out.println(" this is true!");
                break;
            default:
                System.out.println(str);

2.更强的数值文本表示

  • 数字常量(如int类型)可以用二进制表示
        //在jdk7以前,如果你想将二进制的表示的数转成int 你需要这么做,不仅繁琐,还浪费性能
        int num = Integer.parseInt("10001",2);

        //jdk7则提供如下方式,更加简单明了
        byte b = 0b1010101;
        Integer i = 0b111111111;
        long l = 0b00000;
  • 整形常量中可使用下划线
    人在处理长段的数据时候会在中间添加分隔符从而加强可读性,比如用400-800-8866表示一个电话号码,用1,030,839表示1030839的金额数目等。但是在代码中却又不能用“-”或“,”作为分隔符,因为会引起歧义,所以使用“_”来满足需求。
        Byte b2 = 0b0_1_0_1;
        int i2 = 342_231_32_1;
        long l2 = 1_2_3_4_5;

3.异常处理机制的增强

  • multicatch
//jdk7以前我们捕获异常会这么做
    public Resource getResource(String fileName){
            Resource resource = null;
            try{
                String text = getText(fileName);
                resource = verifyResource(text);
            }catch (FileNotFoundException e){
                e.printStackTrace();
            }catch (IOException e){
                e.printStackTrace();
            }catch (ConfigurationException e){
                e.printStackTrace();
            }catch (ParseException e){
                e.printStackTrace();
            }
        return  resource;
    }

事实上,上述捕获的四个异常可以分为两类,一类是文件可以读取,但是文件错误或者丢失的情况,一类是文件无法读取的情况,在jdk7中我们可以这么做:

    public Resource getResource2(String fileName){
        Resource resource = null;
        try{
            String text = getText(fileName);
            resource = verifyResource(text);
        }catch (FileNotFoundException| ConfigurationException| ParseException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
        return  resource;
    }
  • final重抛
    在以前的版本中我们通常会见到如下代码:
        try{
            doSomethingWithSqlException();
            doSomethingWithIoException();
        }catch (Exception e){
            throw e;
        }

这会强制把要抛出的异常转化为Exception,从而掩盖真实的异常类型。
而在jdk7中我们可以:

        try{
            doSomethingWithSqlException();
            doSomethingWithIoException();
        }catch (final Exception e){
            throw e;
        }

只需要添加一个关键字final就可以使得抛出的异常就是真实运行情况下所产生的异常类型,如上述SQLException或IOException其中一种。

4.try-with-resources

没人能在需要手写关闭资源的代码片段时能保证绝对正确,在以前我们手写一个文件读写的代码会这么做:

        InputStream is = null;
        FileOutputStream fos = null;
        try {
            is = getInputStream();
            fos = getOutputStream(fileName);
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = is.read(buff)) > -1) {
                fos.write(buff, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

但是最后结尾需要手动关闭输入输出流稍显繁琐,还容易出错,好在java7通过编译器帮我们实现了这种改进,从而降低了代码出错的风险:

        try(InputStream is = getInputStream();FileOutputStream fos = getOutputStream(fileName)) {

            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = is.read(buff)) > -1) {
                fos.write(buff, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

这样看上去不仅简洁,而且降低了我们粗心大意的风险。
但是要使用这种功能也是有条件的,那就是需要关闭的对象必须实现Cloaseable接口:

public interface Closeable extends AutoCloseable {

    /**
     * Closes this stream and releases any system resources associated
     * with it. If the stream is already closed then invoking this
     * method has no effect.
     *
     * @throws IOException if an I/O error occurs
     */
    public void close() throws IOException;
}

5.钻石语法(增强泛型推断)

针对java中泛型定义和实例太过繁琐的问题,java7做了改进,从而减少了代码量。

        //在jdk7以前我们需要这么定义一长串
        Map<String,Map<Integer,List<Object>>> maps1 = new HashMap<String,Map<Integer,List<Object>>>();
        //在jdk7以后我们只需要这么做
        Map<String,Map<Integer,List<Object>>> maps2 = new HashMap<>();

6.java7中的NIO.2

很多Java开发者还是不知道怎么充分利用NIO,更少的人知道在Java SE 7里引入了更新的输入/输出 API(NIO.2)
Java AIO(NIO.2)----异步非阻塞IO:
在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。
鉴于这节内容较多,我会单独写一篇文章来介绍其原理和用法。

7.JSR292与InvokeDynamic

JSR 292: Supporting Dynamically Typed Languages on the JavaTM Platform,支持在JVM上运行动态类型语言。在字节码层面支持了InvokeDynamic。

  • 方法句柄MethodHandle

public class ThreadPoolManager {
private final ScheduledExecutorService stpe = Executors
.newScheduledThreadPool(2);
private final BlockingQueue<WorkUnit> lbq;
public ThreadPoolManager(BlockingQueue<WorkUnit> lbq_) {
lbq = lbq_;
}
public ScheduledFuture<?> run(QueueReaderTask msgReader) {
msgReader.setQueue(lbq);
return stpe.scheduleAtFixedRate(msgReader, 10, 10, TimeUnit.MILLISECONDS);
}
private void cancel(final ScheduledFuture<?> hndl) {
stpe.schedule(new Runnable() {
public void run() {
hndl.cancel(true);
}
}, 10, TimeUnit.MILLISECONDS);
}
/**
* 使用传统的反射api
/
public Method makeReflective() {
Method meth = null;
try {
Class<?>[] argTypes = new Class[]{ScheduledFuture.class};
meth = ThreadPoolManager.class.getDeclaredMethod(“cancel”, argTypes);
meth.setAccessible(true);
} catch (IllegalArgumentException | NoSuchMethodException
| SecurityException e) {
e.printStackTrace();
}
return meth;
}
/
*
* 使用代理类
* @return
/
public CancelProxy makeProxy() {
return new CancelProxy();
}
/
*
* 使用Java7的新api,MethodHandle
* invoke virtual 动态绑定后调用 obj.xxx
* invoke special 静态绑定后调用 super.xxx
* @return
/
public MethodHandle makeMh() {
MethodHandle mh;
MethodType desc = MethodType.methodType(void.class, ScheduledFuture.class);
try {
mh = MethodHandles.lookup().findVirtual(ThreadPoolManager.class,
“cancel”, desc);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw (AssertionError) new AssertionError().initCause(e);
}
return mh;
}
public static class CancelProxy {
private CancelProxy() {
}
public void invoke(ThreadPoolManager mae_, ScheduledFuture<?> hndl_) {
mae_.cancel(hndl_);
}
}
}
调用invoke
public class ThreadPoolMain {
/
*
* 如果被继承,还能在静态上下文寻找正确的class
*/
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private ThreadPoolManager manager;
public static void main(String[] args) {
ThreadPoolMain main = new ThreadPoolMain();
main.run();
}
private void cancelUsingReflection(ScheduledFuture<?> hndl) {
Method meth = manager.makeReflective();
try {
System.out.println(“With Reflection”);
meth.invoke(hndl);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
private void cancelUsingProxy(ScheduledFuture<?> hndl) {
CancelProxy proxy = manager.makeProxy();
System.out.println(“With Proxy”);
proxy.invoke(manager, hndl);
}
private void cancelUsingMH(ScheduledFuture<?> hndl) {
MethodHandle mh = manager.makeMh();
try {
System.out.println(“With Method Handle”);
mh.invokeExact(manager, hndl);
} catch (Throwable e) {
e.printStackTrace();
}
}
private void run() {
BlockingQueue<WorkUnit> lbq = new LinkedBlockingQueue<>();
manager = new ThreadPoolManager(lbq);
final QueueReaderTask msgReader = new QueueReaderTask(100) {
@Override
public void doAction(String msg_) {
if (msg_ != null)
System.out.println("Msg recvd: " + msg_);
}
};
ScheduledFuture<?> hndl = manager.run(msgReader);
cancelUsingMH(hndl);
// cancelUsingProxy(hndl);
// cancelUsingReflection(hndl);
}
}

8.Path接口(重要接口更新)

Path
public class PathUsage {
public void usePath() {
Path path1 = Paths.get(“folder1”, “sub1”);
Path path2 = Paths.get(“folder2”, “sub2”);
path1.resolve(path2); //folder1\sub1\folder2\sub2
path1.resolveSibling(path2); //folder1\folder2\sub2
path1.relativize(path2); //…\folder2\sub2
path1.subpath(0, 1); //folder1
path1.startsWith(path2); //false
path1.endsWith(path2); //false
Paths.get(“folder1/./…/folder2/my.text”).normalize(); //folder2\my.text
}
/**
* @param args the command line arguments
/
public static void main(String[] args) {
PathUsage usage = new PathUsage();
usage.usePath();
}
}
DirectoryStream
public class ListFile {
public void listFiles() throws IOException {
Path path = Paths.get("");
try (DirectoryStream stream = Files.newDirectoryStream(path, "
.*")) {
for (Path entry: stream) {
//使用entry
System.out.println(entry);
}
}
}
/**
* @param args the command line arguments
/
public static void main(String[] args) throws IOException {
ListFile listFile = new ListFile();
listFile.listFiles();
}
}
Files
public class FilesUtils {
public void manipulateFiles() throws IOException {
Path newFile = Files.createFile(Paths.get(“new.txt”).toAbsolutePath());
List content = new ArrayList();
content.add(“Hello”);
content.add(“World”);
Files.write(newFile, content, Charset.forName(“UTF-8”));
Files.size(newFile);
byte[] bytes = Files.readAllBytes(newFile);
ByteArrayOutputStream output = new ByteArrayOutputStream();
Files.copy(newFile, output);
Files.delete(newFile);
}
/
*
* @param args the command line arguments
/
public static void main(String[] args) throws IOException {
FilesUtils fu = new FilesUtils();
fu.manipulateFiles();
}
}
WatchService
public class WatchAndCalculate {
public void calculate() throws IOException, InterruptedException {
WatchService service = FileSystems.getDefault().newWatchService();
Path path = Paths.get("").toAbsolutePath();
path.register(service, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key = service.take();
for (WatchEvent<?> event : key.pollEvents()) {
Path createdPath = (Path) event.context();
createdPath = path.resolve(createdPath);
long size = Files.size(createdPath);
System.out.println(createdPath + " ==> " + size);
}
key.reset();
}
}
/
*
* @param args the command line arguments
*/
public static void main(String[] args) throws Throwable {
WatchAndCalculate wc = new WatchAndCalculate();
wc.calculate();
}
}

8.fork/join计算框架

Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

该框架为Java8的并行流打下了坚实的基础

小结

修改语言有时候是非常困难的一件事,若是通过类库修改特性要相对简单一些,但并非所有特性都能通过类库来实现,面对挑战的时候,编程语言的设计师们总会做出一些更轻微和保守的调整,以保证不矫枉过正取得不利的效果。但不论如何,我都希望,java能一直这样充满活力的走下去。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值