1. The interface

Interfaces are used to describe what classes should do, not specify how they should do it. A class can implement one or more interfaces.

1.1 concept

An interface is not a class, but rather a set of requirements for classes that want to conform to that interface.

Public interface Comparable<T>{int compareTo(T other); } // x<y returns a negative number when x.compareTo(y) is called; X ==y returns 0; X >y returns a positive number.Copy the code

All methods in an interface are automatically public methods, and you do not have to provide the keyword public when declaring methods in an interface.

Interfaces can contain multiple methods, and constants can be defined. But there will never be an instance field.

There are usually two steps to getting a class to implement an interface:

  1. Declare a class to implement the given interface.
  2. Provides definitions for all methods in the interface.
public class Employee implements Comparable { @Override public int compareTo(Object otherObj) { Employee other = (Employee) otherObj; return Double.compare(salary,other.salary); }} Public class Employee implements Comparable<Employee> {@override public int compareTo(Employee other) { return Double.compare(salary,other.salary); }}Copy the code

1.2 Interface Attributes

// Interfaces are not classes. Specifically, you cannot instantiate an interface using the 'new' operator: x = new Comparable(...) ; Comparable x; // we cannot construct an interface object, but we can declare an interface variable: Comparable x; // The interface variable must refer to the class object that implements the interface x = new Employee(...) ; // Use instanceof to check whether an object implements a specific interface system.out.println (x instanceof Comparable); //trueCopy the code

Like establishing an inheritance hierarchy for a class, you can extend the interface.

// define an interface called Moveable: public interface Moveable{void move(double x, double y); } public interface hw-powered extends Moveable{double milesPerGallon();} public interface hw-powered extends Moveable{double milesPerGallon(); double SPEED_LIMIT = 95; // Fields in an interface are always public static final, just as methods in an interface are automatically set to publicCopy the code

1.3 Interfaces and Abstract Classes

abstract class Comparable{ public abstract int compareTo(Object other); } class Employee extends Comparable{ public int compareTo(Object other){ ... }} // An implementation of CompareTo methods can be provided using abstract classes, but only one class can be extended per classCopy the code

1.4 Static and private methods

In Java 8, static methods are allowed to be added to the interface. In theory, there is no reason why this should be illegal, except that it defeats the purpose of interfaces as abstract specifications.

So far, the usual practice has been to put static methods in adjoint classes. In the standard library, there are pairs of interfaces and utility classes, such as Collection/Collection or Path/Paths.

Public static Path get(String first, String... more){} Path path = Paths.get("jdk-12", "conf", "sec"); //class System.out.println(path); // static Path of(String first, String first... more){} Path of = Path.of("jdk-12", "conf", "sec"); //interface System.out.println(of); //jdk-12\conf\secCopy the code

As a result, the Paths class is no longer necessary, and similarly, there is no reason to provide an accompanying class for utility methods when implementing their own interfaces.

In Java 9, the overall method of an interface can be private. Private methods can be static or instance methods. Because private methods can only be used within the methods of the interface itself, their use is limited and can only be used as auxiliary methods to other methods in the interface.

1.5 Default Methods

You can provide a default implementation for interface methods. Such a method must be marked with the default modifier.

public interface Comparable<T>{ default int compareTo(T other){ return 0; }} // However, this is not very useful; every implementation overrides this method. In some cases, the default method can be useful. // The Iterator interface is used to access elements in a data structure. Public interface Iterator<E>{Boolean hasNext(); E next(); / / if you want to traverse the access data structures are read-only, don't tube the remove method, the default default exception: a void the remove () {throw new UnsupportedOperationException (" remove "); Public interface Collection {int size(); default boolean isEmpty() { return size() == 0; }}Copy the code

An important use of the default method is “interface evolution”. Take the Collection interface, which has been part of Java for many years. Suppose a long time ago a class was provided that implemented this interface:

public class Bag implements Collection
Copy the code

In Java 8, a stream method was added to this interface. Assuming that this method is not a default, the Bag class will not compile because it does not implement the new method. Adding a non-default method to an interface does not guarantee “source code compatibility”. However, assuming you don’t recompile the class and just use the original JAR file containing the class, the class will still load normally. However, if the program calls the Stream method on a Bag instance, an AbstractMethodError will appear

Implementing the method as a default method solves both of these problems. The Bag class will compile properly again. If the class is loaded directly without recompilation and the Stream method is called on a Bag instance, the collection.stream method is called, which is the default method.

1.6. Resolve default method conflicts

What happens if you define a method as the default method in one interface, and then define the same method in a superclass or another interface? Java has rules to address these ambiguities:

  1. The superclass takes precedence. If the superclass provides a concrete method, default methods with the same name and argument types are ignored.
  2. Interface conflict. If one interface provides a default method and another interface provides a method with the same name and parameter type (whether default or not), this method must be overridden to resolve the conflict.
Interface Person {// Provide the default implementation default String getName() {return ""; }} interface Named {// Regardless of whether a default implementation is provided. // If at least one interface provides an implementation, the compiler will report an error. String getName(); // default String getName() { // return getClass().getName() + "_" + hashCode(); //}} class Student implements Person, Named {// @override public String getName() {return person.super.getName (); }} // If the extension superclass implements an interface at the same time and inherits the same methods from the superclass and interface. In this case, only superclass methods are considered, and all default methods in the interface are ignored. class Student extends Person implements Named{... }Copy the code

1.7 Interfaces and Callback

Callbacks are a common programming pattern. In this mode, you can specify the action that should be taken when a particular event occurs.

public class TimerTest { public static void main(String[] args) { TimePrinter timePrinter = new TimePrinter(); Timer(int delay, ActionListener listener) Timer Timer = new Timer(1000, timePrinter); // Start timer. Once started, the timer calls the listener's actionPerformed timer.start(); // Stop the timer. Once stopped, the timer will no longer call the listener's actionPerformed // timer.stop(); // Static void showMessageDialog(Component parentComponent, Object Message) // Displays a dialog box with a prompt message and OK button. This dialog box is located in the center of the parentComponent. Null display screen central JOptionPane. ShowMessageDialog (null, "Quit the program?" ); System.exit(0); } } class TimePrinter implements ActionListener { @Override public void actionPerformed(ActionEvent actionEvent) { System.out.println("at the tone,the time is" + Instant.ofEpochMilli(actionEvent.getWhen())); / / Toolkit. GetDefaultToolkit () to obtain the default toolbox, beep () Toolkit. The sound of the bell getDefaultToolkit (). The beep (); }}Copy the code

1.8 the Comparator interface

Because the String class implements the Comparable

interface, and because the compareTo method overridden in the String class compares strings in lexicographical order. But if you want to sort strings by increasing length rather than by fields, you can’t change the String class. To handle this, the arrays.sort method has a second version that takes as arguments an array and a Comparator, which is an instance of a class that implements the Comparator interface.

public interface Comparator<T> { int compare(T var1, T var2); } // Define a class that implements the Comparator<String> interface, LengthComparator <String> {@override public int compare(String s, String s); String t1) { return s.length() - t1.length(); } } String[] words = {"shinobu", "asd", "gxsb"}; Arrays.sort(words,new LengthComparator()); for(String s : words) System.out.print(s); //asd gxsb shinobuCopy the code

2. Lambda expressions

Lambda expressions are used to create blocks of code that can be executed at some point in the future. By using lambda expressions, you can represent code that uses callbacks or mutable behavior in a neat and concise way

2.1 concept

A lambda expression is a transitive block of code that can be executed once or more later.

class LengthComparator implements Comparator<String> { @Override public int compare(String s, String t1) { return s.length() - t1.length(); } } String[] words = {"shinobu", "asd", "gxsb"}; Arrays.sort(words,new LengthComparator()); // Here the compare method is not called immediately. In fact, sort calls compare until the array is sorted, rearranging elements whenever they are not in the right order. // Pass a block of code to an object that will be called at some future event.Copy the code

2.2 grammar

First.length () -second.length () // Need to specify the types of first and second (String first,String second) -> First.length () -second.length () // If the computation to be performed cannot be placed in an expression, you can put the code in {} the same way. Return (String first, String second) -> {if (first.length() < second.length()) return -1; else if (first.length() > second.length()) return 1; Else return 0} // Even if lambda expressions have no arguments, empty parentheses are provided, just as if lambda methods have no arguments () -> {for (int I = 0; i < 100; i++) { System.out.println(i); }} // If the argument type of a lambda expression can be derived, the type can be ignored. Comparator<String> comp = (first, second) -> first.length(); // If the method has only one argument and the type of the argument can be deduced, ActionListener Listener = event -> system.out.println (" The time is" + instant.ofePochmilli (event.getWhen()))); // There is no need to specify the return type of the lambda expression. Lambda return types are always derived from context (String first,String second) -> first.length() -second.length (); / /!!!!!! But it is illegal for a lambda expression to return a value on some branches and none on others. (int x) -> { if (x >= 0) return 1; }Copy the code
String[] planets = {"Shinobu", "Ads", "Gxsb", "Mars", "Inori"}; System.out.println(Arrays.toString(planets)); System.out.println("Sorted in dictionary order:"); Arrays.sort(planets); System.out.println(Arrays.toString(planets)); System.out.println("Sorted by length:"); Sort (planets, (first, sencod) -> first.length() -sencod.length ()); System.out.println(Arrays.toString(planets)); Timer = new Timer(1000, event -> system.out.println (" The time is" + new Date()))); timer.start();Copy the code

2.3 Functional interfaces

Lambda expressions are compatible with Java’s many interfaces that encapsulate blocks of code.

For interfaces that have only one abstract method, a lambda expression can be provided when an object of that interface is needed. This interface is called a functional interface

// arrays. sort requires an instance of a Comparator. When a Compartor is an interface that has only one method, Arrays. Sort (words, (first,second)->first.length()-second.length()); // Underneath, the arrays.sort method receives an object of a class that implements a Compartor<String>. Calling the Compare method on this object executes the body of the lambda expression. // The management of these objects and classes is entirely implementation-dependent and can be much more efficient than traditional inline classes. // It is best to think of a lambda expression as a function, not an object, and to accept that lambda expressions can be passed to functional interfaces.  Timer timer = new Timer(1000, event -> { System.out.println("at the tone,the time is " + Instant.ofEpochMilli(event.getWhen())); Toolkit.getDefaultToolkit().beep(); }); // Do the following:  class TimePrinter implements ActionListener { @Override public void actionPerformed(ActionEvent actionEvent) { System.out.println("at the tone,the time is" + Instant.ofEpochMilli(actionEvent.getWhen())); Toolkit.getDefaultToolkit().beep(); } } Timer timer = new Timer(1000, new TimePrinter());Copy the code

Can’t takelambdaThe expression is assigned to typeObjectThe variable,ObjectNot a functional interface

To do something with lambda expressions, remember the purpose of the expression and create a specific functional interface for it. The java.util.function package has an interface that’s particularly useful for Predicate:

public interface Predicate<T>{
    boolean test(T t);
    //additional default and static methods
}
Copy the code

The ArrayList class has a removeIf method that takes a Predicate. This interface is specifically used to pass lambda expressions. For example, the following statement removes all null values from an arraylist:

list.removeIf(e -> e == null);
Copy the code

Another useful functional interface is Supplier:

public interface Supplier<T>{
    T get();
}
Copy the code

The Supplier has no arguments and generates a value of type T when called. Providers are used to implement lazy computing. Some methods call the provider only if they need a value.

2.4 Method Reference

Sometimes lambda expressions involve a method. For example,

// Suppose you want to print this event object whenever a timer time occurs. Timer timer = new Timer(1000, event -> System.out.println(event)); // However, it would be better to pass println to the Timer constructor: Timer Timer = new Timer(1000, system.out ::println); // The expression System.out::println is a method reference that instructs the compiler to generate an instance of a functional interface and override the interface's abstract methods to call the given method. In this example, an ActionListener is generated, and its actionPerformed(ActionEvent e) method calls System.out.println(e).Copy the code

In another example, imagine that you want to sort strings regardless of the case of the letters. We can pass the expression:

Arrays.sort(planets, String::compareToIgnoreCase);
Copy the code

2.5 Constructor references

3. The inner classes

Inner classes are defined inside another class, and their methods can access the fields of the outer class that contains them. Inner classes are useful when designing collections of classes that have reciprocal writing relationships.

  • Inner classes can be hidden from other classes in the same package;
  • Inner class methods can access data in the scope in which the class is defined, including data that would otherwise be private.

In fact, an object of an inner class always has an implicit object that points to the object of the outer class that created it. This reference is not visible in the definition of the inner class,

3.1 Local inner classes

When an inner class is used only once, you can locally define a class in a method called a local class. Local classes cannot be declared with access specifiers. The scope of a local class is limited to the block in which it is declared. Local classes are completely hidden from the outside world.

3.2 Anonymous inner classes

When using local inner classes, you can usually go one step further. If you want to create only one object of a class, you do not need to specify a name for the class. Such a class is called an anonymous inner class.

// Create a new object for a class that implements the ActionListener interface, ActionPerformed // Define var listen = new ActionListener(){public void actionPerformed(ActionEvent event){...  }}; var timer = new Timer(interval, listener); timer.start(); // Generally, the syntax is as follows: // New SuperType(construction parameter){// inner class methods and data //} The inner class implements this interface. //SuperType can also be a class, if so, the inner class extends the class.Copy the code
Var timer = new timer (interval, event -> {... }); timer.start();Copy the code

3.3 Static inner Classes

Sometimes, inner classes are used just to hide a class inside another class, and there is no need for the inner class to have a reference to the enclosing class object. To do this, declare the inner class static so that the reference is not generated.