由于 jdk 9 和 jdk10都不是长期支持的版本,因此将它们的新特性放到 jdk 11 中讲
没有名为jre的子目录 | |
bin目录 | 包含所有命令。在Windows平台上,它继续包含系统的运行时动态链接库 |
conf目录 | 包含用户可编辑的配置文件,例如以前位于jre/bin目录中.properties和.policy文件 |
include目录 | 包含要在以前编辑本地代码时使用的C/C++头文件。它只存在于JDK中/td> |
jmods目录 | 包含JMOD格式的平台模块。创建自定义运行时映像时需要它。它只存在于JDK中/td> |
legal目录 | 包含法律声明 |
lib目录 | 包含非Windows平台上的动态连接本地库。其子目录和文件不应由开发人员直接编辑或使用 |
每次JVM启动的时候,至少会有30~60MB的内存加载,主要原因时JVM需要加载rt.jar,不管其中的类是否被classloader加载,第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)。每一个公共类都可以被类路径之下任何其它的公共类所访问到,这就会导致无意中使用了并不想被公开访问的API。
本质上将,模块(moudule)的概念,其实就是package外再裹一层,也就是说,用模块来管理各个package,通过声明某个package暴露,不声明默认就是隐藏。因此,模块化使的代码组织上更安全,因此它可以指定哪些部分可以暴露,哪些部分可以隐藏。
实现目标
package stars.grace.test; import stars.grace.routine.Person; public class ModuleTest { public static void main(String[] args) { Person person = new Person("Sakura",10); System.out.println(person); } }
module test { requires routine; }
package stars.grace.routine; public class Person { private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
module routine { exports stars.grace.routine; }
jSell工具让Java可以像脚本语言一样运行,从控制台启动jSell,利用jShell在没有创建类的情况下直接声明变量,计算表达式,执行语句。即开发时在命令行里直接运行Java的代码,而不需要创建Java文件。jShell也可以从文件中加载语句或者将语句保存到文件中。jShell也可以使用tab键进行自动补全和自动添加分号。
Java 8 规定接口中的方法处理抽象方法之外,还可以定义静态方法和默认方法。一定程度上,拓展了接口的功能,此时的接口更像是一个抽象类。在 Java 9 中,接口更加的灵活和强大,连方法的访问修饰符都可以声明为private的,此时方法将不会为你对外暴露的API的一部分。
public class MyInterfaceImplements implements MyInterface{ public static void main(String[] args) { //接口中的静态方法只能由接口自己调用 MyInterface.staticMethod(); MyInterfaceImplements myInterfaceImplements = new MyInterfaceImplements(); myInterfaceImplements.defaultMethod(); //接口的私有方法,不能在接口外部调用 //myInterfaceImplements.privateMethod(); } @Override public void abstractMethod() { } @Override public void defaultMethod() { System.out.println("实现类重写了接口中的默认方法"); } }
public interface MyInterface { //权限修饰符为public void abstractMethod(); //权限修饰符为public static void staticMethod(){ System.out.println("我是接口中的静态方法"); } //权限修饰符为public default void defaultMethod(){ System.out.println("我是接口中的默认方法"); privateMethod(); } private void privateMethod(){ System.out.println("我是接口中的私有方法"); } }
import java.util.ArrayList; import java.util.Comparator; public class Template { public static void main(String[] args) { //JDK 7 中的新特性:类型推断 ArrayList<String> list = new ArrayList<>(); //钻石操作符与匿名实现类在 Java 8 中不能共存,在 Java 9 中可以 Comparator<Object> comparator = new Comparator<>(){ @Override public int compare(Object o1, Object o2) { return 0; } }; } }
Java 8 中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。
import java.io.IOException; import java.io.InputStreamReader; public class Template { public static void main(String[] args) { //Java 9 中资源关闭操作:需要自动关闭的资源的实例化可以放在try的一对小括号外、 //此时的资源属性是常量,声明为final,不可修改 InputStreamReader reader = new InputStreamReader(System.in); try(reader){ char[] cbuf = new char[20]; int len; if((len = reader.read(cbuf)) != -1){ String str = new String(cbuf,0,len); System.out.println(str); } } catch (IOException e) { e.printStackTrace(); } } }
在处理 var 时,编译器先是查看表达式右边的部分,并根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字节码当中。var 不是关键字
import java.util.ArrayList; import java.util.function.Consumer; import java.util.function.Supplier; public class Template { public static void main(String[] args) { //声明变量时,根据所赋的指,推断变量的类型 //局部变量不赋值,不能实现类型推断 var num = 10; var list = new ArrayList<String>(); list.add("Sakura"); list.add("Mikoto"); list.add("Misaka"); for (var i : list) { System.out.println(i); System.out.println(i.getClass().getName()); } //Lambda表达式和方法引用中,左边函数式接口不能声明var //var supplier = () -> Math.random(); //var consumer = System.out::println; //数组的静态初始化 //var array = {1,2,3,4}; } }
不能使用类型推断的情景