设计模式
设计原则
开闭原则(Open Close Principle)
对扩展开放对修改关闭,为了使程序的扩展性好,易于维护和升级。
里氏代换原则(Liskov Substitution Principle)
任何基类可以出现的地方,子类一定可以出现,多使用多态的方式。
依赖倒转原则(Dependence Inversion Principle)
尽量多依赖于抽象类或接口而不是具体实现类,对子类具有强制性和规范性
接口隔离原则(Interface Segregation Principle)
尽量多使用小接口而不是大接口,避免接口的污染,降低类之间耦合度。
迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少与其他实体之间发生相互作用,使系统功能模块相对独立。高内聚,低耦合。
合成复用原则(Composite Reuse Principle)
尽量多使用合成/聚合的方式,而不是继承的方式。
设计模式
-
分类
创建型模式 - 单例设计模式、工厂方法模式、抽象工厂模式、... 结构型模式 - 装饰器模式、代理模式、... 行为型模式 - 模板设计模式、...
-
单例设计模式
-
普通工厂
-
多个工厂方法模式
-
静态工厂方法
-
抽象工厂模式
-
装饰器模式
-
代理模式
-
模版方法模式
#新特性
JAVA8
函数式接口
- 函数式接口主要指只包含一个抽象方法的接口,如:java.lang.Runnable、java.util.Comparator接口等。
- Java8提供@FunctionalInterface注解来定义函数式接口,若定义的接口不符合函数式的规范便会报错。
- Java8中增加了java.util.function包
接口名称 | 方法声明 | 功能介绍 |
---|---|---|
Consumer | void accept(T t) | 根据指定的参数执行操作 |
Supplier | T get() | 得到一个返回值 |
Function<T,R> | R apply(T t) | 根据指定的参数执行操作并返回 |
Predicate | boolean test(T t) | 判断指定的参数是否满足条件 |
Lambda表达式
Runnable runnable1 = () -> { System.out.println("我是既没有参数又没有返回值的方法!"); };
Runnable runnable1 = () -> System.out.println("我是既没有参数又没有返回值的方法!");
// 自动类型推断
Consumer consumer1 = o -> System.out.println(o + "有参但没有返回值的方法就是我!");
Supplier supplier1 = () -> "无参有返回值!";
// return 和 {} 都可以省略
Function function1 = o -> o;
Comparator comparator1 = (o1, o2) -> 0;
Predicate predicate1 = o -> false;
方法引用
方法引用主要指通过方法的名字来指向一个方法而不需要为方法引用提供方法体,该方法的调用交给函数式接口执行。
方法引用使用一对冒号 :: 将类或对象与方法名进行连接,通常使用方式如下:
- 对象的非静态方法引用 ObjectName :: MethodName
- 类的静态方法引用 ClassName :: StaticMethodName
- 类的非静态方法引用 ClassName :: MethodName
- 构造器的引用 ClassName :: new
- 数组的引用 TypeName[] :: new
Stream接口
- java.util.stream.Stream接口是对集合功能的增强,可以对集合元素进行复杂的查找、过滤、筛选等操作。
- Stream接口借助于Lambda 表达式极大的提高编程效率和程序可读性,同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势。
中间操作
- 筛选与切片方法
/**
通过调用集合的默认方法来获取流,如:default Stream stream()
Stream filter(Predicate<? super T> predicate) 返回一个包含匹配元素的流
*/
list.stream().filter(new Predicate<Person>() {
@Override
public boolean test(Person person) {
return person.getAge() >= 18;
}
}).forEach(new Consumer<Person>() {
@Override
public void accept(Person person) {
System.out.println(person);
}
});
// 使用lambda表达式对上述代码进行优化
list.stream().filter(person -> person.getAge() >= 18).forEach(System.out::println);
/**
Stream distinct() 返回不包含重复元素的流
Stream limit(long maxSize) 返回不超过给定元素数量的流
Stream skip(long n) 返回丢弃前n个元素后的流
*/
list.stream().skip(2).limit(3).forEach(System.out::println);
- 映射方法
/**
Stream map(Function<? super T,? extends R> mapper) 返回每个处理过元素组成的流
Stream flatMap(Function<? super T,? extends Stream<? extends R>> mapper) 返回每个被替换过元素组成的流,并将所有流合成一个流
*/
list.stream().map(Person::getAge).forEach(System.out::println);
- 排序
/**
Stream sorted() 返回经过自然排序后元素组成的流
Stream sorted(Comparator<? super T> comparator) 返回经过比较器排序后元素组成的流
*/
list.stream().sorted().forEach(System.out::println);
终止操作
- 匹配与查找的常用方法
/**
Optional findFirst() 返回该流的第一个元素
boolean allMatch(Predicate<? super T> predicate) 返回所有元素是否匹配
boolean noneMatch(Predicate<? super T> predicate) 返回没有元素是否匹配
long count() 返回元素的个数
void forEach(Consumer<? super T> action) 对流中每个元素执行操作
*/
boolean b1 = list.stream().noneMatch(new Predicate<Person>() {
@Override
public boolean test(Person person) {
return person.getAge() > 45;
}
});
b1 = list1.stream().noneMatch(person -> person.getAge() > 45);
/*
Optional max(Comparator<? super T> comparator) 根据比较器返回最大元素
Optional min(Comparator<? super T> comparator) 根据比较器返回最小元素
*/
Optional<Person> max = list.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
/**
*/
- 规约
/**
Optional reduce(BinaryOperator accumulator) 返回结合后的元素值
*/
reduce = list.stream().map(Person::getAge).reduce((Integer::sum));
- 收集
/**
<R,A> R collect(Collector<? super T,A,R> collector) 使用收集器对元素进行处理
*/
list.stream().map(Person::getName).collect(Collectors.toList()).forEach(System.out::println);
Optional
- java.util.Optional类可以理解为一个简单的容器,其值可能是null或者不是null,代表一个值存在或不存在。
- 该类的引入很好的解决空指针异常,不用显式进行空值检测。
/**
static Optional ofNullable(T value) 根据参数指定数值来得到Optional类型的对象
Optional map(Function<? super T,? extends U>mapper)根据参数指定规则的结果来得到Optional类型的对象
T orElse(T other) 若该值存在就返回,否则返回other的数值。
*/
String str1 = null;
// Java8中使用Optional类实现空值的处理
// 1.将数据str1装到Optional对象代表的容器中
Optional<String> optional = Optional.ofNullable(str1);
// 2.建立映射关系 使用字符串的长度与字符串建立映射关系
Optional<Integer> integer = optional.map(String::length);
// 3.若字符串为空则打印0,否则打印字符串的数值
System.out.println("integer = " + integer); // Optional.empty
System.out.println(integer.orElse(0)); // 0
JAVA9
模块化
在 module-info.java 文件中,我们可以用新的关键词module来声明一个模块,具体如下:
module 模块名称 {
}
优势
- 减少内存的开销。
- 可简化各种类库和大型应用的 开发和维护。
- 安全性,可维护性,提高性能。
module java9 {
// 实现将com.XXX这个包暴露出去
exports com.XXXX;
}
module java92 {
// 需要java9-01中的模块信息
requires java9;
}
钻石操作符升级
// 实现匿名内部类和钻石操作符的搭配使用
//Comparator<Integer> comparator = new Comparator<Integer>() {
Comparator<Integer> comparator = new Comparator<>() {
@Override
public int compare(Integer o1, Integer o2) {
return 0;
}
};
集合工厂方法
- Java9的List、Set和Map集合中增加了静态工厂方法of实现不可变实例的创建。
- 不可变体现在无法添加、修改和删除它们的元素。
- 不允许添加null元素对象。
实际意义
- 保证线程安全:在并发程序中既保证线程安全性,也大大增强了并发时的效率。
- 被不可信的类库使用时会很安全。
- 如果一个对象不需要支持修改操作,将会节省空间和时间的开销。
- 可以当作一个常量来对待,并且这个对象在以后也不会被改变。
// 创建List类型的不可变实例
List<Integer> list = List.of(1, 2, 3, 4, 5);
//list.add(6); // 编译ok,运行发生UnsupportedOperationException不支持此操作的异常
System.out.println(list); // [1, 2, 3, 4, 5]
Set<Integer> set = Set.of(6, 7, 8);
//set.add(null);// 编译ok,运行发生UnsupportedOperationException不支持此操作的异常
Map<Integer, String> map = Map.of(1, "one", 2, "two");
//map.put(3, "three");// 编译ok,运行发生UnsupportedOperationException不支持此操作的异常
InputStream的增强
InputStream类中提供了transferTo方法实现将数据直接传输到OutputStream中。
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new FileInputStream("d:/a.txt");
outputStream = new FileOutputStream("d:/b.txt");
inputStream.transferTo(outputStream); // 实现数据的复制,底层是read和write方法的调用
} catch (IOException e) {
e.printStackTrace();
}finally{
}
JAVA10
改进的关键点包括一个本地类型推断、一个垃圾回收的增强
局部变量类型推断
- Java10可以使用var作为局部变量类型推断标识符,此符号仅适用于局部变量,增强for循环的索引,以及传统for循环的本地变量。
- 它不能使用于方法形式参数,构造函数形式参数,方法返回类型,字段,catch形式参数或任何其他类型的变量声明
实际意义
- 标识符var不是关键字,只是一个保留的类型名称。这意味着var用作变量,方法名或包名的代码不会受到影响,但var不能作为类或则接口的名字。
- 避免了信息冗余。
- 对齐了变量名。
- 更容易阅读。
// 由初始值可以推断出变量的类型,因此可以使用var取代
//int num = 10;
var num = 10;
//List<Integer> list = new LinkedList<>();
var list = new LinkedList<Integer>();
list.add(10);
for (var v : list) {
System.out.println(v);
}
for (var i = 0; i < 10; i++) {
JAVA11
简化的编译运行操作
- 在Java11中可以使用java命令一次性进行编译和运行操作。
- 执行源文件中的第一个类必须包含主方法。
- 不可以使用其它源文件中自定义的类。
String类新增方法
boolean isBlank() 判断字符串是否为空或只包含空白代码点
Optional map(Function<? super T,? extends U>mapper) 根据参数指定规则的结果来得到Optional类
型的对象
T orElse(T other) 若该值存在就返回,否则返回other的数值。