跳至主要內容

Java 全版本新特性

大约 12 分钟

Java 全版本新特性

Java 1.0

1996-01-23 Oak(橡树)

初代版本,伟大的一个里程碑,但是是纯解释运行,使用外挂JIT,性能比较差,运行速度慢。

  • 自带类库: Java 1.0 自带了一些基本类库和方法,如java.lang, java.util, java.io包等。

  • 多线程支持:Java 1.0 支持多线程,提供了java.lang.Thread类和相关方法。

  • 网络编程: Java 1.0 为网络编程提供了基本的支持,包括网络I/O和套接字。

  • 安全性:Java 1.0 提供了安全性机制,如类加载器、安全管理器等,保证代码安全。

Java 1.1

1997-02-19 major.minor 45

  • 内部类: Java 1.1引入了内部类,可以在一个类的内部定义另一个类。
  • JDBC: Java 1.1 开始提供JDBC支持
  • RMI(Remote Method Invocation):
  • 反射: 仅用于内省
  • Java Bean
  • AWT: Java 1.1 开始引入AWT,提供了图形用户界面开发支持。
  • 加强垃圾回收机制

Java 1.2

1998-12-08 Playground(操场) major.minor 46

  • 集合框架: Java 1.2 引入了Collections框架,提供了一组接口和实现类来操作和存储对象集合
  • JIT(Just In Time) 编译器
  • Swing 1.0 : Java1.2 提供的全新的GUI工具包。
  • JDBC优化: 引入可滚动结果集,BLOB,CLOB,批量更新和用户自定义类型。
  • Java插件

Java 1.3

2000-05-08 Kestrel(红隼) major.minor 47

  • JNDI(Java Naming and Directory Interface): Java 1.3 的JNDI是的Java应用程序可以访问命名和目录服务
  • J2EE: Java 1.3 引入了J2EE规范,提供了一套完整的企业级应用程序开发方案。
  • 全方面的优化和增强

Java 1.4

2002-02-13 Merlin(隼) major.minor 48

  • XML处理

    针对XML处理的JavaTM API 已经被添加到Java 2平台。它通过一套标准的Java平台API提供对XML的基本处理的支持

  • Logging API

    Logging API为程序提供了一种报告其行为的机制。它提供了一种在现场部署应用程序后打开和关闭日志消息的方法,极大地帮助了应用程序的维护。

  • JDBC 3.0 API [提升]

  • 断言

    它用于对程序进行调试的,对于执行结构的判断,而不是对于业务流程的判断。(可以理解为一个if ()语句,如果满足断言就执行程序,如果不满足则抛错误)

    语法:

    • assert condition 这里condition是一个必须为真(true)的表达式。如果表达式的结果为true,那么断言为真,则不会有任何行动;如果表达式为false,则断言失败,这时会抛出一个AssertionError。
    • asser condition:expr 这里condition是一个必须为真(true)的表达式。冒号后跟的是一个表达式,通常用于断言失败后的提示信息,简而言之是一个传到AssertionError构造函数的值,如果断言失败,该值被转化为它对应的字符串,并显示出来。
    //当变量name为null时,将会抛出一个AssertionError,并输出错误信息
    public class TestAssert{
        public static void main(String[] args){
            String name = "xiaoming";
            assert (name!=null):"name为空";
            System.out.println(name);
        }
    }
    
  • Preferences API

    用于将首选项存储到特定于操作系统的后端。在Windows等操作系统上,首选项存储在操作系统级别的注册表中,对于非Windows环境,它们可以存储在其他注册表类存储中,也可以存储在简单的XMLopen in new window文件中

    Preferences root = Preferences.userRoot();
    root.putInt( "age", 10 );
    int fontSize = prefs.getInt( "age", 1 );//这里的1是默认值,当没有获得age的值会返回它
    //更多例子见:https://www.ibm.com/developerworks/cn/java/j-prefapi/index.html
    
  • 链式异常处理

    链式异常允许将一个异常与另一个异常联系起来,即一个异常描述了另一个异常的原因。例如,考虑一种情况,即由于试图除以零而导致抛出ArithmeticException,但实际的异常原因是导致除数为零的I / O错误。该方法只会向调用者抛出ArithmeticException。所以调用者不会知道异常的真正原因

    public class ExceptionHandling {
        public static void main(String[] args) {
            try {
                //创建一个错误
                NumberFormatException ex = new NumberFormatException("Exception");
                //设置错误的触发原因
                ex.initCause(new NullPointerException("This is actual cause of the exception"));
                //抛出错误并指明原因
                throw ex;
            } catch(NumberFormatException ex) {
                //在控制台打印错误
                System.out.println(ex);
                //获得错误的触发原因
                System.out.println(ex.getCause());
            }
        }
    }
    
  • 支持IPV6

    JDK 1.4开始支持 Linux 和Solaris 平台上的 IPv6(JDK 1.5起加入了 Windows 平台上的支持)

  • 支持正则表达式

  • 引入Imgae I/O API

    提供了一组用于操作存在本地文件的或者通过网络传输的图片的可插入式架构。它较之前的API在读取和保存图片方面总体上来看要更加灵活和强大。

Java 5

2004-09-30 Tiger(老虎) major.minor 49

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

  • 增强循环(for-each):for-each循环简化了集合的遍历。

  • 自动封箱拆箱:

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

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

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

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

    //可变参数String... args
    private static void testVarargs(String... args) {
        for (String arg : args) {
            System.out.println(arg);
        }
    }
    
  • 注解:可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。

  • 静态导入:通过import static类,就可以使用类里的静态变量或方法。

  • 线程并发库(JUC):JDK5 丰富了线程处理功能,java.util.concurrent包提供了以下的类、接口:

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

  • Introspector(内省)

  • Scanner 类

Java 6

2006-12-11 Mustang(野马) major.minor 50

  • Desktop类和SystemTray类:在java.awt包下新增的两个类,主要用来打开系统默认浏览器以及托盘区管理,不常用。

  • 引入 JAXB2 来处理对象和 XML 之间的映射;

  • 轻量级 Http Server API

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

    /**
     * 根据Java提供的API实现Http服务器
     */
    public class MyHttpServer {
    
        /**
         * @param args
         * @throws IOException
         */
        public static void main(String[] args) throws IOException {
            //创建HttpServer服务器
            HttpServer httpServer = HttpServer.create(new InetSocketAddress(8080), 10);
            //将 /jay请求交给MyHandler处理器处理
            httpServer.createContext("/", new MyHandler());
            httpServer.start();
        }
    }
    
    public class MyHandler implements HttpHandler {
    
        public void handle(HttpExchange httpExchange) throws IOException {
            //请求头
            Headers headers = httpExchange.getRequestHeaders();
            Set<Map.Entry<String, List<String>>> entries = headers.entrySet();
    
            StringBuffer response = new StringBuffer();
            for (Map.Entry<String, List<String>> entry : entries){
                response.append(entry.toString() + "\n");
            }
            //设置响应头属性及响应信息的长度
            httpExchange.sendResponseHeaders(200, response.length());
            //获得输出流
            OutputStream os = httpExchange.getResponseBody();
            os.write(response.toString().getBytes());
            os.close();
        }
    }
    
    
  • 插入式注解处理API

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

  • StAX(Streaming API for XML) 处理 XML;

    public class STAXTest {
    
        public static void main(String[] args) throws Exception {
    
            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
            XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(new FileInputStream("C:\\jay.xml"));
            XMLEvent event = null;
            StringBuffer stringBuffer = new StringBuffer();
            while (xmlEventReader.hasNext()) {
                event = xmlEventReader.nextEvent();
                stringBuffer.append(event.toString());
            }
            System.out.println("xml文档解析结果:");
            System.out.println(stringBuffer);
        }
    }
    

    运行结果

    xml文档解析结果:
    <?xml version="1.0" encoding='GBK' standalone='yes'?><list>
        <singer name='jay' age='8'></singer>
        <singer name='eason' age='10'></singer>
    </list>ENDDOCUMENT
    
  • 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
  • Compiler API

    javac编译器可以把.java的源文件编译为.class文件,JDK 6的新特性Compiler API(JSR 199)也可以动态编译Java源文件。

    public class CompilerApiTest {
        public static void main(String[] args) throws Exception {
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null,null,null);
            Iterable<? extends JavaFileObject> javaFileObjects = manager.getJavaFileObjects("C:\\Singer.java");
            javaCompiler.getTask(null, manager, null, null, null, javaFileObjects).call();
            standardJavaFileManager.close();
        }
    }
    
  • 对脚本语言的支持

    JDK6增加了对脚本语言的支持(JSR 223),原理是将脚本语言编译成字节码,这样脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等。JDK6实现包含了一个基于Mozilla Rhino的 脚本语言引擎,因此可以支持javascript,当然JDK也支持ruby等其他语言

    public class JavaScriptTest {
    
        public static void main(String[] args) throws Exception {
            ScriptEngineManager factory = new ScriptEngineManager();
            ScriptEngine engine = factory.getEngineByName("JavaScript");
            String script;
            try {
                script = "print('Hello')";
                engine.eval(script);// 执行脚本
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    //output
    Hello
    
    
  • Console API

  • JDBC 4.0

  • 引入新的 GC 算法

Java 7

2011-07-28 Dolphin(海豚) major.minor 51

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

  • 泛型实例化类型自动推断

  • try-with-resources:资源自动关闭

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

    try{
       //do something
    } catch (FirstException | SecondException e) {
         logger.error(e);
    }
    
  • Java NIO2 API

    Java7 提供了全新的NIO2.0 API,方便文件管理的编码。如,可以在java.nio.file包下使用Path、Paths、Files、WatchService等常用类型。

    Path path = Paths.get("C:\\jay\\七里香.txt"); //创建Path对象
    byte[] bytes= Files.readAllBytes(path);  //读取文件
    System.out.println(path.getFileName()); //获取当前文件名称
    System.out.println(path.toAbsolutePath()); // 获取文件绝对路径
    System.out.println(new String(bytes, "utf-8"));
    
  • switch 支持String字符串类型。

    String singer = "jay";
    switch (singer) {
           case "jay" :
                System.out.println("周杰伦");
                 break;
           case "eason" :
                System.out.println("陈奕迅");
                break ;
           default :
                System.out.println("其他");
                break ;
       }
    
  • 数字常量支持下划线

    int a = 11_11;  //a的值为1111,下划线不影响实际值,提升可读性
    
  • 整数类型如(byte,short,int,long)能够用二进制来表示

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

Java 8

2014-03-18 Spider(蜘蛛) major.minor 52

  • lambada表达式

  • 管道和 Stream API

    Stream API,支持对元素流进行函数式操作,它集成在Collections API 中,可以对集合进行批量操作。常用API

    • filter 筛选
    • map流映射
    • reduce 将流中的元素组合起来
    • collect 返回集合
    • sorted 排序
    • flatMap 流转换
    • limit返回指定流个数
    • distinct去除重复元素
    public class Singer {
    
        private String name;
        private Integer songNum;
        private Integer age;
        ...
    }
    
    List<Singer> singerList = new ArrayList<Singer>();
    singerList.add(new Singer("jay", 11, 36));
    singerList.add(new Singer("eason", 8, 31));
    singerList.add(new Singer("JJ", 6, 29));
    
    List<String> singerNameList = singerList.stream()
                    .filter(singer -> singer.getAge() > 30)  //筛选年龄大于30
                    .sorted(Comparator.comparing(Singer::getSongNum))  //根据歌曲数量排序
                    .map(Singer::getName)  //提取歌手名字
                    .collect(Collectors.toList()); //转换为List
    
    
  • 新的日期和时间 API

    JDK 8之前的日期API处理存在非线程安全、时区处理麻烦等问题。Java 8 在 java.time包下提供了新的日期API,简化了日期的处理~

    LocalDate today = LocalDate.now();
    int year = today.getYear();
    System.out.println("今年是" + year);
    //是否闰年
    System.out.println("今年是不是闰年:" + today.isLeapYear());
    
    LocalDateTime todayTime = LocalDateTime.now();
    System.out.println("当前时间" + todayTime);
    //时区指定
    System.out.println("美国时间:" + ZonedDateTime.of(todayTime,ZoneId.of("America/Los_Angeles")));
            
    LocalDate specailDate = LocalDate.of(2020, 6, 20);
    LocalDate expectDate = specailDate.plus(100, ChronoUnit.DAYS);
    System.out.println("比较特别的一天" + specailDate);
    System.out.println("特殊日期的100天" + expectDate);
    
  • 函数式接口

    Lambda的设计者为了让现有的功能与Lambda表达式很好兼容,设计出函数式接口。

    • 函数式接口是指只有一个函数的接口,可以隐式转换为lambada表达式。
    • Java 8 提供了注解@FunctionalInterface,显示声明一个函数式接口。
    • java.lang.Runnable和java.util.concurrent.Callable是函数式接口的例子~
    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    
  • 方法与构造函数的引用;

    方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。它与Lambda表达式配合使用,可以减少冗余代码,使代码更加简洁。

    //利用函数式接口Consumer的accept方法实现打印,Lambda表达式如下
    Consumer<String> consumer = x -> System.out.println(x);
    consumer.accept("jay");
    //引用PrintStream类(也就是System.out的类型)的println方法,这就是方法引用
    consumer = System.out::println;
    consumer.accept("hello world");
    
  • 接口的默认方法,又称为扩展方法

    默认方法就是一个在接口里面有了一个实现的方法。它允许将新方法添加到接口,但不强制实现了该接口的类必须实现新的方法。

    public interface ISingerService {
        // 默认方法
        default void sing(){
            System.out.println("唱歌");
        }
        void writeSong();
    }
    
    //JaySingerServiceImpl 不用强制实现ISingerService的默认sing()方法
    public class JaySingerServiceImpl implements ISingerService {
        @Override
        public void writeSong() {
            System.out.println("写了一首七里香");
        }
    }
    
    
  • Optional API

    Java 8引入Optional类,用来解决NullPointerException。Optional代替if...else解决空指针问题,使代码更加简洁。

    Optional<Singer> singer = Optional.ofNullable(getSingerById("666"));
    singer.ifPresent(s -> System.out.println(s.getName()));
    
  • 支持多重注解,并新增了部分注解

    重复注解,即一个注解可以在一个类、属性或者方法上同时使用多次;用@Repeatable定义重复注解

    @Repeatable(ScheduleTimes.class)
    public @interface ScheduleTime {
        String value();
    }
    
    public @interface ScheduleTimes {
        ScheduleTime[] value();
    }
    
    public class ScheduleTimeTask {
        @ScheduleTime("10")
        @ScheduleTime("12")
        public void doSomething() { }
    }
    
  • Base64

    Java 8把Base64编码的支持加入到官方库中~

    String str = "Hello World !";
    String encoded = Base64.getEncoder().encodeToString(str.getBytes( StandardCharsets.UTF_8));
    String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
    
  • JVM的新特性

    使用元空间Metaspace代替持久代(PermGen space),JVM参数使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize设置大小。

Java 9

  • 模块系统
上次编辑于:
贡献者: xuliang