This is the 28th day of my participation in the August Text Challenge.More challenges in August

1. Static method and default method in interface

Prior to JDK1.8, Java had features for interfaces that could contain variables and methods. Variables in the interface are specified as public static final by default. It is common to define constant values in the interface. Methods in the interface are specified as abstract methods of type Public Abstract by default. Members in interfaces are of type public by default.

Two major features have been added for interfaces in JDK1.8.

1.1 the static method

In JDK1.8, you can define one or more static methods in an interface that are used similarly to normal static methods.

public interface InterfaceA {
	/** * static method */ in interface
	static void showStaticMethod(a) {
		System.out.println("showStaticMethod");
	}
	
	public static void main(String[] args) { InterfaceA.showStaticMethod(); }}Copy the code

Note: Static methods in an interface cannot be inherited by their implementation classes, that is, only the current interface can access them. Static variables in interfaces can be inherited.

1.2 Default modifier

Classes, member variables, or methods that are not decorated with private, protected, or public modifiers default to type default. In JDK1.8, methods in interfaces can be defined using the default modifier. The default method is added to the interface to add new functionality to existing Java class library classes without having to redesign them. For example, simply add default Stream Stream () to the Collection interface, and the corresponding Set and List interfaces and their subclasses contain this method. You don’t have to re-copy the method for each subclass.

In Java8, there are public, default, and abstract method modifiers in an interface. The default method modifiers are implemented in the interface, and the implementation class of the interface can be called directly or overridden if necessary.

Example:

public interface InterfaceA {
	public static String tag="dsw";
	
	/** * static method */ in interface
	static void showStaticMethod(a) {
		System.out.println("showStaticMethod");
	}
	
	default void showDefaultMethod(a) {
		System.out.println("showDefaultMethod"); }}Copy the code

Here we can define an implementation class with reference to InterfaceA.

class InterfaceClass implements InterfaceA {

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

	@Override
	public void showDefaultMethod(a) {
		InterfaceA.super.showDefaultMethod(); }}Copy the code

As you can see above, the implementation class can override the default method in the interface to meet its own needs. If multiple interfaces have the same default and static methods, you need to use the interface name. Super. Method name is specified.

2. Basic use of Lambda

The introduction of Lambda in Java 8 is comparable to that in Java 5, which introduced “generics,” “annotations,” “enumerations,” and “auto-unboxing.” Lambda expressions are used instead of functional interfaces (such as Runnbale) to simplify programs.

At the same time, in Java 8, operations on collections were enhanced through Lambda expressions, and two packages’ java.util.function ‘and’ java.util.stream ‘were introduced, greatly simplifying operations on collections.

Lambda expressions are basically used

2.1 Basic Syntax

Basic syntax:

(parameters) -> expression
或
(parameters) ->{ statements; }
Copy the code

Lambda expressions consist of three parts: parameters, ->, and implementation body.

2.2 Common Formats

Some common forms of Lambda expressions are:

// 1. No argument is required and the return value is 2() - >2  
  
// 2. Take a parameter (numeric type) and return three times its value
x -> 3 * x  
  
// 3. Take two arguments (numbers) and return their difference(x, y) -> x -- y// 4. Accept two ints and return their sum
(int x, int y) -> x + y  
  
// 5. Take a string object and print it on the console without returning any value (looks like returning void)
(String s) -> System.out.print(s)
Copy the code

Examples of specific interfaces:

public class CreateSecretKey {
	public static void main(String[] args) {
		/** * lambda expression without arguments */
		Runnable runnable = ()->{
			System.out.println("No Parameters");
		};
		/** * a lambda expression for one argument */
		OneParameter oneParameter = x -> {
			System.out.println("One Param:" + x);
		};
		/** * Lambda expression for two arguments */
		TwoParameters twoParameters = (x, y) -> {
			System.out.println("Two Param:" + x + ":" + y);
		};
		/** * Lambda expressions for string arguments */
		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);
}
Copy the code

2.3 Functional interfaces

In Java8, the concept of a functional interface was introduced, in which only one abstract method can be defined (except for the implicit public method of an Object Object). Methods with default and static modifications are not included. So we started with a SAM type interface (Single Abstract Method). Functional interfaces are identified by annotations to functional Interfaces.

Such as the Runnabhle interface in JDK1.8.

@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(a);
}
Copy the code

In Java8, four types of function interfaces are introduced with presets:

  • Function

    : takes an input argument and returns a result
    ,r>
  • Consumer: Accepts an input parameter with no result returned
  • Predicate: Takes an input parameter and returns a Boolean result
  • Supplier: no argument, returns a result

1. The Function < T, R > interface

The Function interface takes an input parameter T and returns a result R.

@FunctionalInterface
public interface Function<T.R> {

    /** * given a value, return the result */
    R apply(T t);

    /** * get the apply method of the function interface, and take the result of the apply method of the function as argument *@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));
    }

    /** * returns a function pair that executes the apply method on the after function object. The argument after is the result of the apply method on the current function object@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(a) {
        returnt -> t; }}Copy the code

Example: Define a Function object.

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

Function interface method demo

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);
}
	
// Output the result
This is number:1
This is number:10
The result:This is number:8
Copy the code

In the demo example above, we can optimize with lambda expressions.

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);
}

// Output the result
This is number:1
This is number:10
The result:This is number:8
Copy the code

2. Consumer interface

Represents an operation that takes an input parameter and returns nothing.

@FunctionalInterface
public interface Consumer<T> {

    /** * The operation is performed with no return value *@param t the input argument
     */
    void accept(T t);

    /** * restrict the accept method, and then execute the accept method after. *@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); }; }}Copy the code

Example:

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);;
}
// Execution result
This is accept number:5
This is after accept number:5
Copy the code

3. The Predicate interface

Enter a parameter and return a Boolean result.

@FunctionalInterface
public interface Predicate<T> {
    // Execute the test logic
    boolean test(T t);
    // The result of the current Predicate and other operations is and
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    // Preidcate Indicates that the interface is reversed
    default Predicate<T> negate(a) {
        return(t) -> ! test(t); }// The result of the current Predicate and other operations is the or operation
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    // Check whether it is equal
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null== targetRef) ? Objects::isNull : object -> targetRef.equals(object); }}Copy the code

Example:

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));// Evaluates to 5 and returns true
	System.out.println("negate:" + predicate.negate().test(5)); // set test to false
	System.out.println("isEqual:" + Predicate.isEqual(6).test(5));// Check whether it is equal, not equal, false
	boolean and = predicate.and((Integer x)->{
		if (x >10) {
			return false;
		} else {
			return true;
		}
	}).test(6);
	System.out.println("and:" + and);// And, true and false are false
	
	boolean or = predicate.or(x ->{
		if (x > 10 ) {
			return false;
		} else {
			return true;
		}
	}).test(6);
	System.out.println("or:" + or);// True and false are true
}
/ / the result
test:true
negate:false
isEqual:false
and:false
or:true
Copy the code

4. : Supplier interface

Returns a result with no arguments.

@FunctionalInterface
public interface Supplier<T> {

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

Example:

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