Java

Java 5 新特性

Java5-7新特性 - 图1

1、泛型

泛型本质是参数化类型,解决不确定具体对象类型的问题。

  1. List<String> strList=new ArrayList<String>();

2、增强循环(for-each)

for-each循环简化了集合的遍历。

  1. String [] str = {"Hello","World","Fcant"};
  2. for (String temp:str) {
  3. System.out.println(temp);
  4. }

3、自动封箱拆箱

  • 自动装箱:就是将基本数据类型自动转换成对应的包装类。
  • 自动拆箱:就是将包装类自动转换成对应的基本数据类型。

包装类型有:Integer,Double,Float,Long,Short,Character和Boolean

  1. Integer i =666; //自动装箱
  2. int a= i; //自动拆箱

4、枚举

关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这就是枚举类型。

  1. enum SeasonEnum {
  2. SPRING,SUMMER,FALL,WINTER;
  3. }

5、可变参数

在定义方法参数的时候不确定定义多少个,就可以定义为「可变参数」,它本质上是一个「数组」

  1. public static void main(String[] args) throws Exception {
  2. String [] str = {"Hello","World","Fcant"};
  3. testVarargs(str);
  4. String str1 = "Hello,World";
  5. testVarargs(str1);
  6. }
  7. //可变参数String... args
  8. private static void testVarargs(String... args) {
  9. for (String arg : args) {
  10. System.out.println(arg);
  11. }
  12. }

6、注解

可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.SOURCE)
  3. public @interface Override {
  4. }

7、静态导入

通过import static类,就可以使用类里的静态变量或方法。看一下例子哈~

  1. import static java.lang.System.out; //静态导入System类的静态变量out
  2. public class Test {
  3. public static void main(String[] args) throws Exception {
  4. String str1 = "Hello,World";
  5. System.out.println(str1); //常规写法
  6. out.println(str1); //静态导入,可以直接使用out输出
  7. }
  8. }

8、线程并发库(JUC)

JDK5 丰富了线程处理功能,java.util.concurrent包提供了以下的类、接口:

  • 线程池:ExecutorService接口
  • 线程护斥:Lock 类
  • 线程通信:Condition接口
  • 同步队列:ArrayBlockingQueue类
  • 同步集合:ConcurrentHashMap类

Java 6 新特性

Java5-7新特性 - 图2

1、Desktop类和SystemTray类

JDK 6在java.awt包下,新增了两个类:Desktop类和SystemTray

  • 「Desktop类」:用来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端发邮件等
  • 「SystemTray类」:用来在系统托盘区创建一个托盘程序,如果在微软的Windows上,它被称为“任务栏”状态区域。
  1. //获取Desktop实例
  2. Desktop desktop = Desktop.getDesktop();
  3. desktop.browse(URI.create("https://www.google.com"));

2、使用JAXB2来实现对象与XML之间的映射

JAXB,即Java Architecture for XML Binding,可以实现对象与XML之间的映射,常用注解如下:

  • @XmlRootElement:注解在类上面,对应xml的跟元素,使用name属性定义根节点的名称。
  • @XmlElement:指定一个字段或get/set方法映射到xml的节点,使用name属性定义这个根节点的名称。
  • @XmlAttribute:将JavaBean对象的属性映射为xml的属性,使用name属性为生成的xml属性指定别名。
  • @XmlAccessorType:定义映射这个类中的何种类型都需要映射到xml。
  • @XmlSchema:将包映射到XML名称空间

「举个例子」

  1. public class JAXB2XmlTest {
  2. public static void main(String[] args) throws JAXBException, IOException {
  3. List<Singer> list = new ArrayList<>();
  4. list.add(new Singer("jay", 8));
  5. list.add(new Singer("eason", 10));
  6. SingerList singerList = new SingerList();
  7. singerList.setSingers(list);
  8. String str = JAXB2XmlTest.beanToXml(singerList, SingerList.class);
  9. String path = "C:\\jay.txt";
  10. BufferedWriter bfw = new BufferedWriter(new FileWriter(new File(path)));
  11. bfw.write(str);
  12. bfw.close();
  13. }
  14. private static String beanToXml(Object obj, Class<?> load) throws JAXBException {
  15. JAXBContext context = JAXBContext.newInstance(load);
  16. Marshaller marshaller = context.createMarshaller();
  17. marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  18. marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");
  19. StringWriter writer = new StringWriter();
  20. marshaller.marshal(obj,writer);
  21. return writer.toString();
  22. }
  23. }
  24. public class Singer {
  25. private String name;
  26. private int age;
  27. public Singer(String name, int age) {
  28. this.name = name;
  29. this.age = age;
  30. }
  31. @XmlAttribute(name="name")
  32. public String getName() {
  33. return name;
  34. }
  35. public void setName(String name) {
  36. this.name = name;
  37. }
  38. @XmlAttribute(name="age")
  39. public int getAge() {
  40. return age;
  41. }
  42. public void setAge(int age) {
  43. this.age = age;
  44. }
  45. }
  46. @XmlRootElement(name="list")
  47. public class SingerList {
  48. private List<Singer> singers;
  49. @XmlElement(name="singer")
  50. public List<Singer> getSingers() {
  51. return singers;
  52. }
  53. public void setSingers(List<Singer> singers) {
  54. this.singers = singers;
  55. }
  56. }

「运行效果:」

  1. <?xml version="1.0" encoding="GBK" standalone="yes"?>
  2. <list>
  3. <singer age="8" name="jay"/>
  4. <singer age="10" name="eason"/>
  5. </list>

3、轻量级 Http Server API

JDK 6中提供了简单的Http Server API,可以构建嵌入式Http服务器,同时支持Http和Https协议。HttpServer会调用HttpHandler实现类的回调方法来处理客户端请求,这里用户只需实现HttpHandler接口就可以了。

  1. /**
  2. * 根据Java提供的API实现Http服务器
  3. */
  4. public class MyHttpServer {
  5. /**
  6. * @param args
  7. * @throws IOException
  8. */
  9. public static void main(String[] args) throws IOException {
  10. //创建HttpServer服务器
  11. HttpServer httpServer = HttpServer.create(new InetSocketAddress(8080), 10);
  12. //将 /jay请求交给MyHandler处理器处理
  13. httpServer.createContext("/", new MyHandler());
  14. httpServer.start();
  15. }
  16. }
  17. public class MyHandler implements HttpHandler {
  18. public void handle(HttpExchange httpExchange) throws IOException {
  19. //请求头
  20. Headers headers = httpExchange.getRequestHeaders();
  21. Set<Map.Entry<String, List<String>>> entries = headers.entrySet();
  22. StringBuffer response = new StringBuffer();
  23. for (Map.Entry<String, List<String>> entry : entries){
  24. response.append(entry.toString() + "\n");
  25. }
  26. //设置响应头属性及响应信息的长度
  27. httpExchange.sendResponseHeaders(200, response.length());
  28. //获得输出流
  29. OutputStream os = httpExchange.getResponseBody();
  30. os.write(response.toString().getBytes());
  31. os.close();
  32. }
  33. }

4、插入式注解处理API

JDK 6提供了插入式注解处理API,可以让定义的注解在编译期而不是运行期生效,从而可以在编译期修改字节码。lombok框架就是使用该特性来实现的,Lombok通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equalshashcodetoString等方法,大大简化了代码的开发。

5、STAX

STAX,是JDK6中一种处理XML文档的API。

  1. public class STAXTest {
  2. public static void main(String[] args) throws Exception {
  3. XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
  4. XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(new FileInputStream("C:\\jay.xml"));
  5. XMLEvent event = null;
  6. StringBuffer stringBuffer = new StringBuffer();
  7. while (xmlEventReader.hasNext()) {
  8. event = xmlEventReader.nextEvent();
  9. stringBuffer.append(event.toString());
  10. }
  11. System.out.println("xml文档解析结果:");
  12. System.out.println(stringBuffer);
  13. }
  14. }

「运行结果:」

  1. xml文档解析结果:
  2. <?xml version="1.0" encoding='GBK' standalone='yes'?><list>
  3. <singer name='jay' age='8'></singer>
  4. <singer name='eason' age='10'></singer>
  5. </list>ENDDOCUMENT

6、Common Annotations

Common annotations原本是Java EE 5.0(JSR 244)规范的一部分,现在SUN把它的一部分放到了Java SE 6.0中。随着Annotation元数据功能加入到Java SE 5.0里面,很多Java 技术都会用Annotation部分代替XML文件来配置运行参数。

以下列举Common Annotations 1.0里面的几个Annotations:

  • @Generated:用于标注生成的源代码
  • @Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式 。
  • @Resources:同时标注多个外部依赖,容器会把所有这些外部依赖注入
  • @PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct
  • @PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为PreDestroy

    7、Compiler API

    javac编译器可以把.java的源文件编译为.class文件,JDK 6的新特性Compiler API(JSR 199)也可以动态编译Java源文件。
    1. public class CompilerApiTest {
    2. public static void main(String[] args) throws Exception {
    3. JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
    4. StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null,null,null);
    5. Iterable<? extends JavaFileObject> javaFileObjects = standardJavaFileManager.getJavaFileObjects("C:\\Singer.java");
    6. javaCompiler.getTask(null, standardJavaFileManager, null, null, null, javaFileObjects).call();
    7. standardJavaFileManager.close();
    8. }
    9. }
    运行结果:会在C目录生成Singer.class文件

    8、对脚本语言的支持(如: ruby, groovy, javascript)

    JDK6增加了对脚本语言的支持(JSR 223),原理是将脚本语言编译成字节码,这样脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等。JDK6实现包含了一个基于Mozilla Rhino的 脚本语言引擎,因此可以支持javascript,当然JDK也支持ruby等其他语言
    1. public class JavaScriptTest {
    2. public static void main(String[] args) throws Exception {
    3. ScriptEngineManager factory = new ScriptEngineManager();
    4. ScriptEngine engine = factory.getEngineByName("JavaScript");
    5. String script;
    6. try {
    7. script = "print('Hello')";
    8. engine.eval(script);// 执行脚本
    9. }catch (Exception e) {
    10. e.printStackTrace();
    11. }
    12. }
    13. }
    14. //output
    15. Hello

    Java 7 新特性

    Java5-7新特性 - 图3

    1、switch 支持String字符串类型。

    1. String singer = "jay";
    2. switch (singer) {
    3. case "jay" :
    4. System.out.println("周杰伦");
    5. break;
    6. case "eason" :
    7. System.out.println("陈奕迅");
    8. break ;
    9. default :
    10. System.out.println("其他");
    11. break ;
    12. }

    2、try-with-resources,资源自动关闭

    JDK 7 之前:
    1. BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt"));
    2. try {
    3. return br.readLine();
    4. } finally {
    5. br.close();
    6. }
    JDK 7 之后:
    1. /*
    2. * 声明在try括号中的对象称为资源,在方法执行完毕后会被自动关闭
    3. */
    4. try (BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt")) {
    5. return br.readLine();
    6. }

    3、整数类型如(byte,short,int,long)能够用二进制来表示

    1. //0b或者0B表示二进制
    2. int a = 0b010;
    3. int b = 0B010;

    4、数字常量支持下划线

    1. int a = 11_11;//a的值为1111,下划线不影响实际值,提升可读性

    5、泛型实例化类型自动推断,即”<>”

    JDK 7 之前:
    1. Map<String, List<String>> map = new HashMap<String, List<String>>();
    JDK 7之后:
    1. //不须声明类型,自动根据前面<>推断其类型
    2. Map<String, List<String>> map = new HashMap<>();

    6、一个catch中捕获多个异常类型,用(|)分隔开

    JDK 7之前
    1. try{
    2. //do something
    3. } catch (FirstException e) {
    4. logger.error(e);
    5. } catch (SecondException e) {
    6. logger.error(ex);
    7. }
    JDk 7之后
    1. try{
    2. //do something
    3. } catch (FirstException | SecondException e) {
    4. logger.error(e);
    5. }

    7、增强的文件系统

    Java7 提供了全新的NIO2.0 API,方便文件管理的编码。如,可以在java.nio.file包下使用Path、Paths、Files、WatchService等常用类型。
    1. Path path = Paths.get("C:\\jay\\七里香.txt"); //创建Path对象
    2. byte[] bytes= Files.readAllBytes(path); //读取文件
    3. System.out.println(path.getFileName()); //获取当前文件名称
    4. System.out.println(path.toAbsolutePath()); // 获取文件绝对路径
    5. System.out.println(new String(bytes, "utf-8"));

    8、Fork/join 框架

    Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。Java5-7新特性 - 图4
    Fork/join计算1-1000累加值:
    1. public class ForkJoinPoolTest {
    2. private static final Integer DURATION_VALUE = 100;
    3. static class ForkJoinSubTask extends RecursiveTask<Integer>{
    4. // 子任务开始计算的值
    5. private Integer startValue;
    6. // 子任务结束计算的值
    7. private Integer endValue;
    8. private ForkJoinSubTask(Integer startValue , Integer endValue) {
    9. this.startValue = startValue;
    10. this.endValue = endValue;
    11. }
    12. @Override
    13. protected Integer compute() {
    14. //小于一定值DURATION,才开始计算
    15. if(endValue - startValue < DURATION_VALUE) {
    16. System.out.println("执行子任务计算:开始值 = " + startValue + ";结束值 = " + endValue);
    17. Integer totalValue = 0;
    18. for (int index = this.startValue; index <= this.endValue; index++) {
    19. totalValue += index;
    20. }
    21. return totalValue;
    22. } else {
    23. // 将任务拆分,拆分成两个任务
    24. ForkJoinSubTask subTask1 = new ForkJoinSubTask(startValue, (startValue + endValue) / 2);
    25. subTask1.fork();
    26. ForkJoinSubTask subTask2 = new ForkJoinSubTask((startValue + endValue) / 2 + 1 , endValue);
    27. subTask2.fork();
    28. return subTask1.join() + subTask2.join();
    29. }
    30. }
    31. }
    32. public static void main(String[] args) throws ExecutionException, InterruptedException {
    33. // Fork/Join框架的线程池
    34. ForkJoinPool pool = new ForkJoinPool();
    35. ForkJoinTask<Integer> taskFuture = pool.submit(new ForkJoinSubTask(1,1000));
    36. Integer result = taskFuture.get();
    37. System.out.println("累加结果是:" + result);
    38. }
    39. }
    运行结果:
    1. ...
    2. 执行子任务计算:开始值 = 189;结束值 = 250
    3. 执行子任务计算:开始值 = 251;结束值 = 313
    4. 执行子任务计算:开始值 = 314;结束值 = 375
    5. 执行子任务计算:开始值 = 376;结束值 = 438
    6. 执行子任务计算:开始值 = 439;结束值 = 500
    7. 执行子任务计算:开始值 = 501;结束值 = 563
    8. 执行子任务计算:开始值 = 564;结束值 = 625
    9. 执行子任务计算:开始值 = 626;结束值 = 688
    10. 执行子任务计算:开始值 = 689;结束值 = 750
    11. 执行子任务计算:开始值 = 751;结束值 = 813
    12. 执行子任务计算:开始值 = 814;结束值 = 875
    13. 执行子任务计算:开始值 = 876;结束值 = 938
    14. 执行子任务计算:开始值 = 939;结束值 = 1000
    15. 累加结果是:500500