百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

Java14~java8~Java1各大版本中令人激动的特性

xsobi 2024-12-17 17:07 2 浏览

现在的 JDK 真变成了“版本帝”,无力吐槽啊,版本发到 15,大部分人却都还在用着 JDK 7/8,甚至 6。不过没关系,多了解一下,多掌握一点新东西,对你来说没有坏处。

Java14

instanceof模式匹配

通常情况下我们使用instanceof来探测类的真实类型,如果符合该类型,则可进行强制转换。

在Java14之前,我们通常的写法如下:

Object obj = "程序新视界";
if(obj instanceof String){
	String str = (String) obj;
	System.out.println("关注公众号:" + str);
}

通过java14的新特性,我们可以简化成如下方式:

Object obj = "程序新视界";
if(obj instanceof String str){
	System.out.println("关注公众号:" + str);
}

我们可以通过模式匹配简洁地表达对象,并允许各种语句和表达式对其进行测试。

Switch表达式

通常情况下我们通过如下形式使用switch语法:

switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}

java14引入了新形式的switch标签“case L->”,表示如果匹配,则只执行标签右边的代码。switch标签允许在每种情况下使用逗号分隔多个常量。

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

是不是简单清晰了很多。

记录类型(Record Type)的引入

Java 14中记录类型(Record Type)作为预览特性被引入。记录对象允许使用紧凑的语法来声明类,和枚举类型一样,记录也是类的一种受限形式。

在idea 2020.1中,创建Record与创建类和枚举一样,可以在创建时直接选择对应的类型。

定义一个Record类型如下:

public record Point(int x, int y) {

}

使用Record操作如下:

Point point = new Point(1,3);
System.out.println(point.x());
System.out.println(point.y());

对Record类进行反编译我们会看到如下内容:

public final class Point extends java.lang.Record {
    private final int x;
    private final int y;

    public Point(int x, int y) { /* compiled code */ }

    public java.lang.String toString() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    public int x() { /* compiled code */ }

    public int y() { /* compiled code */ }
}

是不是有替代Lombok的潜质?

文本块作为预览特性保留

通常情况下我们定义一个字符串,如果比较长可使用如下形式进行编写:

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";

使用java14的文本块新特性,则可改写为如下形式:

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

文本块是Java语言的新语法,可以用来表示任何字符串,具有更高的表达能力和更少的复杂度。

文本块的开头定界符是由三个双引号字符(""")组成的序列,后面跟0个或多个空格,最后跟一个行终止符。内容从开头定界符的行终止符之后的第一个字符开始。

结束定界符是三个双引号字符的序列。内容在结束定界符的第一个双引号之前的最后一个字符处结束。

与字符串文字中的字符不同,文本块的内容中可以直接包含双引号字符。允许在文本块中使用",但不是必需的或不建议使用。

与字符串文字中的字符不同,内容可以直接包含行终止符。允许在文本块中使用\n,但不是必需或不建议使用。

打包工具 (Incubator)

jpackage打包工具可以将Java应用程序打包为针对特定平台的安装包,这个安装包包含所有必需的依赖项。该应用程序可以以普通JAR文件集合或模块集合的方式提供。软件包格式可以分为:

  • Linux:deb和rpm
  • macOS:pkg和dmg
  • Windows:msi和exe



Java 13

一. 文本块-预览(JEP 355)

这是预览功能。它使我们能够轻松地创建多行字符串。多行字符串必须写在一对三重双引号内。

使用文本块创建的字符串对象没有其他属性。这是创建多行字符串的简便方法。我们不能使用文本块来创建单行字符串。另外,开头的三重双引号后必须跟一个行终止符。

在 Java 13 之前:

String html ="<html>\n" +
			  "   <body>\n" +
			  "      <p>Hello, World</p>\n" +
			  "   </body>\n" +
			  "</html>\n";


String json ="{\n" +
			  "   \"name\":\"mkyong\",\n" +
			  "   \"age\":38\n" +
			  "}\n";

Java 13:

String html =  """
               <html>
                   <body>
                       <p>Hello, World</p>
                   </body>
               </html>
				        """;

String json = """
               {
                   "name":"mkyong",
                   "age":38
               }
               """;

回到顶部

二. 文本块的字符串类新方法

String 类中有三个与文本块功能关联的新方法。

  1. formatted(Object…args):它类似于 String format() 方法。添加它是为了支持文本块的格式化。
  2. stripIndent():用于从文本块中的每一行的开头和结尾删除附带的空格字符。文本块使用此方法,并保留内容的相对缩进。
  3. translateEscapes():返回一个值为该字符串的字符串,其转义序列就像在字符串文字中一样进行翻译。
package com.journaldev.java13.examples;

public class StringNewMethods {

	/***
	 * New methods are to be used with Text Block Strings
	 * @param args
	 */
	@SuppressWarnings("preview")
	public static void main(String[] args) {
		
		String output = """
			    Name: %s
			    Phone: %d
			    Salary: $%.2f
			    """.formatted("Pankaj", 123456789, 2000.5555);
		
		System.out.println(output);
		
		
		String htmlTextBlock = "<html>   \n"+
				                    "\t<body>\t\t \n"+
				                        "\t\t<p>Hello</p>  \t \n"+
				                    "\t</body> \n"+
				                "</html>";
		System.out.println(htmlTextBlock.replace(" ", "*"));
		System.out.println(htmlTextBlock.stripIndent().replace(" ", "*"));
		
		String str1 = "Hi\t\nHello' \" /u0022 Pankaj\r";
		System.out.println(str1);
		System.out.println(str1.translateEscapes());
		
	}
}

输出:

Name: Pankaj
Phone: 123456789
Salary: $2000.56

<html>***
	<body>		*
		<p>Hello</p>**	*
	</body>*
</html>
<html>
	<body>
		<p>Hello</p>
	</body>
</html>
Hi	
Hello' " /u0022 Pankaj
Hi	
Hello' " /u0022 Pankaj

回到顶部

三. 开关表达式-预览(JEP 354)

Java 12 引入了JEP 325 Switch表达式。该 JEP 放弃brea 关键字而改用 yield 关键字从 switch 表达式返回值。(其他均与 Java 12 没区别)

// switch expressions, use yield to return, in Java 12 it was break
int x = switch (choice) {
    case 1, 2, 3:
        yield choice;
    default:
        yield -1;
};

(ps:这会在 Java 14 - JEP 361 中成为标准功能)

回到顶部

四. 重新实现旧版套接字 API(JEP 353)

java.net.Socketjava.net.ServerSocket 的底层实现都很古老,可以追溯到 JDK 1.0,它混合了遗留的 Java 和 C 代码,很难维护和调试。这个 JEP 为套接字 API 引入了新的底层实现,这是 Java 13 中的默认实现。

在 Java 13 之前,SocketImpl 使用 PlainSocketImpl

public class ServerSocket implements java.io.Closeable {

    /**
     * The implementation of this Socket.
     */
    private SocketImpl impl;
}

Java 13 引入了一个新的 NioSocketImpl 类,作为对 PlainSocketImpl 的临时替换。但是,如果出现错误,我们仍然可以通过设置 jdk.net.usePlainSocketImpl 系统属性切换回旧的实现 PlainSocketImpl

下面是一个简单的套接字示例。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class JEP353 {

    public static void main(String[] args) {

        try (ServerSocket serverSocket = new ServerSocket(8888)){

            boolean running = true;
            while(running){
                Socket clientSocket = serverSocket.accept();
                //do something with clientSocket
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在 Java 13 中,默认实现是 NioSocketImpl

D:\test>javac JEP353.java

D:\test>java JEP353

D:\test>java -XX:+TraceClassLoading JEP353  | findStr Socket

[0.040s][info   ][class,load] java.net.ServerSocket source: jrt:/java.base
[0.040s][info   ][class,load] jdk.internal.access.JavaNetSocketAccess source: jrt:/java.base
[0.040s][info   ][class,load] java.net.ServerSocket$1 source: jrt:/java.base
[0.040s][info   ][class,load] java.net.SocketOptions source: jrt:/java.base
[0.040s][info   ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.044s][info   ][class,load] java.net.SocketImpl$Lambda$1/0x0000000800ba0840 source: java.net.SocketImpl
[0.047s][info   ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base

[0.047s][info   ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base

[0.047s][info   ][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
[0.052s][info   ][class,load] java.net.SocketAddress source: jrt:/java.base
[0.052s][info   ][class,load] java.net.InetSocketAddress source: jrt:/java.base
[0.052s][info   ][class,load] java.net.InetSocketAddress$InetSocketAddressHolder source: jrt:/java.base
[0.053s][info   ][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.053s][info   ][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.053s][info   ][class,load] java.net.SocketOption source: jrt:/java.base
[0.053s][info   ][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.053s][info   ][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.053s][info   ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.053s][info   ][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.054s][info   ][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.054s][info   ][class,load] sun.nio.ch.NioSocketImpl$FileDescriptorCloser source: jrt:/java.base
[0.055s][info   ][class,load] java.net.Socket source: jrt:/java.base

回到顶部

五. 动态 CDS 存档(JEP 350)

该 JEP 扩展了 Java 10 中引入的类数据共享功能。现在,创建 CDS 存档并使用它要容易得多。

$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar

$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar

回到顶部

六. ZGC:取消提交未使用的内存(JEP 351)

该 JEP 增强了ZGC,可以将未使用的堆内存返回给操作系统。Z垃圾收集器是 Java 11 中引入的。它会在堆内存清理之前增加一个短暂的暂停时间。但是,未使用的内存没有返回给操作系统。对于诸如 IoT 和微芯片等内存占用较小的设备,这是一个问题。

现在,它已得到增强,可以将未使用的内存返回给操作系统。

回到顶部

七. FileSystems.newFileSystem() 方法

在 FileSystems 类中添加了三种新方法,以便更容易地使用文件系统提供程序,这些提供程序将文件的内容视为文件系统。

  1. newFileSystem(Path)
  2. newFileSystem(Path, Map<String, ?>)
  3. newFileSystem(Path, Map<String, ?>, ClassLoader)

回到顶部

八. 具有命名空间支持的 DOM 和 SAX 工厂

有一些新方法可以实例化支持名称空间的 DOM 和 SAX 工厂。

  1. newDefaultNSInstance()
  2. newNSInstance()
  3. newNSInstance(String factoryClassName, ClassLoader classLoader)
//java 13 onwards
DocumentBuilder db = DocumentBuilderFactory.newDefaultNSInstance().newDocumentBuilder(); 

// before java 13
DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); 
dbf.setNamespaceAware(true); 
DocumentBuilder db = dbf.newDocumentBuilder();

Java 12

switch 表达式

Java 12 以后,switch 不仅可以作为语句,也可以作为表达式。

private String switchTest(int i) {
    return switch (i) {
        case 1 -> "1";
        default -> "0";
    };
}

Java 11

1. Lambda 中使用 var

(var x, var y) -> x.process(y)

2. 字符串 API 增强

Java 11 新增了 一系列字符串处理方法,例如:

// 判断字符串是否为空白
" ".isBlank(); 
" Javastack ".stripTrailing();  // " Javastack"
" Javastack ".stripLeading();   // "Javastack "

3. 标准化 HttpClient API

4. java 直接编译并运行,省去先 javac 编译生成 class 再运行的步骤

5. 增加对 TLS 1.3 的支持

其他一些改进可以参照 https://www.oracle.com/technetwork/java/javase/11-relnote-issues-5012449.html#NewFeature



Java 10

1. 新增局部类型推断 var

var a = "aa";
System.out.println(a);

var 关键字目前只能用于局部变量以及 for 循环变量声明中。

2. 删除工具 javah

从JDK中移除了 javah 工具,使用 javac -h 代替。

3. 统一的垃圾回收接口,改进了 GC 和其他内务管理

其他特性

  • ThreadLocal 握手交互
    JDK 10 引入一种在线程上执行回调的新方法,很方便地停止单个线程而不是停止全部线程或者一个都不停。
  • 基于Java的实验性JIT编译器
    Java 10 开启了 Java JIT编译器 Graal,用作Linux / x64平台上的实验性JIT编译器。
  • 提供默认的 CA 根证书
  • 将 JDK 生态整合到单个仓库
    此JEP的主要目标是执行一些内存管理,并将JDK生态的众多存储库组合到一个存储库中。

其他一些改进可以参照 https://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html#NewFeature



Java 9

1. Jigsaw 模块系统

在 Java 9 以前,打包和依赖都是基于 JAR 包进行的。JRE 中包含了 rt.jar,将近 63M,也就是说要运行一个简单的 Hello World,也需要依赖这么大的 jar 包。在 Java 9 中提出的模块化系统,对这点进行了改善。 关于模块化系统具体可以看看这篇文章。

2. JShell REPL

Java 9 提供了交互式解释器。有了 JShell 以后,Java 终于可以像 Python,Node.js 一样在 Shell 中运行一些代码并直接得出结果了。

3. 私有接口方法,接口中使用私有方法

Java 9 中可以在接口中定义私有方法。示例代码如下:

public interface TestInterface {
    String test();

    // 接口默认方法
    default String defaultTest() {
        pmethod();
        return "default";
    }

    private String pmethod() {
        System.out.println("private method in interface");
        return "private";
    }
}

4. 集合不可变实例工厂方法

在以前,我们想要创建一个不可变的集合,需要先创建一个可变集合,然后使用 unmodifiableSet 创建不可变集合。代码如下:

Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");

set = Collections.unmodifiableSet(set);
System.out.println(set);

Java 9 中提供了新的 API 用来创建不可变集合。

List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
Map<String, String> map = Map.of("KA", "VA", "KB", "VB");

5. 改进 try-with-resources

Java 9 中不需要在 try 中额外定义一个变量。Java 9 之前需要这样使用 try-with-resources:

InputStream inputStream = new StringBufferInputStream("a");
try (InputStream in = inputStream) {
    in.read();
} catch (IOException e) {
    e.printStackTrace();
}

在 Java 9 中可以直接使用 inputStream 变量,不需要再额外定义新的变量了。

InputStream inputStream = new StringBufferInputStream("a");
try (inputStream) {
    inputStream.read();
} catch (IOException e) {
    e.printStackTrace();
}

6. 多版本兼容 jar 包

Java 9 中支持在同一个 JAR 中维护不同版本的 Java 类和资源。

7. 增强了 Stream,Optional,Process API

8. 新增 HTTP2 Client

9. 增强 Javadoc,增加了 HTML 5 文档的输出,并且增加了搜索功能

10. 增强 @Deprecated

对 Deprecated 新增了 since 和 forRemoval 属性

11. 增强了钻石操作符 "<>",可以在 匿名内部类中使用了。

在 Java 9 之前,内部匿名类需要指定泛型类型,如下:

Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
}

而在 Java 9 中,可以自动做类型推导,如下:

Handler<? extends Number> intHandler1 = new Handler<>(2) {
}

12. 多分辨率图像 API:定义多分辨率图像API,开发者可以很容易地操作和展示不同分辨率的图像了。

13. 改进的 CompletableFuture API

CompletableFuture 类的异步机制可以在 ProcessHandle.onExit 方法退出时执行操作。

其他一些改进可参照 https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-C23AFD78-C777-460B-8ACE-58BE5EA681F6



Java 8

1. Lambda 和 函数式接口

Lambda 表达式相信不用再过多的介绍,终于在 Java 8 引入了,可以极大的减少代码量,代码看起来更清爽。
函数式接口就是有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。可以隐式转化为 Lambda 表达式。 我们定义一个函数式接口如下:

@FunctionalInterface
interface Operation {
    int operation(int a, int b);
}

再定义一个 Class 用来操作 Operation 接口。

class Test {
    private int operate(int a, int b, Operation operation) {
        return operation.operation(a, b);
    }
}

Test test = new Test();

在 Java 8 之前,我们想要实现 Operation 接口并传给 Test.operate() 方法使用,我们要定义一个匿名类,实现 Operation 方法。

test.operate(1, 2, new Operation() {
    @Override
    public int operation(int a, int b) {
        return a + b;
    }
});

而使用 Lambda 表达式,我们就可以这样写了:

test.operate(1, 2, (a, b) -> a + b);

2. 方法引用

通过方法引用,可以使用方法的名字来指向一个方法。使用一对冒号来引 "::" 用方法。 还是以上面的例子来看,我们再添加几个方法:

@FunctionalInterface
interface Operation {
    int operation(int a, int b);
}

interface Creater<T> {
    T get();
}

interface TestInt {
    int cp(Test test1, Test test2);
}

class Test {
    public static Test create(Creater<Test> creater) {
        return creater.get();
    }

    private int operate(int a, int b, Operation operation) {
        return operation.operation(a, b);
    }

    private static int add(int a, int b) {
        return a + b;
    }

    private int sub(int a, int b) {
        return a - b;
    }

    public int testM(Test test) {
        return 0;
    }

    public void test(TestInt testInt) {
        Test t1 = Test.create(Test::new); 
        Test t2 = Test.create(Test::new);
        testInt.cp(t1, t2);
    }

}

那么对应的方法引用有四种: 构造方法引用
使用方式:Class::new

Test test = Test.create(Test::new);

静态方法引用
使用方式:Class::staticMethod

test.operate(1, 2, Test::add);

对象的实例方法引用
使用方式:instance::method

test.operate(1, 2, test::sub);

类的实例方法引用
使用方式:Class::method

test.test(Test::testM);

其实上面三种方法引用都好理解,最后类的实例方法引用,有两个条件:

  1. 首先要满足实例方法,而不是静态方法
  2. Lambda 表达式的第一个参数会成为调用实例方法的对象 根据这两点我们看上面的例子,test 方法接受一个 TestInt 实例,用 Lambda 表达式表示就是 (Test t1, Test t2) -> res,而我们调用 test 方法时传入的方法引用是 Test::testM,其参数也是一个 Test 实例,最终 test.test(Test::testM) 的调用效果就是 t1.testM(t2)

3. 接口默认方法和静态方法

Java 8 新增了接口的默认实现,通过 default 关键字表示。同时也可以提供静态默认方法。

public interface TestInterface {
    String test();

    // 接口默认方法
    default String defaultTest() {
        return "default";
    }

    static String staticTest() {
        return "static";
    }
}

4. 重复注解

Java 8 支持了重复注解。在 Java 8 之前想实现重复注解,需要用一些方法来绕过限制。比如下面的代码。

@interface Author {
    String name();
}

@interface Authors {
    Author[] value();
}

@Authors({@Author(name="a"), @Author(name = "b")})
class Article {
}

而在 Java 8 中,可以直接用下面的方式。

@Repeatable(Authors.class)
@interface Author {
    String name();
}

@interface Authors {
    Author[] value();
}

@Author(name = "a")
@Author(name = "b")
class Article {
}

在解析注解的时候,Java 8 也提供了新的 API。

AnnotatedElement.getAnnotationsByType(Class<T>)

5. 类型注解

Java 8 之前注解只能用在声明中,在 Java 8 中,注解可以使用在 任何地方。

@Author(name="a")
private Object name = "";
private String author = (@Author(name="a")String) name;

6. 更好的类型推断

Java 8 对于类型推断做了改进。
比如在 Java 7 中下面的写法:

List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.addAll(Arrays.<String>asList());

在 Java 8 中改进后的写法,可以自动做类型推断。

List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.addAll(Arrays.asList());

7. Optional

Java 8 中新增了 Optional 类用来解决空指针异常。Optional 是一个可以保存 null 的容器对象。通过 isPresent() 方法检测值是否存在,通过 get() 方法返回对象。
除此之外,Optional 还提供了很多其他有用的方法,具体可以查看文档。下面是一些示例代码。

// 创建一个 String 类型的容器
Optional<String> str = Optional.of("str");
// 值是否存在
boolean pre = str.isPresent();
// 值如果存在就调用 println 方法,这里传入的是 println 的方法引用
str.ifPresent(System.out::println);
// 获取值
String res = str.get();
// 传入空值
str = Optional.ofNullable(null);
// 如果值存在,返回值,否则返回传入的参数
res = str.orElse("aa");
str = Optional.of("str");
// 如果有值,对其调用映射函数得到返回值,对返回值进行 Optional 包装并返回
res = str.map(s -> "aa" + s).get();
// 返回一个带有映射函数的 Optional 对象
res = str.flatMap(s -> Optional.of(s + "bb")).flatMap(s -> Optional.of(s + "cc")).get();

8. Stream

Java 8 中新增的 Stream 类提供了一种新的数据处理方式。这种方式将元素集合看做一种流,在管道中传输,经过一系列处理节点,最终输出结果。
关于 Stream 提供的具体方法,可以参照 API。下面是一些示例代码。

List<String> list = Arrays.asList("maa", "a", "ab", "c");
list.stream()
        .filter(s -> s.contains("a"))
        .map(s -> s + "aa")
        .sorted()
        .forEach(System.out::println);

System.out.println("####");
list.parallelStream().forEach(System.out::println);

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
int res = numbers.stream().map(i -> i + 1).mapToInt(i -> i).summaryStatistics().getMax();
System.out.println(res);

9. 日期时间 API

Java 8 中新增了日期时间 API 用来加强对日期时间的处理,其中包括了 LocalDate,LocalTime,LocalDateTime,ZonedDateTime 等等,关于 API 可以参照官方文档以及这篇博客,写得很详细。下面是示例代码。

LocalDate now = LocalDate.now();
System.out.println(now);
System.out.println(now.getYear());
System.out.println(now.getMonth());
System.out.println(now.getDayOfMonth());

LocalTime localTime = LocalTime.now();
System.out.println(localTime);
LocalDateTime localDateTime = now.atTime(localTime);
System.out.println(localDateTime);

10. Base64 支持

Java 8 标准库中提供了对 Base 64 编码的支持。具体 API 见可参照文档。下面是示例代码。

String base64 = Base64.getEncoder().encodeToString("aaa".getBytes());
System.out.println(base64);
byte[] bytes = Base64.getDecoder().decode(base64);
System.out.println(new String(bytes));

11. 并行数组 ParallelSort

Java 8 中提供了对数组的并行操作,包括 parallelSort 等等,具体可参照 API。

Arrays.parallelSort(new int[] {1, 2, 3, 4, 5});

12. 其他新特性

  • 对并发的增强 在java.util.concurrent.atomic包中还增加了下面这些类: DoubleAccumulator DoubleAdder LongAccumulator LongAdder
  • 提供了新的 Nashorn javascript 引擎
  • 提供了 jjs,是一个给予 Nashorn 的命令行工具,可以用来执行 JavaScript 源码
  • 提供了新的类依赖分析工具 jdeps
  • JVM 的新特性 JVM内存永久区已经被metaspace替换(JEP 122)。JVM参数 -XX:PermSize 和 –XX:MaxPermSize被XX:MetaSpaceSize 和 -XX:MaxMetaspaceSize代替。

可以看到,Java 8 整体上的改进是很大的,最重要的是引入 Lambda 表达式,简化代码。

其他一些改进可参照 https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html



Java SE 7(2011-07-28, codename Dolphin):

JVM 对动态语言的支持

压缩的 64 位指针(可在 Java 6 中使用 -XX:+UseCompressedOops )

Switch 支持 String 类型

try 语句中的自动资源管理

改进在创建泛型对象时应用类型推断

简化 varargs 方法声明

二进制字符串表示整数,允许在字符串表示中添加下划线

捕获多种异常类型并通过改进的类型检查重新抛出异常

Java NIO 新增了对多个文件系统,文件元数据和符号链接的支持,对应软件包:java.nio.file、java.nio.file.attribute、java.nio.file.spi

Timsort 用于对对象的集合和数组进行排序

类库对椭圆曲线密码算法的支持

适用于 Java 2D 的 XRender 管道,改善对 GPU 特定功能的处理

新协议 SCTP 和 Sockets Direct Protocol 的支持

Upstream 对 XML 和 Unicode 的更新

Java 部署规则集

Java SE 6(2006-12-11, codename Mustang):

Sun 用 Java SE 替换了名称 J2SE,并从版本号中删除了".0",开发人员的内部编号仍然为1.6.0

不再支持较旧的 Win9x 版本

脚本语言支持

核心平台和 Swing 性能显着提高

通过 JAX-WS改进了 Web 服务支持

JDBC 4.0 支持

Java 编译器 API,允许 Java 程序以编程方式选择和调用 Java 编译器的 API

JAXB 升级到 2.0 版,包括 StAX 解析器的集成

支持可插入注解

GUI 的许多改进

JVM 的改进:同步和编译器性能优化,新算法和对现有垃圾回收算法的升级以及应用程序启动性能

J2SE 5.0(2004-09-30, codename Tiger):

泛型

注解(annotation)

自动装箱/拆箱

枚举

Varargs,用类型名称和三个点来声明方法的最后一个参数,如 void drawtext(String... lines)

增强的 for each 循环

改进了多线程 Java 程序的执行语义,新的 Java 内存模型解决了先前规范的复杂性、有效性和性能问题

静态导入

RMI 对象自动存根生成

Swing 新的外观

并发包 java.util.concurrent

扫描程序类,用于解析输入流和缓冲区的数据

在 Apple Mac OS X 10.4 开始支持

J2SE 1.4(2002-02-06, codename Merlin):

新增 assert 关键字

新增 Perl 正则表达式

提供了异常链,允许封装原始的低级的异常

支持 IPv6

Logging API

Image I/O API

集成 XML 解析器和 XSLT 处理器(JAXP)

集成安全性和加密扩展(JCE,JSSE,JAAS)

Java Web Start

Preferences API

J2SE 1.3(2000-05-08, codename Kestrel):

新增 HotSpot JVM

修改 RMI 支持与 CORBA 的可选兼容性

JNDI (Java Naming and Directory Interface),Java 命名和目录接口

新增 JPDA(Java Platform Debugger Architecture),Java 平台调试器体系架构

Java 声音

合成代理类

J2SE 1.2(1998-12-08, codename Playground):

版本名称改为 "J2SE",区分 J2EE 和 J2ME

新增类达到 1520 个

Java plug-in

Collections 框架

Swing 图形 API

Java IDL

Sun 的 JVM 首次搭载一台 JIT 编译器

JDK 1.1(1997-02-19):

AWT 事件模型

内部类

JavaBeans

JDBC(Java DataBase Connectivity)

RMI(Remote Method Invocation)

反射(暂不支持实时修改对象属性)

Windows 平台上的 JIT(Just In Time)编译器

Taligent 的国际化和 Unicode 支持

JDK 1.0(1996-01-23,codename Oak):

第一版 JDK,纯解释运行,外挂JIT,运行速度较慢

相关推荐

js向对象中添加元素(对象,数组) js对象里面添加元素

一、添加一个元素对象名["属性名"]=值(值:可以是一个值,可以是一个对象,也可以是一个数组)这样添加进去的元素,就是一个值或对象或数组...

JS小技巧,如何去重对象数组?(一)

大家好,关于数组对象去重的业务场景,想必大家都遇到过类似的需求吧,这对这样的需求你是怎么做的呢。下面我就先和大家分享下如果是基于对象的1个属性是怎么去重实现的。方法一:使用.filter()和....

「C/C++」之数组、vector对象和array对象的比较

数组学习过C语言的,对数组应该都不会陌生,于是这里就不再对数组进行展开介绍。模板类vector模板类vector类似于string,也是一种动态数组。能够在运行阶段设置vector对象的长度,可以在末...

如何用sessionStorage保存对象和数组

背景:在工作中,我将[{},{}]对象数组形式,存储到sessionStorage,然后ta变成了我看不懂的形式,然后我想取之用之,发现不可能了~记录这次深刻的教训。$clickCouponIndex...

JavaScript Array 对象 javascript的array对象

Array对象Array对象用于在变量中存储多个值:varcars=["Saab","Volvo","BMW"];第一个数组元素的索引值为0,第二个索引值为1,以此类推。更多有...

JavaScript中的数组Array(对象) js array数组

1:数组Array:-数组也是一个对象-数组也是用来存储数据的-和object不同,数组中可以存储一组有序的数据,-数组中存储的数据我们称其为元素(element)-数组中的每一个元素都有一...

数组和对象方法&amp;数组去重 数组去重的5种方法前端

列举一下JavaScript数组和对象有哪些原生方法?数组:arr.concat(arr1,arr2,arrn);--合并两个或多个数组。此方法不会修改原有数组,而是返回一个新数组...

C++ 类如何定义对象数组?初始化数组?linux C++第43讲

对象数组学过C语言的读者对数组的概念应该很熟悉了。数组的元素可以是int类型的变量,例如int...

ElasticSearch第六篇:复合数据类型-数组,对象

在ElasticSearch中,使用JSON结构来存储数据,一个Key/Value对是JSON的一个字段,而Value可以是基础数据类型,也可以是数组,文档(也叫对象),或文档数组,因此,每个JSON...

第58条:区分数组对象和类数组对象

示例设想有两个不同类的API。第一个是位向量:有序的位集合varbits=newBitVector;bits.enable(4);bits.enable([1,3,8,17]);b...

八皇后问题解法(Common Lisp实现)

如何才能在一张国际象棋的棋盘上摆上八个皇后而不致使她们互相威胁呢?这个著名的问题可以方便地通过一种树搜索方法来解决。首先,我们需要写一个函数来判断棋盘上的两个皇后是否互相威协。在国际象棋中,皇后可以沿...

visual lisp修改颜色的模板函数 怎么更改visual studio的配色

(defunBF-yansemokuai(tuyuanyanse/ss)...

用中望CAD加载LISP程序技巧 中望cad2015怎么加载燕秀

1、首先请加载lisp程序,加载方法如下:在菜单栏选择工具——加载应用程序——添加,选择lisp程序然后加载,然后选择添加到启动组。2、然后是添加自定义栏以及图标,方法如下(以...

图的深度优先搜索和广度优先搜索(Common Lisp实现)

为了便于描述,本文中的图指的是下图所示的无向图。搜索指:搜索从S到F的一条路径。若存在,则以表的形式返回路径;若不存在,则返回nil。...

两个有助于理解Common Lisp宏的例子

在Lisp中,函数和数据具有相同的形式。这是Lisp语言的一个重大特色。一个Lisp函数可以分析另一个Lisp函数;甚至可以和另一个Lisp函数组成一个整体,并加以利用。Lisp的宏,是实现上述特色的...