Java casting issues are not complicated; just remember one phrase: a parent class reference points to a child class object.

What does it mean for a parent class reference to point to a child class object? Let me explain slowly.

Let's start with 2 terms: Upcasting 、Downcasting。

For example: there are 2 classes, Father is the parent class, and Son class inherits from Father.

First example:

Father f1 = new Son();   // 这就叫 upcasting (向上转型)
// 现在 f1 引用指向一个Son对象

Son s1 = (Son)f1;   // 这就叫 downcasting (向下转型)
// 现在f1 还是指向 Son对象

Second example:

Father f2 = new Father();
Son s2 = (Son)f2;       // 出错,子类引用不能指向父类对象

You might ask, in the first example:Son s1 = (Son)f1;Why is it correct?

Very simple because f1 points to a child class object,Father f1 = new Son();the child class reference s1 can naturally point to a child class object.

And f2 is passed a Father object,Father f2 = new Father();the child class reference s2 cannot point to a parent class object.

Summary:

1. A parent class reference can point to a child class object, but a child class reference cannot point to a parent class object.

2. Directly assigning a child class object to a parent class reference is called upcasting. Upcasting does not require a forced conversion, for example:

Father f1 = new Son();

3. Assigning a parent class reference that points to a child class object to a child class reference is called downcasting; it requires forced conversion, for example:

f1 is a parent class reference pointing to a child class object. Assigning f1 to child class reference s1 is:Son s1 = (Son)f1;

The (Son) in front of f1 must be added to perform forced conversion.

1. Upcasting.

Simply put, it is converting a child class object to a parent class object. Here the parent class object can be an interface.

1. Method calls in upcasting:

Example

public class Animal { public void eat(){ System.out.println("animal eatting..."); } } class Bird extends Animal{ public void eat(){ System.out.println("bird eatting..."); } public void fly(){ System.out.println("bird flying..."); } } class Main{ public static void main(String[] args) { Animal b=new Bird(); //Upcasting b.eat(); //! error: b.fly(); although b points to a child class object, it has lost the fly() method dosleep(new Male()); dosleep(new Female()); } public static void dosleep(Human h) { h.sleep(); } }

Example

public class Human { public void sleep() { System.out.println("Human sleep.."); } } class Male extends Human { @Override public void sleep() { System.out.println("Male sleep.."); } } class Female extends Human { @Override public void sleep() { System.out.println("Female sleep.."); } }

Note the upcasting here:

Animal b=new Bird(); //向上转型
b.eat();

This will call the eat() method of the child class. Reason: b actually points to the Bird child class, so when called, the child class's own method will be invoked.

Note that during upcasting, b will lose other methods not shared with the parent class object. For example, the fly method in this case is no longer available to b.

2. Benefits of upcasting

Look at the code above:

public static void dosleep(Human h) {
    h.sleep();
}

Here the parent class is used as the parameter, and sometimes the child class is used as the parameter, which utilizes upcasting. This makes the code concise. Otherwise, if dosleep takes child class objects as parameters, then you would need to write as many functions as there are child classes. This also reflects Java's abstract programming philosophy.

2. Downcasting.

Opposite to upcasting, it is converting a parent class object to a child class object.

Example

package com.wensefu.other1; public class Girl { public void smile(){ System.out.println("girl smile()..."); } } class MMGirl extends Girl{ @Override public void smile() { System.out.println("MMirl smile sounds sweet..."); } public void c(){ System.out.println("MMirl c()..."); } } class Main{ public static void main(String[] args) { Girl g1=new MMGirl(); //Upcasting g1.smile(); MMGirl mmg=(MMGirl)g1; //Downcasting, both compilation and execution will not error mmg.smile(); mmg.c(); Girl g2=new Girl(); //MMGirl mmg1=(MMGirl)g2; //unsafe downcasting, compilation has no error but runtime will error // mmg1.smile(); // mmg1.c(); /*output: * CGirl smile sounds sweet... * CGirl smile sounds sweet... * CGirl c()... * Exception in thread "main" java.lang.ClassCastException: com.wensefu.other1.Girl * at com.wensefu.other1.Main.main(Girl.java:36) */ if(g2 instanceof MMGirl){ MMGirl mmg1=(MMGirl)g2; mmg1.smile(); mmg1.c(); } } }
Girl g1=new MMGirl(); //向上转型
g1.smile();
MMGirl mmg=(MMGirl)g1; //向下转型,编译和运行皆不会出错

The downcasting here is safe because g1 points to a child class object.

and

Girl g2=new Girl();
MMGirl mmg1=(MMGirl)g2; //不安全的向下转型,编译无错但会运行会出错

Runtime error:

Exception in thread "main" java.lang.ClassCastException: com.wensefu.other1.Girl
    at com.wensefu.other1.Main.main(Girl.java:36)

As shown in the code, you can use instanceof to prevent exceptions.