Interface Overview
Interface is a reference type in the Java language and a "collection" of methods. Therefore, the interior of the interface is mainly to define methods, including constants, abstract methods (JDK 7 and before), default methods and static methods (JDK 8), and private methods (jdk9). There can be no other members in the interface, no constructor and no initialization block, because there are no member variables to initialize in the interface. The definition of interface, which is similar to the way of defining classes, but uses the interface keyword. It will also be compiled into Class file, but it must be clear that it is not a class, but another reference data type. Interface, which cannot create objects, but can be implemented (similar to being inherited). A class that implements an interface (which can be regarded as a subclass of the interface) needs to implement all the abstract methods in the interface. After creating this class object, you can call the method, otherwise it must be an abstract class.
Declaration format of interface
An interface is a specification, which defines a set of rules, reflecting the real world "if you are / want to..., you must be able to..." My thoughts. Inheritance is a yes / no is-a relationship, while interface implementation is a yes / no has-a relationship.
Code example
public interface IA { // Constants (jdk7 and before) are decorated with the public static final keyword, which can be omitted public static final int A = 18; int B = 20; // Abstract methods (jdk7 and before) are decorated with the public abstract keyword. Both keywords can be omitted public abstract void method1(); void method2(); // The default method (jdk8) is decorated with the keyword public default. Public can be omitted and default cannot be omitted public default void method3() { System.out.println("I am the default method 1"); } default void method4() { System.out.println("I am the default method 2"); } // The static method (jdk8) is decorated with the keyword public static. Public can be omitted and static cannot be omitted public static void method5() { System.out.println("I am static method 1"); } static void method6() { System.out.println("I am static method 2"); } // The private method (jdk9) is decorated with the private keyword. Private cannot be omitted private static void method7() {//Private static method System.out.println("Private static method method5"); } private void method8() {//Common private method System.out.println("Private non static method method6"); } }
Implementation interface
Interface, which cannot create objects, but can be implemented (similar to being inherited). The relationship between class and interface is implementation relationship, that is, class implements interface. This class can be called implementation class of interface or subclass of interface. The actions implemented are similar to inheritance and the format is similar, but the keywords are different. The implementation uses the implements keyword. If a function is added by a class, you can define the additional function in the interface and implement it by this class
Implementation interface syntax format
be careful:
- If the implementation class of the interface is a non abstract class, you must override all abstract methods in the interface.
- The default method can be retained or overridden. When rewriting, do not write the word default. It is only used to represent the default method in the interface, and there is no concept of default method in the class
- Static methods cannot be overridden
Code example
Define interface
public interface IA { //static const long MAX_SPEED = 500*1024*1024;//500MB/s //Abstract method void read(); void write(); //Default method public default void start(){ System.out.println("start"); } public default void stop(){ System.out.println("end"); } //Static method public static void show(){ System.out.println("USB 3.0 It can read and write at full speed synchronously"); } }
Define implementation classes
public class IAimp implements IA { //Rewrite / implement the abstract method of the interface, [required] @Override public void read() { System.out.println("Read data"); } @Override public void write() { System.out.println("Write data"); } //Override the default method of the interface, [optional] //When overriding the default method, the default word is removed @Override public void stop() { System.out.println("Clean up the hidden recycle bin in the hard disk, and then finish"); } }
Access characteristics of members in interface
Constants in the interface: mainly for direct use of the interface. We can access through interface name, implementation class object and implementation class. It is recommended to use interface name to access
interface A { public static final double PI = 3.1415926; } class Aimp implements A { //The constants in the interface are inherited by the implementation class } public class Test { public static void main(String[] args) { // It is recommended to access by interface name System.out.println(A.PI); System.out.println(Aimp.PI); System.out.println(new Aimp().PI); } }
Why can it be accessed through the implementation class and implementation class object? Because the constants in the interface are modified by static and inherited by the implementation class.
Abstract method in interface: it is rewritten by implementation class and can only be called through implementation class object
interface A{ void eat(); } class Aimp implements A{ @Override public void eat() {//Abstract methods in rewriting interfaces System.out.println("Eat something"); } } public class Test { public static void main(String[] args) { //Create an implementation class object and call the rewritten abstract method new Aimp().eat(); } }
Default method in the interface: it is inherited by the implementation class. It can be called directly in the implementation class, and the implementation class object can also be called directly. If the implementation class is overridden, the overridden default method will be executed. If it is not overridden, the default method in the interface will be executed
interface A{ default void eat(){ System.out.println("Parents eat Wowotou"); } default void sleep(){ System.out.println("sleep"); } } class Aimp implements A{ @Override public void eat() {//Override the default method in the interface sleep();//Directly call the default method in the parent class System.out.println("Subclasses eat white rice"); } } public class Test { public static void main(String[] args) { //Create an implementation class object and call the overridden default method new Aimp().eat(); } }
Static method in interface: it can only be called with "interface name". It cannot be called through the object implementing the class
interface A { static void sleep() {//Static method System.out.println("sleep"); } } class Aimp implements A { } public class Test { public static void main(String[] args) { //Use "interface name" directly Just call A.sleep(); // new Aimp().sleep(); Cannot be called through an object that implements a class } }
Private methods in the interface: they can only be called directly in the interface and cannot be inherited by the implementation class. Because there are specific implementation methods such as default methods and static methods, multiple methods may be extracted by common code, and the methods extracted from these common code only want to be used inside the interface, so private methods are added.
Multiple implementation of interface
In the inheritance system, a class can inherit only one parent class. For interfaces, a class can implement multiple interfaces, which is called multiple implementation of interfaces. Moreover, a class can inherit a parent class and implement multiple interfaces at the same time.
What if multiple parent interfaces have the same constants or methods in conflict during multiple implementations?
Conflict of public static constants: if multiple parent interfaces have the same constants, the implementation class cannot inherit. In short: you cannot call the same constant through an implementation class or an implementation class object because the reference is ambiguous.
interface A { public static final int NUM1 = 10; } interface B { public static final int NUM1 = 20; public static final int NUM2 = 30; } class ABimp implements A, B { } public class Test { public static void main(String[] args) { System.out.println(A.NUM1); //10 System.out.println(B.NUM1);//20 System.out.println(B.NUM2);//30 //System.out.println(ABimp.NUM1); error System.out.println(ABimp.NUM2);//30 } }
In general, constants in the parent interface will be inherited by subclasses unless there is a constant conflict problem.
Conflict of public abstract methods: when there are multiple abstract methods in the interface, the implementation class must override all abstract methods. If the abstract method in multiple parent interfaces has the same name, it only needs to be rewritten once.
interface A{ public abstract void method(); } interface B{ public abstract void method(); } class Imp implements A,B{ @Override public void method() { System.out.println("Implement class overrides"); } } public class Test { public static void main(String[] args) { /* Conflict of public abstract methods: the implementation class only needs to rewrite one */ } }
Conflict of public default methods: when a class implements multiple interfaces at the same time and multiple interfaces contain default methods with the same method signature, the implementation class must rewrite the final version once
interface A{ public default void method(){ System.out.println("A Default method of interface method"); } } interface B{ public default void method(){ System.out.println("B Default method of interface method"); } } class Imp implements A,B{ @Override public void method() { System.out.println("Default method to implement class overrides"); } } public class Test { public static void main(String[] args) { /* Conflict of public default methods: the implementation class must rewrite the final version once */ Imp imp = new Imp(); imp.method(); } }
Conflict of public static methods: static methods directly belong to the interface and cannot be inherited, so there is no conflict
Conflict of private methods: private methods can only be used directly in this interface without conflict
Interface and interface relationship
Relationship between interfaces: interfaces can be "inherited" from another "interface", and can be "multi inherited".
interface A { } interface B { } interface C1 extends A { } // Single inheritance interface C2 extends A, B { } // Multiple inheritance interface C3 extends C2 { } // Multilayer inheritance public class Test { public static void main(String[] args) { /* - Relationship between interfaces: inheritance relationship Single inheritance: interface A inherits interface B Multiple inheritance: interface A inherits interface B, interface C Multi layer inheritance: interface A inherits interface B, interface B, and interface C */ } }
When an interface inherits an interface, what happens if there are multiple parent interfaces with the same constants or methods in conflict?
- Conflict of public static constants: the child interface cannot inherit the conflicting constants in the parent interface
- Conflict of public abstract methods: the sub interface will inherit only one conflicting abstract method
- Conflict of public default methods: the conflicting default methods must be rewritten once in the sub interface. The implementation class rewrites the default methods in the interface without adding default. If the sub interface rewrites the default methods in the parent interface, it must add default.
- Public static methods and private methods: no conflict, because static methods directly belong to the interface and can only be accessed directly using this interface, while private methods can only be accessed in the interface without conflict
When the implementation class inherits the parent class and implements the interface, what if there is a conflict between the same constant or method in the parent interface and the parent class?
- Conflict between public static constants of parent class and interface: subclasses cannot inherit conflicting constants
class Fu{ public static final int NUM1 = 10; public static final int NUM2 = 100; } interface A{ public static final int NUM1 = 20; } class Zi extends Fu implements A{ } public class Test { public static void main(String[] args) { /* Conflict of public static constants: subclasses cannot inherit conflicting constants */ //System.out.println(Zi.NUM1);// Compilation error System.out.println(Zi.NUM2); } }
- Abstract method conflict between parent class and interface: subclass must override the conflicting abstract method once
abstract class Fu{ public abstract void method(); } interface A{ public abstract void method(); } class Zi extends Fu implements A{ @Override public void method() { System.out.println("Zi Override conflicting abstract methods"); } } public class Test { public static void main(String[] args) { /* Conflict of public abstract methods: subclasses must override conflicting abstract methods once */ Zi zi = new Zi(); zi.method(); } }
- Conflict between the public default methods of the parent class and the interface: the member method in the parent class has the same name as the default method in the interface, and the child class selects the member method of the parent class nearby.
- Public static methods of parent class and interface: subclasses can only access the static methods of the parent class
- Private methods of parent class and interface: subclasses cannot be accessed, and there is no conflict
Application scenario:
- Additional functions: defined in the interface and implemented by the implementation class. If a function is added by a class, the additional function can be defined in the interface and implemented by this class
- Common functions: define in the parent class and let the subclasses inherit. If a method in a parent class has different implementations for all subclasses, the method should be defined as an abstract method, so the parent class is an abstract class (the parent class is generally an abstract class)
polymorphic
Polymorphism is the third feature of object-oriented after encapsulation and inheritance. In life, such as the function of seeking area, the realization of circle, rectangle and triangle is different. The action of running is different for kittens, dogs and elephants. Another example is the action of flying, insects, birds and aircraft are also different. It can be seen that the same behavior can reflect different forms through different things. Then the types of each seed class will appear.
definition
- Polymorphism: refers to the same behavior, which has multiple different manifestations for different objects.
- Polymorphism in program: it refers to that the same method has different implementations for different objects
Origin of polymorphism:
Java is a strongly typed static language, that is, each variable must declare its exact type before use, and then the subsequent assignment and operation are handled in strict accordance with this data type. For example:
int num = 10;
However, sometimes, when designing an array, or the formal parameter and return value type of a method, we cannot determine its specific type, but can only determine that it is the type of a series. For example, if you want to design an array to store the objects of various graphics and sort them according to the area of various graphics, but the specific stored objects may be circles, rectangles, triangles, etc., then the area calculation methods of various graphics are different. For example, if you want to design a method, its function is to compare the area of two graphics and return the graphic object with larger area. At this time, the formal parameter and return value types are graphic types, but we don't know which graphic type it is. At this time, Java introduced polymorphism.
At the same time, the application of polymorphism in the program can be realized by meeting the following conditions
- Inherit or implement [one of two]
- The parent class reference points to the child class object or the interface reference points to the implementation class object [format embodiment]
- Rewriting of methods [meaning embodiment: no rewriting, meaningless]
Code example
abstract class Animal {//Parent class public abstract void eat(); } //Subclass class Dog extends Animal{ @Override public void eat() {//Method rewriting System.out.println("Dogs eat bones"); } } //Subclass class Cat extends Animal{ @Override public void eat() {//Method rewriting System.out.println("Cats eat fish"); } } public class Test { public static void main(String[] args) { //A parent class reference points to a child class object Animal dog = new Dog(); dog.eat(); //Dogs eat bones //A parent class reference points to a child class object Animal cat = new Cat(); cat.eat();//Cats eat fish } }
Characteristics of accessing members in polymorphism
If you directly access member variables, you can only look at the compile time type, that is, look at the left when compiling and look at the left when running. In short: in the case of polymorphism, the member variables of the parent class are accessed. If there is no member variable to be accessed in the parent class, an error will be reported
class Animal { int age = 18; } class Dog extends Animal { int age = 20; String name = "Golden hair"; } public class Test { public static void main(String[] args) { Animal dog = new Dog(); System.out.println(dog.age);//18 //System.out.println(dog.name); Compilation error } }
Access characteristics of member methods in polymorphism
In Java, virtual method refers to the method whose calling entry address can not be determined in the compilation stage and class loading stage, but can only be determined in the running stage, that is, the method that may be rewritten. When we call a virtual method in the form of "object. Method", how do we determine which method it executes?
- Static dispatch: first look at the compile time type of the object. Find the most matching method in the compile time type of the object. The most matching means that the compile time type of the argument matches the type of the formal parameter best. If not found, the compilation fails
- Dynamic binding: look at the runtime type of this object. If the runtime class of this object overrides the most matching method just found, the overridden method will be executed. Otherwise, the method in the compile time type just now will still be executed
In short: when compiling, look for methods in the parent class, and when running, look for methods in the child class to execute
class Animal { public void eat(){ System.out.println("Eat something"); } } class Dog extends Animal { @Override public void eat() { System.out.println("Dogs eat bones"); } } public class Test { public static void main(String[] args) { Animal dog = new Dog(); dog.eat();//Dogs eat bones } }
The following methods are implemented by finding methods in the parent class when compiling and by finding methods in the parent class when running.
- static method, which determines at compile time that it will not change at run time.
- Methods called by invokespecial instruction, including private methods, instance construction methods and parent class methods. These methods are also determined at compile time and will not be changed at run time
- A method modified by the final keyword. Although the final method is called by the invokevirtual instruction, the final modified method cannot be overridden in the subclass, so the final modified method cannot be changed dynamically at run time.
Several forms of polymorphism
Common parent polymorphism:
class Fu{} class Zi extends Fu{} public class Demo{ public static void main(String[] args){ Fu f = new Zi();//On the left is a "normal parent class" } }
Abstract parent polymorphism
abstract class Fu{} class Zi extends Fu{} public class Demo{ public static void main(String[] args){ Fu f = new Zi();//The parent class on the left is an abstract class } }
Parent interface polymorphism
interface A{} class AImp implements A{} public class Demo{ public static void main(String[] args){ A a = new AImp();//On the left is a parent interface } }
Several application scenarios of polymorphism:
Scenario 1: the variable is polymorphic. If the type of the variable is the parent type, the variable can receive the object of the parent type or all its subclass objects
class Animal{ public void eat(){ System.out.println("Eat something..."); } } class Cat extends Animal{ @Override public void eat() { System.out.println("Cats eat fish"); } } public class Test { public static void main(String[] args) { // Variable polymorphism: variables of the parent type point to objects of the child type // If the type of a variable is a parent type, the variable can receive objects of the parent type or all its subclass objects anl = new Cat(); anl.eat(); } }
Scenario 2: the formal parameters are polymorphic, the parent type is used as the formal parameter of the method, and the subclass object is the argument.
class Animal { public void eat() { System.out.println("Eat something"); } } class Dog extends Animal { @Override public void eat() { System.out.println("Dogs eat bones"); } } public class Test { public static void main(String[] args) { Animal dog = new Dog(); //When assigning an argument to a formal parameter = = > animal anl = new dog(); method(dog); } //Define a method with a parameter that can receive Animal class objects and all subclass objects of Animal class public static void method(Animal animal) { animal.eat();//Dogs eat bones } }
Scenario 3: the return value is polymorphic. If the return value type is the parent type, you can return the object of the parent type or all its subclass objects
//Parent class abstract class Animal { abstract void eat(); } //Subclass Dog class Dog extends Animal { @Override void eat() { System.out.println("Dogs eat bones"); } } //Subclass Cat class Cat extends Animal{ @Override void eat() { System.out.println("Cats eat fish"); } } public class Test { public static void main(String[] args) { buy("Kitty").eat();//Cats eat fish } /* * Design a method that can buy the objects of various animals. At this time, it is not sure what kind of specific animals it is * * The return value type is the object of the parent class * * Polymorphism is reflected in the return value type Animal. The actual returned object is new Cat() or new Dog() of the subclass */ public static Animal buy(String name){ if("Kitty".equals(name)){ return new Cat(); }else if("puppy".equals(name)){ return new Dog(); } return null; } }
Scenario 4: polymorphism is applied to arrays. Array element types are declared as parent types, which can actually store their parent and child objects
/* * Declare an array that can hold objects of various animals, */ Animal[] arr = new Animal[2]; //At this time, it is not the object of new Animal, but the array object of new Animal [] //An array space of length 2 is opened up in the heap to hold the address of Animal or its subclass objects arr[0] = new Cat();//On the left arr[0] of the polymorphic reference is the Animal type, and on the right is the new Cat() //Assign a Cat object to a variable of type Animal arr[1] = new Dog();
Advantages and disadvantages of polymorphism
In the actual development process, the parent type is used as the formal parameter of the method, passing the subclass object to the method and calling the method, which can better reflect the expansibility and convenience of polymorphism. However, after using the parent variable to receive the subclass object, we can't call the methods owned by the subclass but not by the parent. This is also a little "trouble" brought by polymorphism. Disadvantages: in the case of polymorphism, you can only call the common content of the parent class, not the unique content of the child class. Therefore, if you want to call subclass specific methods, you must do type conversion. Whether the transformation is upward or downward, it must meet the parent-child relationship or implementation relationship
Upward Transformation: when the type (parent class) of the variable on the left > the type (subclass) of the object / variable on the right, we call it upward transformation
- At this time, when compiling, you can only call the variables and methods in the parent class according to the type of variables on the left, and you can't call the variables and methods unique to the child class
-
However, at runtime, it is still the type of the object itself. At this time, it must be safe and automatic
Downward Transformation: when the type (subclass) of the variable on the left < the type (parent) of the object / variable on the right, we call it downward transformation
- Format: subclass type object name = (subclass type) variable of parent type;
- At this time, the variables and methods unique to the subclass can be called when the compilation is processed according to the type of the variables on the left
- However, at runtime, it is still the type of the object itself. At this time, it is not necessarily safe. You need to use (type) to force type conversion. This process is manual.
- Not all downward transformations through compilation are correct, and classcastexceptions may occur. For safety, you can judge through the isInstanceof keyword
Code example
//Parent class abstract class Animal { abstract void eat(); } //Subclass Dog class Dog extends Animal { @Override void eat() { System.out.println("Dogs eat bones"); } public void lookHome(){ System.out.println("Dog watch"); } } //Subclass Cat class Cat extends Animal{ @Override void eat() { System.out.println("Cats eat fish"); } public void grabMouse(){ System.out.println("Cat catches mouse"); } } public class Test { public static void main(String[] args) { method(new Cat());//The Dog object is passed in } public static void method(Animal animal){ Dog dog = (Dog) animal;//This code can be compiled, but ClassCastException is reported at runtime //This is because the Cat type object is clearly created. Of course, it cannot be converted into a Dog object at run time. These two types do not have any inheritance relationship, } }
The results after running are shown in the following figure:
In order to avoid the occurrence of ClassCastException, Java provides the instanceof keyword to verify the type of reference variables. As long as instanceof is used to judge whether it returns true, it must be safe to forcibly convert to this type and ClassCastException exception will not be reported.
effect:
- Judge whether the object type pointed to by the previous variable is the following data type:
- If the object type pointed to by the preceding variable belongs to the following data type, it returns true
- If the object type pointed to by the preceding variable does not belong to the following data type, false is returned
Therefore, we'd better make a judgment before conversion. The code is as follows:
public static void method(Animal animal) { if (animal instanceof Cat) { // Downward transformation Cat cat = (Cat) animal; cat.eat();//Cats eat fish // Cat's unique grabMouse method is called cat.grabMouse();//Cat catches mouse } else if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.eat();//Dogs eat bones // Dog's unique lookHome method is called dog.lookHome();//Dog watch } }
To summarize the disadvantages of polymorphism: you can't access the unique methods or member variables of subclasses, because the characteristic of polymorphic member access is to compile and see the parent class. Solution type conversion.