[Java] vivid example detailed interface

Keywords: Java JavaSE

1, What is the interface

My computer has a USB interface. When I want to use the wireless mouse, I just need to insert the USB connector of the wireless mouse into it, and the wireless mouse can be used; When I want to charge my mobile phone, I just need to insert the USB head of the charging cable into it, and the mobile phone starts charging; When I want to get the information on the USB flash drive, insert it into the USB interface and the USB flash drive will be connected to my computer.

This is the interface in our life. If there is no such USB interface on the computer, does it mean that whenever you want to realize the above functions, you need to spend a lot of time building a new port on the computer to realize this function. If you want to realize too many functions, the computer will become a cellular sooner or later, All the above are specially created to realize a certain function.

If it is an example in the code, it should be like this...

A robot company has invented two kinds of robots, robot a and robot B. both robots have something in common, that is, they can speak and have their own names. The different function is that a can walk and B can sing. If you use code, it should be like this...

📑 Code example:

class Robot {
    public String name;
    public Robot(String name) {
        this.name = name;
    }
    public void talking() {
        System.out.println(this.name + "Can talk!");
    }
}
class RobotA extends Robot {
    public RobotA(String name) {
        super(name);
    }
    public void walking() {
        System.out.println(this.name + "Can walk!");
    }
}
class RobotB extends Robot {
    public RobotB(String name) {
        super(name);
    }
    public void singing() {
        System.out.println(this.name + "Can sing!");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        RobotA robotA = new RobotA("robot A");
        robotA.talking();
        robotA.walking();
        RobotB robotB = new RobotB("robot B");
        robotB.talking();
        robotB.singing();
    }
}

🏸 Code result:

Question:

  • If robot A can sing one day, should robot A be modified to add A singing function?

  • If one day Robot B doesn't want to have the function of speaking, should Robot be modified and the function of speaking be deleted, but Robot A can speak? Wouldn't it also be modified together with Robot A?

  • Since there are so many functions, simply write these functions as classes and inherit them all! Inherit all!!! The problem is that a robot has several functions, but Java does not support multi inheritance...

At this critical time, we will introduce the topic object of this section: interface!

Interface is a technology to solve the problem that Java does not support multi inheritance. It is used to describe what a class should do, what functions to implement, and how to implement this function. It is not specified, but the method in the interface is implemented by the class that implements the interface.

A class can implement one or more interfaces. In some cases, it may be required to meet these interfaces. As long as there is such a requirement, the object of the class that implements this interface can be used.

2, Initial interface

Declaration of interface:

[visibility] interface Interface name [extends Other interface names] {
        // Declare variable
        // Abstract method
}

💬 Code interpretation:

  • The interface is decorated by the interface keyword
  • Generally speaking, the methods in the interface cannot have ordinary methods. The methods can only be abstract methods, and the methods in the interface are modified by public abstract by default
  • The member variables in the interface can only be static constants, which are modified by public static final by default
  • Starting from JDK 1.8, the methods in the interface can also be ordinary methods, and these methods are modified by the default keyword, but this usage can exist, but it is rarely used
  • When creating an interface, the interface name generally starts with the capital letter I and is generally named with the adjective part of speech
  • In order to keep the code concise and clear, the symbols of default modification should not be added to the code

Improvement of robot code:

class Robot {
    public String name;
    public Robot(String name) {
        this.name = name;
    }
}
interface IWalking {
    void walking();
}
interface ISinging {
    void singing();
}
interface ITalking {
    void talking();
}
class RobotA extends Robot implements IWalking,ITalking {
    public RobotA(String name) {
        super(name);
    }
    @Override
    public void walking() {
        System.out.println(this.name + "Walking function");
    }
    @Override
    public void talking() {
        System.out.println(this.name + "It has the function of speaking");
    }
}
class RobotB extends Robot implements ISinging {
    public RobotB(String name) {
        super(name);
    }
    @Override
    public void singing() {
        System.out.println(this.name + "It has singing function");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        IWalking iWalking = new RobotA("robot A");
        iWalking.walking();
        ISinging iSinging = new RobotB("robot B");
        iSinging.singing();
    }
}

🏸 Code result:

💬 Code interpretation:

  • Interfaces cannot be instantiated, and they are not inherited by classes, but implemented by classes

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

  1. Declare the class to implement the given interface

  2. Provide definition for all abstract methods in the interface (provide concrete implementation)

To declare a class to implement an interface, you need to use the implements keyword

  • A class can use the implements keyword to implement multiple interfaces, which are separated by commas, so as to achieve the effect similar to multiple inheritance
  • Interfaces and interfaces are maintained by using the extends keyword, which indicates that the interface extends the functions of other interfaces. These interfaces need to be implemented in the class
  • Interfaces can also undergo upward transformation and polymorphism

Summary:

  • The meaning of interface expression is that XXX has XXX characteristics (functions)
  • The advantage of interface is that programmers don't need to know what specific type, but whether this class has some characteristics (functions). For example, not only robots, but also people have the characteristics of speaking, walking and singing, so it's OK to use the human class to implement these interfaces

3, Interface usage instance

3.1 Comparable and Comparator interfaces

We know that if you want to sort an array of basic types, you can use the sort() method under the Arrays class. After sorting with this method, the data in the array will be sorted from small to large.

📑 Code example:

public class TestDemo {
    public static void main(String[] args) {
        int[] array = {3,20,15,4,1};
        System.out.println("Before sorting:" + Arrays.toString(array));
        Arrays.sort(array);
        System.out.println("After sorting:" + Arrays.toString(array));
    }
}

🏸 Code result:

If you want to sort a user-defined type with this method, what is the result? In fact, even if there is no sorting, we should expect that the result is not feasible, because there will be many sorting bases in the user-defined type...

📑 Code example:

class Book {
    public double price;
    public String name;
    public Book(double price, String name) {
        this.price = price;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Book{" +
                "price=" + price +
                ", name='" + name + '\'' +
                '}';
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Book[] books = new Book[3];
        books[0] = new Book(32.3,"C language");
        books[1] = new Book(53.4,"Java Explain in detail");
        books[2] = new Book(23.6,"magical C++");
        System.out.println("Before sorting:" + Arrays.toString(books));
        Arrays.sort(books);
        System.out.println("After sorting:" + Arrays.toString(books));
    }
}

🏸 Code result:

The result shows that there are exceptions in type conversion, so what should I do in order to sort correctly?

Here, the Comparable and Comparator interfaces are involved. These two interfaces correspond to two sorting methods respectively.

First, introduce the Comparable interface

📑 Code example:

class Book implements Comparable<Book>{
    private double price;
    private String name;
    public Book(double price, String name) {
        this.price = price;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Book{" +
                "price=" + price +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    /*public int compareTo(Book o) {
        //Sort from small to large
        return (int) (this.price - o.price);
        //Sort from large to small
        //return (int) (o.price - this.price);
    }*/
    public int compareTo(Book o) {
        return this.name.compareTo(o.name);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Book[] books = new Book[3];
        books[0] = new Book(32.3,"C language");
        books[1] = new Book(53.4,"Java Explain in detail");
        books[2] = new Book(23.6,"magical C++");
        System.out.println("Before sorting:" + Arrays.toString(books));
        Arrays.sort(books);
        System.out.println("After sorting:" + Arrays.toString(books));
    }
}

🏸 Code result:

💬 Code interpretation:

  • Book is a custom type and books is an array of book types
  • Comparable is an interface that has the function of sorting. If the Book type implements the interface, the type has the function of sorting
  • < > is the type name that needs to have sorting function. Here is the Book type
  • After implementing the interface, you need to implement the compareTo method in the interface in the Book class. Compare the current object with O. if the object is less than o, a negative integer is returned; If equal, return 0; Otherwise, a positive integer is returned.
  • If you sort by price, you need to force the type of the comparison result into int. if you sort by name, you need to use the compareTo method

Obviously, through the Comparable interface, we successfully sort the arrays of custom types according to the results we want, and compared with the array sorting of basic types, it can more freely decide whether to sort from small to large or from large to small; However, the disadvantages are also very obvious. This interface is very intrusive to classes. Every time you want to change a comparison method, you need to modify the compareTo method inside the class and formulate new comparison rules. It has great limitations. Therefore, this interface is equivalent to an "internal comparator".

In order to solve this problem, we are now introducing another interface that enables classes to have sorting function - Comparator interface.

📑 Code example:

class Book {
    public double price;
    public String name;
    public Book(double price, String name) {
        this.price = price;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Book{" +
                "price=" + price +
                ", name='" + name + '\'' +
                '}';
    }
}
//Comparator sorted by price
class PriceComparator implements Comparator<Book> {
    @Override
    public int compare(Book o1, Book o2) {
        return (int)(o1.price - o2.price);
    }
}
//Comparator sorted by age
class NameComparator implements Comparator<Book> {
    @Override
    public int compare(Book o1, Book o2) {
        return o1.name.compareTo(o2.name);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Book[] books = new Book[3];
        books[0] = new Book(32.3,"C language");
        books[1] = new Book(53.4,"Java Explain in detail");
        books[2] = new Book(23.6,"magical C++");
        System.out.println("Before sorting:" + Arrays.toString(books));
        PriceComparator priceComparator = new PriceComparator();
        //NameComparator nameComparator = new NameComparator();
        Arrays.sort(books,priceComparator);
        System.out.println("After sorting:" + Arrays.toString(books));
    }
}

🏸 Code result:

💬 Code interpretation:

  • In order to avoid creating too much code (Getter and Setter methods are provided), the two member variables are modified with Public. Generally speaking, in order to strengthen encapsulation, they should be modified with Private
  • When a class does not implement the Comparable interface, we establish a Comparator to sort. The Comparator only needs to implement the Comparator interface
  • To implement the interface, you need to rewrite the compare method to compare the size of the two parameters o1 and o2. o1 is smaller than o2 and returns a negative number; o1 and o2 are equal and return 0; Otherwise, a positive integer is returned.
  • When calling Arrays.sort, the parameters should be passed not only to the custom type array, but also to the comparator

It can be found that using the Comparator interface not only has the advantages of the Comparable interface, but also avoids its disadvantages, that is, the intrusion into the class is serious. For which comparison method you want, you can directly write a new Comparator outside the class. Therefore, this interface is equivalent to an "external Comparator".

3.2 clonable interface

Cloneable interface is a tag interface used to copy objects in Java. This interface is an empty interface. A class implements this interface, indicating that this class can be copied.

📑 Code example:

class Book implements Cloneable{
    public double price = 9.9;
    public String name = "magical JAVA";
   /* @Override
    public String toString() {
        return "Book{" +
                "price=" + price +
                ", name='" + name + '\'' +
                '}';
    }*/
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Book book = new Book();
        System.out.println(book);
        Book book1 = (Book)book.clone();
        System.out.println(book1);
    }
}

🏸 Code result:

After overriding the toString() method

💬 Code interpretation:

  • The Book class implements the Cloneable interface, has the ability to copy, then rewrites the clone method in the Object class in the class, and then calls the clone method of the parent class (Object class) to clone the object successfully.
  • If the interface is not implemented, an exception will be thrown: CloneNotSupportedException
  • The results show that the address of book1 is different from that of book, but the content is the same, indicating that the cloning is successful
  • At this time, the copy is a full copy. Modifying the value in book1 will not affect the value in book

About copying, we have to mention deep copy and shallow copy. In the section of Java explaining arrays, we talk about the copying of arrays, which involves this.
[Java] analyze the use of arrays
There will also be such a problem with object copying. If there is another object in the copied object, there is no way to copy the content of the object in the object with the previous clone method. At this time, the copy is only a shallow copy.

📑 Code example:

class Number{
    public int number = 23;
}
class Book implements Cloneable{
    public double price = 9.9;
    public String name = "magical JAVA";
    public Number num = new Number();
    @Override
    public String toString() {
        return "Book{" +
                "price=" + price +
                ", name='" + name + '\'' +
                ", num.number=" + num.number +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Book book = new Book();
        Book book1 = (Book) book.clone();
        System.out.println("Before modification");
        System.out.println(book);
        System.out.println(book1);
        book1.num.number = 44;
        System.out.println("After modification");
        System.out.println(book);
        System.out.println(book1);
    }
}

🏸 Code result:

💬 Code interpretation:

It can be seen from the results that the content of the object pointed to by num in the book can be changed through the newly copied book1 due to the incomplete copy

If you want to make a deep copy and a full copy of the object, you need to rewrite the clone method again. This time, you need to copy a copy of the object in the object

📑 Code example:

class Number implements Cloneable{
    public int number = 23;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Book implements Cloneable{
    public double price = 9.9;
    public String name = "magical JAVA";
    public Number num = new Number();
    @Override
    public String toString() {
        return "Book{" +
                "price=" + price +
                ", name='" + name + '\'' +
                ", num.number=" + num.number +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Book bookClone = (Book)super.clone();
        bookClone.num = (Number)this.num.clone();
        return bookClone;
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Book book = new Book();
        Book book1 = (Book) book.clone();
        System.out.println("Before modification");
        System.out.println(book);
        System.out.println(book1);
        book1.num.number = 44;
        System.out.println("After modification");
        System.out.println(book);
        System.out.println(book1);
    }
}

🏸 Code result:

💬 Code interpretation:

  • It can be seen from the results that due to the complete copy, there is no way to change the content of the object pointed to by num in the book through the newly copied book1
  • Modifications made:
  1. The Number type also has the ability to copy, implement the Cloneable interface, and then rewrite the clone method in the Object class in the class, then call the clone method of the parent class (Object class).
  2. Override the clone method in the Book type so that the object pointed to by the member in the object is also copied


Over!

Posted by ShaolinF on Sun, 26 Sep 2021 10:46:51 -0700