一.接口的默认方法&静态方法
(1.1)default
1.1.1)定义
在Java8前 接口方法默认是abstract修饰表示抽象方法, 子类必须实现.
Java8提供default修饰词,以允许接口定义一个方法的默认实现
public interface Interface01 {
default void test(){
System.out.println("Interface01");
}
default void test02(){
System.out.println("Interface01");
}
}
1.1.2)方法冲突
public interface Interface02 {
default void test() {
System.out.println("Interface02");
}
}
public class ImplementClass implements Interface01, Interface02 {
}
以上实现编译期就会异常:
com.dxm.test.java8.ImplementClass inherits unrelated defaults for test() from types com.dxm.test.java8.Interface01 and com.dxm.test.java8.Interface02
public class ImplementClass implements Interface01
public class ImplementClass implements Interface01, Interface02 {
@Override
public void test() {
Interface01.super.test();
}
}
(1.2)静态方法
Java8+接口中可以定义静态方法. 一般充当工具方法
public class Collections {
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
}
Lambda表达式
允许函数当作一个参数
public void test(String s) {
System.out.println("s");
}
将以上函数转换成一个参数.将无用字段,类型,修饰词省略
(s)-> {
System.out.println("s");
};
参数的类型? 所有的lambda都是接口类型, 并且接口只有一个抽象方法. 接口可以用@FunctionalInterface修饰.编译约束接口规范
@FunctionalInterface
public interface Interface02 {
void test(String s);
}
Interface02 i = (s)-> {
System.out.println("s");
};
二.函数接口
方便使用lambda来定义函数. java8提供了一些函数接口
(2.1)Consumer
消费类型接口
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
另外也有IntConsumer等不同参数类型的Consumer
(2.2)Supplier
供应类型接口
@FunctionalInterface
public interface Supplier<T> {
T get();
}
另外也有BoolenConsumer等不同参数类型的Supplier
(2.3)Predicate
断言类型接口
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
(2.4)Function
功能类型接口
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
(2.5)UnaryOperator
计算类型接口, 用于补充Function
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
UnaryOperator<Integer> u = (i)->i+1;
三.方法引用
方法的引用是简化已存在方法的lambda表达式的简写
语法:
(3.1)静态方法引用
public class ImplementClass {
static String innerTest(String s) {
return s;
}
public static void main(String[] args) {
Function<String, String> function = ImplementClass::innerTest;
}
}
(3.2)实例方法引用
public class ImplementClass {
String innerTest(String s) {
System.out.println(s);
return s;
}
public static void main(String[] args) {
ImplementClass implementClass = new ImplementClass();
Function<String, String> function = implementClass::innerTest;
}
}
(3.3)特定类型的任意对象的实例方法引用
public class ImplementClass {
boolean innerTest(ImplementClass s2) {
return s2.equals(s2);
}
public static void main(String[] args) {
BiFunction<ImplementClass, ImplementClass, Boolean> biFunction = ImplementClass::innerTest;
}
}
(3.4)构造方法引用
public class ImplementClass {
public static void main(String[] args) {
Supplier<ImplementClass> supplier = ImplementClass::new;
}
}
四.Stream
Java8允许通过Stream流的方式处理数据集合
(4.1)流只能遍历一次. 下一次必须重新获取流
下面的code运行期会报
stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
Stream<Integer> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println);
}
五.Optional
为了方便处理空指针问题.java8引入了Optional.
Optional是一个容器,可以保持T类型的对象,也可以保存null空值对象
(5.1)创建一个optional对象
of:只能创建入参非空的容器
ofNullable:可以创建非空的或者null的容器
public static void main(String[] args) {
TestClass test = new TestClass();
Optional<TestClass> testOptional = Optional.of(test);
test = null;
Optional<TestClass> testNullOptional = Optional.ofNullable(test);
}
(5.2)Optional使用
isPresent() : 判断是否存在
get() : 获取容器内对象, 若容器内对象为null.会报错
if(testOptional.isPresent()){
TestClass testClass = testOptional.get();
}
map : 返回映射后的Optional容器
orElse : 非空返回容器内对象,否则返回参数对应对象
orElseGet : 非空返回容器内对象,否则返回方法创建的对象
//ofNullable
Optional<TestClass> testOptional = Optional.ofNullable(test);
//orElse
TestClass testClass = testOptional.orElse(new TestClass());
//orElseGet
testClass = testOptional.orElseGet(TestClass::new);
//map
Optional<TestClass2> testClass21 = testOptional.map(TestClass::getTestClass2);
(5.3)防止空指针的写法比较
原始写法:
TestClass test = new TestClass();
if(test == null){
hashCode = 12345;
}else {
if(test.getTestClass2() == null){
hashCode = 12345;
}else {
hashCode = test.getTestClass2().hashCode();
}
}
Optional写法:
TestClass test = new TestClass();
Optional<TestClass> testOptional = Optional.ofNullable(test);
Integer hashCode = testOptional.map(TestClass::getTestClass2).map(TestClass2::hashCode).orElse(12345);