[读书笔记]《Java程序员修炼之道》

来源:互联网 发布:重庆行知教育集团 编辑:程序博客网 时间:2024/04/30 15:05

转载请注明:本文来自:mrcode markdown博客:http://www.mrcode.cn/zhuqiang/article/details/22.html

Java7新特性

  1. switch支持String
  2. 数字常量的新形式:
    1. 二进制文本:如0x10000
    2. 使用下划线分割数字常量:如 int a = 22_222
  3. 改进的异常处理
    1. 在catch的时候可以使用 | 来链接不同的异常
      一般用于异常归类,比如 格式化数字出错,计算中出错,都能归类为计算错误?
    2. final 重抛
      java
      try{
      }catch(final Exception e){ throw e}

      说实话没有看懂这个重抛的意思
  4. try-with-resources(TWR)
    作用就是把资源放在try的圆括号中,那么就能自动帮你关闭资源文件,但是api本身自带的异常你还是需要catch的。

    语法:

        try(OutputStream out = new FileOutputStream("sss")){        out.write(1);    }catch(Exception e){}

    记住try()中只能放置资源文件的返回对象的操作语句,如果没有检测到有显示的资源对象,将会提示语法错误

  5. 钻石语法
    就是创建泛型的时候,右边的new Arraylist<>()中的泛型可以省略,原文提案“为泛型实例创建而做的类型推断改进”说名称太长,从而叫做钻石语法

  6. 变参警告位置的修改
    这个感觉没有说明白,就不记录了

NIO

path

类 描述 Path 可以用来获取路径信息,访问该路径中的个元素,将路径转换为其他形式,或提取路径中的一部分。有的方法还可以匹配路径字符串以及移除路径中的冗余项 Paths 工具类,提供返回一个路径的辅助方法,比如get(String first,String…more) 和get(URI uri) FileSystem 与文件系统交互的类,无论是默认的文件系统,还是通过其统一资源标识(URI)获取的可选文件系统 FileSystems 工具类,提供各种方法,比如其中用于返回默认文件系统的FileSystems.getDefault()
        Path path = Paths.get("F:\\技术文档\\pdf");        System.out.println(path.toAbsolutePath());        System.out.println(path.toFile().exists());        System.out.println(path.getNameCount());        // TWR 自动关闭流        try(                //可以过滤到指定的文件                DirectoryStream<Path> paths = Files.newDirectoryStream(path,"Java*");            ){            for (Path path1 : paths) {                System.out.println(path1);            }        } catch (IOException e) {            e.printStackTrace();        }

遍历文件

    @Test    public void fun_ml(){        Path path = Paths.get("F:\\");        try {            //给定一个对象FileVisitor,能帮你遍历到 给定的path下的所有文件            Path fileTree = Files.walkFileTree(path, new MyFileVisitor());        } catch (IOException e) {            e.printStackTrace();        }    }    // SimpleFileVisitor 是java默认实现的一个类,可以通过扩展该类来实现对某个目录下的所有文件的操作    private class MyFileVisitor extends SimpleFileVisitor<Path>{        @Override        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {            System.out.println(file.getFileName());            System.out.println(JSON.toJSONString(attrs));            return super.visitFile(file, attrs);        }    }

nio 的文件系统

以下部分对于传统的io都进行了增强

类 描述 Files 让你轻松复制、移动、删除或处理文件的工具类,有你所需要的所有方法 WatchService 用来监视文件或目录的核心类,不管他们有没有变化

文件常用操作

一些特定系统上的权限等操作,在使用的时候再深入

    @Test    public void fun_files() throws IOException {        Path path = Paths.get("F:\\技术文档\\pdf\\demo");        // 在linux 上面创建文件目录,加上权限/*        Files.createDirectories(path,                PosixFilePermissions.asFileAttribute(                        PosixFilePermissions.fromString("rw-rw-rw")));*/        Files.createDirectories(path); //对于目录,不存在的直接创建,存在的会创建失败,但是api已经将异常过滤掉了        Path file = Paths.get(path.toString(), "text.txt");//        Files.createFile(file); //如果已经存在该文件,将会抛出异常        Path file2 = Paths.get(path.toString(), "text2.txt");//        Files.copy(file, file2); //文件复制        Path file3 = Paths.get(path.toString(), "text3.txt");//        Files.move(file2,file3); //文件移动        Files.delete(file3); //文件删除    } @Test    public void fun_file_attr() throws IOException {        Path path = Paths.get("F:\\技术文档\\pdf\\demo");        System.out.println(Files.getLastModifiedTime(path)); //获取最后一次修改时间        System.out.println(Files.readAttributes(path,"*")); //读取所有的属性    }

快速读写数据

对文件的读写操作

    @Test    public void fun_file_read(){        Path path = Paths.get("F:\\技术文档\\pdf\\demo\\text.txt");        if(!path.toFile().exists()){            System.out.println("文件不存在");        }        try(                //文件编码一定要正确,否则将读取异常                BufferedReader bufferedReader = Files.newBufferedReader(path, StandardCharsets.UTF_8);            ){            String line = null;            while ((line = bufferedReader.readLine()) != null){                System.out.println(line);            }        } catch (IOException e) {            e.printStackTrace();        }    }    @Test    public void fun_file_write(){        Path path = Paths.get("F:\\技术文档\\pdf\\demo\\text.txt");        try(              //默认是没有文件则创建一个新文件,有文件则直接覆盖//            BufferedWriter bufferedWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8);            //该模式是没有文件则报错。//            BufferedWriter bufferedWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8,StandardOpenOption.APPEND);              //通过打开模式可以快速的帮我们进行一些逻辑的设定,比如下面的组合,文件不存在则先创建            BufferedWriter bufferedWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8,                    StandardOpenOption.APPEND,                    StandardOpenOption.CREATE);        ){            bufferedWriter.write("追加文件");        } catch (IOException e) {            e.printStackTrace();        }    }

使用新的简化读取方式

上面的那种还是基于java6的读取思路,这里又进行了进一步的封装,我想是针对于小文件进行快速的读取

    @Test    public void fun_file_simpl_read() throws IOException {        // 简化读取        Path path = Paths.get("F:\\技术文档\\pdf\\demo\\text.txt");        List<String> strings = Files.readAllLines(path, StandardCharsets.UTF_8);        System.out.println(Arrays.toString(strings.toArray()));    }

文件修改通知

对于平时项目的使用来说,一般在于什么时候/时机读取文件?比如说读取一个配置文件,需要修改之后就立即加载生效类似的。就要用到文件修改通知了。

    @Test    public void fun_watchservice() {        try (                WatchService watchService = FileSystems.getDefault().newWatchService();        ) {            Path path = Paths.get("E:\\学习\\"); //只能对一个目录下的文件进行监控,有点类似zookpooer的节奏            // 在该路径上注册            WatchKey watchKey = path.register(watchService,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE); //对修改进行监控            boolean flag = true; //用于跳出循环            while(flag){                WatchKey take = watchService.take(); //如果有事                // 件触发,将会被放入服务队列中,等待处理//                List<WatchEvent<?>> watchEvents = watchKey.pollEvents(); //获取该key上的所有事件:其实没有太明白 这个WatchService 和 WatchKey的关系。所以下面的代码有点没有搞明白                List<WatchEvent<?>> watchEvents = take.pollEvents();                for (WatchEvent<?> watchEvent : watchEvents) {                    if(watchEvent.kind() == StandardWatchEventKinds.ENTRY_MODIFY){                        Object context = watchEvent.context(); //在windows中 该对象类型原型是私有的 WindowsPath类型,但是该类的实现接口也是path                        Path file = (Path)context; //返回的是针对该目录的一个相对路径                        Path child = path.resolve(file); // 不太看得懂英文说明:这里需要转换为绝对路径,这个是一个简便的转换                        List<String> strings = Files.readAllLines(child, StandardCharsets.UTF_8);                        System.out.println(Arrays.toString(strings.toArray()));                    }                }                watchKey.reset(); //重置监控key            }        } catch (IOException e) {            e.printStackTrace();        } catch (InterruptedException e) {            e.printStackTrace();        }    }

对上面代码的第一遍理解:
1. 只能对目录下的文件或则目录的一些变化监控
2. 没有搞明白这个服务的提供大体原理,所以对于api来说不太会用

SeekableByteChannel

FileChannel 是该接口
java.nio.channels
public interface SeekableByteChannel 的实现,
功能就是:在文件读取或写入时保持当前位置,比如说,下面的代码就是读取了文件最后的三个字节。

    public void fun_channel(){        Path path = Paths.get("F:\\技术文档\\pdf\\demo\\text.txt");        ByteBuffer buffer = ByteBuffer.allocate(1024);        try (                FileChannel fc = FileChannel.open(path, StandardOpenOption.READ);                ){            // fc.size 返回的是自己数,utf中一个汉字占三个字节            int read = fc.read(buffer, fc.size() - 3); // 读取该文件最后的三个字节            System.out.println(new String(buffer.array()));        } catch (IOException e) {            e.printStackTrace();        }    }

异步i/o操作

.

.

.

太难了。 等待用到的时候再学习

.

.

.

.

.

.

.

.

.


关键技术

  1. 控制反转(IoC)和依赖注入(Di)
  2. 涨或依赖注入技术为什么如此重要
  3. JSR-330如何统一了Java中的Di
  4. 常见的JSR-330注解,比如@Inject
  5. Guice3简介,JSR-330的参考实现(RI)

依赖注入

  1. 控制反转(IoC)
    好莱坞原则-“不要给我打电话,我们会打给你”
    其实就算是游戏命令行控制行为,还是改编为 界面控制行为,感觉都没能好好的理解这个控制反转的说明,有一种朦胧的理解,就是由你主动的操作,变成了由我主动操作。

  2. 依赖注入
    依赖注入是IoC的一种特定形态,是指寻找依赖项的过程不在当前执行代码的直接控制之下。一般由第三方框架帮你处理。
    可以把IocRon容器看作运行时环境。Java中为依赖注入提供的容器有Guice、Spring和PicoContainer

注: 显式的创建一个对象,并把该对象注入到另外一个服务中去; 这个过程也算是注入。 不过把这个过程交给了第三方框架去做,也就是Ioc容器和Di依赖注入

Di的好处

好处 描述 例子 松耦合 代码不再紧紧的绑定到依赖项的创建上。如果能与面向接口编程的技术相结合,意味着你的代码再也不用紧紧的绑定到依赖项的具体实现上了 易测性 作为松耦合的延伸,还有个特殊的用列值得一提。为了测试,可以把测试替身(后面章节会记录)作为依赖项注入到对象中 更强的内聚性 你的代码可以专注于执行自己的任务,不用为了载入和配置依赖而分心。这样还能增强代码的可读性 你的dao对象可以专注于查询工作,不用考虑JDBC驱动的细节 可重用组件 作为松耦合的延伸,你的代码应用范围会更加宽广,那些可以提供自己特定实现的用户都可以使用你的代码 更轻盈的代码 你的代码不再需要跨层传递依赖项,而是可以在需要依赖项的地方直接注入 你不再需要把jdbc驱动的细节信息从service类往下传递,而是在真正需要它的dao中直接注入这个驱动实例

Java中标准化DI

从Jee6开始构建了自己的依赖注入体系(CDI),由JSR-299规范确定。JSR-299构建在JSR-330基础之上。javax.inject jdk5.6.7都支持该标准。

javax.inject 包:
指明了获取对象的一种方式,与传统的构造方法、工厂模式和服务定位器模式(比如JNDI)等相比,这种方式的可重用性、可测试线和可维护性都得到了极大提升。这种方式称为依赖注入,对于大多数非小型应用程序都很有帮助。

一个接口:Provider接口
5个注解类型:@Inject、@Qualifier、@Named、@Scope、@Singleton

这一章的讲解貌似都没有什么干货,直接忽略


这本书结束: 除了让我对于nio有了一个基础的了解之外,其他的章节可以说是没有什么亮点的。 至少让我感觉是这样的。
这本书总的来说,不推荐看,讲的东西都太浅了,有的直接扒拉概念,看完这本书,唯一的感觉就是知道了点nio的基础知识

0 0
原创粉丝点击