Home>

Java polymorphic object type conversion

The object type conversion mentioned here,Means an object that has an inheritance relationship,Not any type of object.When casting an object that does not have an inheritance relationship,The java runtime will throw a java.lang.classcastexception exception.

In the inheritance chain,We refer to the transition from child to parent as "upward transformation," and the transition from parent to child is called "downward transformation."

most of the time,We will define the variable as the type of the parent class,But references an object of a subclass,This process is an upward transformation.When the program is running, the subclass methods are called through dynamic binding.That is polymorphism.

However, sometimes in order to complete some functions that the parent class does not have,We need to transform the subclass objects after the upward transformation into subclasses.Calling methods of subclasses,This is the downward transformation.

Note:You cannot directly cast an object of a parent class to a subclass type,You can only convert the subclass object after the upcast to the subclass type again.That is,After the subclass object must be transformed upwards,In order to transform downward.Look at the following code:

public class demo {
  public static void main (string args []) {
    superclass superobj=new superclass ();
    sonclass sonobj=new sonclass ();
    //The following code will throw an exception when run,Cannot convert parent object directly to child type
    //sonclass sonobj2=(sonclass) superobj;
    //transform upwards first,Down-transformation
    superobj=sonobj;
    sonclass sonobj1=(sonclass) superobj;
  }
}
class superclass {}
class sonclass extends superclass {}

Remove the comment on line 7,An exception is thrown at runtime,But compilation works.

Because downside risks exist,So when receiving a reference to the parent class,Be sure to use the instanceof operator to determine if the object is the subclass i want,Look at the following code:

public class demo {
  public static void main (string args []) {
    superclass superobj=new superclass ();
    sonclass sonobj=new sonclass ();
    //superobj is not an instance of the sonclass class
    if (superobj instanceof sonclass) {
      sonclass sonobj1=(sonclass) superobj;
    } else {
      system.out.println ("①cannot convert");
    }
    superobj=sonobj;
    //superobj is an instance of the sonclass class
    if (superobj instanceof sonclass) {
      sonclass sonobj2=(sonclass) superobj;
    } else {
      system.out.println ("②cannot convert");
    }
  }
}
class superclass {}
class sonclass extends superclass {}

operation result:

① Cannot be converted

In summary:the type conversion of objects is checked at program runtime,The upward transformation happens automatically,The downcast object must be a subclass of the current reference type.

Java polymorphism and dynamic binding

In java, a variable of a parent class can reference an instance of the parent class,You can also reference instances of subclasses.

Readers first look at a piece of code:

public class demo {
  public static void main (string [] args) {
    animal obj=new animal ();
    obj.cry ();
    obj=new cat ();
    obj.cry ();
    obj=new dog ();
    obj.cry ();
  }
}
class animal {
  //animal call
  public void cry () {
    system.out.println ("I don't know how to call it");
  }
}
class cat extends animal {
  //Cat's barking
  public void cry () {
    system.out.println ("Meow Meow ~");
  }
}
class dog extends animal {
  //dog barking
  public void cry () {
    system.out.println (" ~");
  }
}

operation result:

Don't know what to call
Meow ~
Wang Wang ~

The above code,Three classes are defined,Animal, cat, and dog, respectively, and the cat and dog classes inherit from the animal class. The obj variable is of type animal, which can either point to an instance of the animal class,Can also point to instances of the cat and dog classes,this is correct.That is,Variables of the parent class can reference instances of the parent class,You can also reference instances of subclasses.Note that the reverse is wrong,Because all cats are animals,But not all animals are cats.

As can be seen,obj can be both human,It can also be a cat or a dog. It has different manifestations.This is called polymorphism.Polymorphism means that one thing has different manifestations or forms.

For example, "human", there are many different expressions or implementations.ta can be a driver, teacher, doctor, etc. When you hate yourself, you will say "re-becoming a person in the next life", then you can become a driver, teacher, doctor in your next lifeWe say that "human" has polymorphism.

There are three necessary conditions for the existence of polymorphism:there must be inheritance, there must be rewriting, and the parent variable references the child object.

When calling a method using polymorphism:

First check if the method exists in the parent class,if there is not,Compile error;If so, check if the subclass overrides the method.

If the subclass overrides this method,Just call the methods of the subclass,Otherwise, the parent method is called.

As you can see from the example above,One benefit of polymorphism is that when there are many subclasses,There is no need to define multiple variables,You can define only one type of parent class to reference instances of different subclasses.Consider the following example:

public class demo {
  public static void main (string [] args) {
    //With polymorphism,The owner can feed many animals
    master ma=new master ();
    ma.feed (new animal (), new food ());
    ma.feed (new cat (), new fish ());
    ma.feed (new dog (), new bone ());
  }
}
//animal class and its subclasses
class animal {
  public void eat (food f) {
    system.out.println ("I'm a small animal,Eating "+ f.getfood ());
  }
}
class cat extends animal {
  public void eat (food f) {
    system.out.println ("I'm a kitten,Eating "+ f.getfood ());
  }
}
class dog extends animal {
  public void eat (food f) {
    system.out.println ("I'm a dog,Eating "+ f.getfood ());
  }
}
//food and its subclasses
class food {
  public string getfood () {
    return "thing";
  }
}
class fish extends food {
  public string getfood () {
    return "fish";
  }
}
class bone extends food {
  public string getfood () {
    return "bones";
  }
}
//master class
class master {
  public void feed (animal an, food f) {
    an.eat (f);
  }
}

operation result:

I am a small animal,Eating
I am a kitten
Eating fish
I am a dog
Eating bones

The feed method of the master class has two parameters,Animal type and food type, because it is the parent class,So you can pass an instance of the subclass to it,This way the master class doesn't need multiple methods to feed different animals.

Dynamic binding

To understand the nature of polymorphism,Let's talk about the detailed process of java calling method.

1) The compiler looks at the declared type and method name of the object.

Suppose obj.func (param) is called, and obj is an object of class cat.have to be aware of is,There may be multiple methods named func with different parameter signatures.For example, there may be methods func (int) and func (string). The compiler will enumerate all the methods named func in the cat class and the methods named func that access the property public in its parent animal.

In this way, the compiler has a list of all candidate methods that may be called.

2) Next, the editor will check the parameter signature provided when the method is called.

If there is a method in all methods named func that exactly matches the parameter signature provided,Then choose this method.This process is called overloading resolution. For example, if func ("hello") is called, the compiler chooses func (string) over func (int). Due to the existence of automatic type conversion,For example, int can be converted to double. If the same method as the signature of the calling method parameter is not found,Just perform the type conversion before continuing to find,If there is no matching type in the end or there are multiple methods matching it,Then compile error.

In this way, the compiler obtains the method name and parameter signature to be called.

3) If the modifier of the method is private, static, final (static and final will be explained later), or a constructor method,Then the compiler will know exactly which method should be called,We call this method of static binding (static binding).

Corresponding to this,The method called depends on the actual type of the object, And achieve dynamic binding at runtime.For example, by calling func ("hello"), the editor will use dynamic binding to generate an instruction that calls func (string).

4) When the program runs,And when calling methods with dynamic binding,The jvm will definitely call the method of the class most appropriate to the actual type of the object referenced by obj.We have assumed that the actual type of obj is cat, which is a subclass of animal. If func (string) is defined in cat, we call it,Otherwise it will look in the animal class and its parent.

Search every time the method is called,The time overhead is quite large,Therefore, the JVM creates a method table (method lable) for each class in advance, which lists the names of all methods, their signatures, and the class they belong to.Thus,When the method is actually called,The virtual machine simply looks up this table.In the example above,jvm searches the method table of the cat class,To find a method that matches func ("hello").This method can be either cat.func (string) or animal.func (string). Note that if you call super.func ("hello"), the compiler will search the method table of the parent class.

Suppose the animal class contains three methods:cry (), getname (), and getage ().Then its method table is as follows:

cry ()->animal.cry ()

getname ()->animal.getname ()

getage ()->animal.getage ()

In fact, animal also has a default parent class object (explained later) that inherits the methods of object, so the methods listed above are not complete.

Assuming the cat class overrides the cry () method in the animal class and adds a new method climbtree (), its parameter list is:

cry ()->cat.cry ()

getname ()->animal.getname ()

getage ()->animal.getage ()

climbtree ()->cat.climbtree ()

When running,The process of calling the obj.cry () method is as follows:

jvm first accesses the method table of the actual type of obj,May be a method table of the animal class,It may also be a method table for the cat class and its subclasses.

jvm searches the method table for methods that match cry (),Once you find it, you know which class it belongs to.

jvm calls this method.

  • Previous On the declaration rules and programming style of Java source files
  • Next Workaround for unable to start NET Framework NGEN v4030319_X86 service