Java 8 特性学习总结

296 阅读7分钟

这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战

1. interface 中的 static 方法和 default 方法

在 JDK1.8 之前,Java 中针对接口的特性有:接口中可以包含变量和方法。接口中的变量被默认指定为 public static final 类型,常见的就是在接口中定义一些常量值,接口中的方法则默认是 public abstract 类型的抽象方法,这个不需要我们进行显示指定,接口中的成员一律默认是 public 类型。

在 JDK1.8 中针对接口增加两大特性。

1.1 static 方法

在 JDK1.8 中,可以在接口中定义一个或多个静态方法,用法同普通 static 方法类似。

public interface InterfaceA {
	/**
	 * 接口中的静态方法
	 */
	static void showStaticMethod() {
		System.out.println("showStaticMethod");
	}
	
	public static void main(String[] args) {
		InterfaceA.showStaticMethod();
	}
}

注意:接口中的静态方法无法被它的实现类进行继承,即只有当前接口能进行访问。而接口中的静态变量是可以被继承的。

1.2 default 修饰符

类、成员变量或方法没有 private、protected 或 public 修饰符修饰,则默认是 default 类型。在 JDK1.8 中针对接口中方法可以通过 default 修饰符定义,在接口中,增加 default 方法, 是为了既有的 Java 类库的类增加新的功能, 且不必对这些类重新进行设计。 比如, 只需在 Collection 接口中 增加 default Stream stream(), 相应的 Set 和 List 接口以及它们的子类都包含此的方法, 不必为每个子类都重新copy这个方法。

在 Java8 中针对接口内的方法修饰符有:public、default、abstract,default 修饰的方法在接口中进行实现,接口的实现类可以直接调用,如果有需要可以进行重写。

示例:

public interface InterfaceA {
	public static String tag="dsw";
	
	/**
	 * 接口中的静态方法
	 */
	static void showStaticMethod() {
		System.out.println("showStaticMethod");
	}
	
	default void showDefaultMethod() {
		System.out.println("showDefaultMethod");
	}
}

这里我们可以参照 InterfaceA 定义一个实现类。

class InterfaceClass implements InterfaceA {

	@Override
	public void doAbstract() {
		System.out.println("doAbstract");
	}

	@Override
	public void showDefaultMethod() {
		InterfaceA.super.showDefaultMethod();
	}
}

从上面可以看到,实现类是可以针对接口中的 default 方法进行重写来满足自身的需要。同时如果实现多个接口,且接口中拥有相同的 default 方法和 static 方法,则需要通过 接口名.super.方法名进行指定。

2. Lambda 基本使用

在 Java 近年来的版本更新中,重大的版本更新莫过于 Java 5,在 Java 5 的更新中引入了“泛型”、“注解”、“枚举”和“自动拆装箱”等,本次在 Java 8 中引入 Lambda 的操作堪比 Java 5 的版本更新,Lambda 表达式用于替代函数式接口(比如 Runnbale),用于简化程序的复杂性。

同时在 Java 8 的版本中通过 Lambda 表达式增强集合的操作,引入了 ‘java.util.function’ 和 ‘java.util.stream’ 两个包,极大简化针对集合的操作。

Lambda 表达式基本使用

2.1 基本语法

基本语法:

(parameters) -> expression
或
(parameters) ->{ statements; }

Lambda 表达式由参数、-> 和实现主体 三大部分组成。

2.2 常见格式

Lambda 表达式一些常见的格式:

// 1. 不需要参数,返回值为 2  
() -> 2  
  
// 2. 接收一个参数(数字类型),返回其3倍的值  
x -> 3 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

针对具体的接口示例:

public class CreateSecretKey {
	public static void main(String[] args) {
		/**
		 * 无参数 lambda 表达式
		 */
		Runnable runnable = ()->{
			System.out.println("No Parameters");
		};
		/**
		 * 一个参数的 lambda 表达式
		 */
		OneParameter oneParameter = x -> {
			System.out.println("One Param:" + x);
		};
		/**
		 * 两个参数的 lambda 表达式
		 */
		TwoParameters twoParameters = (x, y) -> {
			System.out.println("Two Param:" + x + ":" + y);
		};
		/**
		 * 字符串参数的 lambda 表达式
		 */
		StringParam strParam = str -> {
			System.out.println("String Param:" + str.length());
		};
	}
}

interface OneParameter {
	void oneParam(int one);
}


interface TwoParameters {
	void twoParam(int one, int two);
}

interface StringParam {
	void strParam(String str);
}

2.3 函数式接口

在 Java8 中引入了函数式接口的概念,函数式接口中只能定义一个抽象方法(除了隐含的Object对象的公共方法),这里不包含 default 和 static 修饰的方法。 因此最开始也就做SAM类型的接口(Single Abstract Method)。函数式接口通过注解 FunctionalInterface 进行标识。

比如在 JDK1.8 中的 Runnabhle 接口。

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

在 Java8 中引入了预置的四种函数接口:

  • Function<T,R>:接受一个输入参数,返回一个结果
  • Consumer:接受一个输入参数,无返回结果
  • Predicate:接受一个输入参数,返回一个布尔类型结果
  • Supplier:无参数,返回一个结果

1. Function<T,R> 接口

Function接口 接受一个输入参数T,返回一个结果R。

@FunctionalInterface
public interface Function<T, R> {

    /**
     * 给定一个值,返回处理结果
     */
    R apply(T t);

    /**
     * 获取 function 接口 apply 方法,以 before 函数的 apply 方法结果作为参数
     * @param before
     * @return
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * 返回一个 执行 after 函数对象 apply 方法的 函数对,after 函数参数是当前函数对象 apply 方法执行结果
     * @param after
     * @return
     */
    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;
    }
}

示例: 定义一个 Function 对象。

Function<Integer, String> fun = new Function<Integer, String>() {
	
	@Override
	public String apply(Integer t) {
		return "This is number:" + t;
	}
};

Function 接口方法演示

public static void main(String[] args) {
	Function<Integer, String> fun = new Function<Integer, String>() {
		
		@Override
		public String apply(Integer t) {
			return "This is number:" + t;
		}
	};
	
	Function<Integer, Integer> funCompose = new Function<Integer, Integer>() {
		
		@Override
		public Integer apply(Integer t) {
			return t + 5;
		}
	};
	
	Function<String, String> funAndThen = new Function<String, String>() {
		
		@Override
		public String apply(String t) {
			return "The result:" + t;
		}
	};
	
	String result = fun.apply(1);
	System.out.println(result);
	
	String compose = fun.compose(funCompose).apply(5);
	System.out.println(compose);
	
	String andThen = fun.andThen(funAndThen).apply(8);
	System.out.println(andThen);
}
	
// 输出结果
This is number:1
This is number:10
The result:This is number:8

在上面的演示示例中,我们可以结合 lambda 表达式进行优化。

public static void main(String[] args) {
	Function<Integer, String> fun = new Function<Integer, String>() {
		
		@Override
		public String apply(Integer t) {
			return "This is number:" + t;
		}
	};
	
	String compose = fun.compose((Integer x)->{
		return x+5;
	}).apply(5);
	System.out.println(compose);
	
	String andThen = fun.andThen((String apply)->{
		return "The result:" + apply;
	}).apply(8);
	System.out.println(andThen);
}

// 输出结果
This is number:1
This is number:10
The result:This is number:8

2. Consumer 接口

代表了 接受一个输入参数并且无返回的操作。

@FunctionalInterface
public interface Consumer<T> {

    /**
     *	接收参数执行操作,无返回值
     * @param t the input argument
     */
    void accept(T t);

    /**
     * 限制性 accept 方法,再执行 after 的 accept 方法。
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

示例:

public static void main(String[] args) {
	Consumer<Integer> consumer = new Consumer<Integer>() {
		
		@Override
		public void accept(Integer t) {
			System.out.println("This is accept number:" + t);
		}
	};
	
	consumer.andThen((Integer x)->{
		System.out.println("This is after accept number:" + x);
	}).accept(5);;
}
// 执行结果
This is accept number:5
This is after accept number:5

3. Predicate 接口

输入一个参数,返回一个布尔类型结果。

@FunctionalInterface
public interface Predicate<T> {
    // 执行判断 test 逻辑
    boolean test(T t);
    // 当前 Predicate 和 other 的运算结果进行 and 运算
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    // Preidcate 接口进行取反
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    // 当前 Predicate 和 other 的运算结果进行 or 运算
    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);
    }
}

示例:

public static void main(String[] args) {
	Predicate<Integer> predicate = new Predicate<Integer>() {
		
		@Override
		public boolean test(Integer t) {
			if (t > 5) {
				return false;
			} else {
				return true;
			}
		}
	};
	
	System.out.println("test:" + predicate.test(5));//以 5 计算,返回 true
	System.out.println("negate:" + predicate.negate().test(5)); //进行 test 的取反,为 false
	System.out.println("isEqual:" + Predicate.isEqual(6).test(5));//判断是否相等,不相等,false
	boolean and = predicate.and((Integer x)->{
		if (x >10) {
			return false;
		} else {
			return true;
		}
	}).test(6);
	System.out.println("and:" + and);//and 运算,一真一假为false
	
	boolean or = predicate.or(x ->{
		if (x > 10 ) {
			return false;
		} else {
			return true;
		}
	}).test(6);
	System.out.println("or:" + or);//or 运算,一真一假为true
}
//结果
test:true
negate:false
isEqual:false
and:false
or:true

4. Supplier 接口

无参数返回一个结果。

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

示例:

public static void main(String[] args) {
	Supplier<Integer> supplier = new Supplier<Integer>() {
		
		@Override
		public Integer get() {
			return 5;
		}
	};
	
	System.out.println(supplier.get());
}
//结果