目录名称 | 说明 |
---|---|
bin |
包含所有命令和运行时动态链接库 |
conf |
包含用户可编辑的配置文件,例如以前位于jre\lib 目录中的.properties 和.policy 文件 |
include |
包含编译本地代码时使用的C/C++头文件 |
jmods |
包含JMOD格式的平台模块, 创建自定义运行时映像时需要它 |
legal |
包含法律声明 |
lib |
其它平台上的动态链接本地库, 其子目录和文件不应由开发人员直接编辑或使用 |
Java运行环境的膨胀和臃肿的主要原因是JVM
需要加载rt.jar
【runtime环境】。不管其中的类是否被classloader
加载,第一步整个jar
都会被JVM
加载到内存当中去,一般需要30~60MB内存(而模块化可以根据模块的需要加载程序运行需要的class)
每一个公共类都可以被类路径之下任何其它的公共类所访问到,这样就会导致无意中使用了并不想被公开访问的 API。模块化限制了类的访问
使用模块化的前提条件是java文件夹下必须有module-info.java
//========================================= 工程java9.modular ========================================
package com.kun.modular.export.bean;
public class Person {
// filed and method
}
/*
* module-info配置
*/
module java9.modular {
// exports [包名...] 暴露当前模块的包,所有其它模块均可访问
exports com.kun.modular.export.bean;
// exports [包名...] to [包名...] 暴露当前模块的包,只有指定的其它包可访问
// exports com.kun.modular.export.bean to com.kun.test.modular;
}
//============================================ 工程java9 ===========================================
package com.kun.test.modular;
public class ModularTest {
public static void main(String[] args) throws Exception {
Person person = new Person();
}
}
/*
* module-info配置
*/
module java9 {
// 引入模块
requires java9.modular;
}
//========================================= 工程java9.modular ========================================
package com.kun.modular.export.bean;
public class Person {
// filed and method
}
/*
* module-info配置
*/
module java9.modular {
// 指定包可以通过java反射访问
opens com.kun.modular.export.bean;
}
//============================================ 工程java9 ===========================================
package com.kun.test;
public class ModularTest {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.kun.modular.bean.Person");
Constructor<?> constructor = aClass.getConstructor();
Object o = constructor.newInstance();
}
}
/*
* module-info配置
*/
module java9 {
// 通过反射也需要显示引入模块
requires java9.modular;
}
//========================================= 工程java9.modular ========================================
package com.kun.modular.export.provides;
public interface PersonService {
Person getPerson();
}
public class PersonServiceImpl implements PersonService{
@Override
public Person getPerson() {
return new Person();
}
}
/*
* module-info配置
*/
module java9.modular {
// 指定服务类和其实现类
provides com.kun.modular.export.provides.PersonService with com.kun.modular.export.provides.PersonServiceImpl;
}
//============================================ 工程java9 ===========================================
package com.kun.test;
public class ModularTest {
public static void main(String[] args) throws Exception {
// 加载服务
PersonService personService = ServiceLoader.load(PersonService.class).findFirst().get();
personService.getPerson();
}
}
/*
* module-info配置
*/
module java9 {
requires java9.modular;
// 指定使用什么服务,上方的requires也必须使用
uses com.kun.modular.export.provides.PersonService;
}
requires static [包名]
表示依赖的模块是编译时是必需的,但运行时是可选的,比如一些检查注解,运行时并不需要
requires transitive [包名]
表示假如模块A依赖模块 B,外界的模块不仅想使用 A 模块还想使用B模块,那么可以使用该指令获取到B 的访问权限,这种对外暴露传递依赖的模块也称为隐式读取(implied read)
public interface NewInterface {
// JDK 7及之前版本只能创建public abstract 方法 和 public static final常量
void methodJDK7();
public static final String CONSTANT_DATA = "常量";
// JDK8允许创建default方法访问修饰符是public, 还允许创建静态方法修饰符是public
default void methodJDK8() {
System.out.println("JDK8允许创建default方法");
}
static void methodStaticJDK8() {
System.out.println("JDK8允允许创建静态方法");
}
// JDK9允许创建private方法,供default方法调用[多个default抽取公共方法]
private void methodJDK9() {
System.out.println("JDK9允许创建private方法,供default方法调用[多个default抽取公共方法]");
}
default void methodDefault(){
methodJDK9();
}
}
public class DiamondOperatorTest {
public static void main(String[] args) {
// JDK8也可以使用但是new HashMap<>不能进行泛型推到必须使用new HashMap<Integer, String>
Map<Integer, String> map = new HashMap<>(){
{
put(1, "A");
put(2, "B");
put(3, "C");
}
};
}
}
//======================================== JDK 7 处理方式 ========================================
InputStream inputStream = null;
try {
inputStream = new FileInputStream("index.html");
} catch (FileNotFoundException e) {
System.out.println("异常处理");
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
System.out.println("异常处理");
}
}
}
//======================================== JDK 8 处理方式 ========================================
// 流会自动关闭但是 InputStream inputStream = new FileInputStream("index.html") 必须写在括号内
try(InputStream inputStream = new FileInputStream("index.html")) {
// do something
} catch (FileNotFoundException e) {
System.out.println("异常处理");
} catch (IOException e) {
System.out.println("异常处理");
}
//======================================== JDK 9 处理方式 ========================================
// 流会自动关闭,但是文件找不到这种异常还是会向上抛出
InputStream inputStream = new FileInputStream("index.html");
try(inputStream) {
// do something
} catch (IOException e) {
System.out.println("异常处理");
}
背景:JDK8的字符串存储在char
类型的数组里面,在大多数情况下字符只需要一个字节就能表示出来了[英文字母和数字],所以使用char[一个char占两个字节]存储势必会浪费空间
JDK9改用byte[]
表示
coder=LATIN1=0
,采用一个byte存储一个字符的策略coder=UTF-16=1
,采用两个byte存储一个字符的策略String底层存储改变引起的连锁反应:StringBuffer
和StringBuilder
底层也使用byte[]
存储,当调用append
时会判断需要连接的俩字符串是否是同coder,是同coder直接连接。不是同coder则需要变为coder=UTF-16
格式
//========================================= JDK 8 创建只读容器 =========================================
List<String> stringList = new ArrayList<>();
stringList.add("1");
stringList.add("2");
stringList.add("3");
stringList = Collections.unmodifiableList(stringList);
stringList.add("2");
//========================================= JDK 9 创建只读容器 =========================================
List<String> stringList = List.of("1", "2", "3", "4", "5");
Set<String> stringSet = Set.of("1", "2", "3", "4", "5");
Map<Integer, String> map = Map.of(1, "v1", 2, "v2", 3, "v3");
Map<Integer, String> mapEntry = Map.ofEntries(
Map.entry(1, "v1"),
Map.entry(2, "v2"),
Map.entry(3, "v3"));
List<Integer> list = Arrays.asList(45, 43, 76, 87, 42, 77, 90, 73, 67, 88);
// 在流中得到尽可能多的符合条件的数据,即从左往右查找
list.stream().takeWhile(x -> x < 80).forEach(System.out::println);
// takeWhile的补集
list.stream().dropWhile(x -> x < 80).forEach(System.out::println);
/*
* public static<T> Stream<T> of(T... values) 可以元素全部为null,count时null不计入
* public static<T> Stream<T> of(T t) 元素不能为null会抛出异常
* public static<T> Stream<T> ofNullable(T t) 元素可以为null,count时null计入
*/
Stream.of("1", "2", null); //count为2
Stream.ofNullable(null); //count为1
// iterator()重载的使用,创建一个1~10的Integer类型的Stream
Stream.iterate(1, i -> i + 1).limit(10)
// 比使用limit更加灵活
Stream.iterate(1, i -> i <= 10,i -> i + 1).forEach(System.out::println);
// Optional类中stream()的使用
Optional<List<String>> optional = Optional.of(Arrays.asList("1", "2", "3", "4"));
// optional.stream() 得到的是Stream<List<String>>
optional.stream().flatMap(x -> x.stream()).forEach(System.out::println);
创建Stream的方法:
InputStream添加了transferTo
放法,可以用来将数据直接传输到OutputStream
,这是在处理原始数据流时非常常见的一种用法
public class InputStreamTest {
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("src/1.txt");
OutputStream outputStream = new FileOutputStream("1_bak.txt");
inputStream.transferTo(outputStream);
}
}