目录
1.向上转型
1.1概念
向上转型:创建一个子类对象给父类引用,将一个子类当成父类来使用
1.2语法格式
父类类型 对象名 = new 子类类型;
class Animal{
private String name;
private int age;
public void eat(){
System.out.println("吃东西");
}
public void voice(){
System.out.println("一般声音");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("吃小鱼干");
}
@Override
public void voice() {
System.out.println("喵喵喵");
}
}
public class Test {
public static void eat(Animal animal){
animal.eat();
}
public static void main(String[] args) {
Animal animal1 = new Animal();//正常实例化创建对象
animal1.eat();
animal1.voice();
System.out.println("*********************************");
Animal animal2 = new Cat();//向上转型,将子类对象给父类引用
animal2.eat();
animal2.voice();
System.out.println("*********************************");
像是下图,子类除了由继承父类的成员,自身还有额外的成员共同组成。所以说将子类对象给父类引用是没问题的,我们只能通过其调用父类自身的成员,不能调用子类额外的成员。
1.3使用场景
- 直接赋值
- 方法传参
- 方法返回
class Animal{
private String name;
private int age;
public void eat(){
System.out.println("吃东西");
}
public void voice(){
System.out.println("一般声音");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("吃小鱼干");
}
@Override
public void voice() {
System.out.println("喵喵喵");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("啃骨头");
}
@Override
public void voice() {
System.out.println("汪汪汪");
}
}
public class Test {
public static void eat(Animal animal){//方法传参,将子类对象作为父类类型接收
animal.eat();
}
public static Animal pickPet(String tmp){//方法返回,方法的返回值为父类,返回子类对象
if("cat".equals(tmp)){
return new Cat();
}
if("dog".equals(tmp)){
return new Dog();
}
return null;
}
public static void main(String[] args) {
Cat cat = new Cat();
eat(cat);//方法传参
Animal animal2 = new Cat();//直接赋值,将子类对象给父类引用
animal2.eat();
animal2.voice();
System.out.println("*********************************");
Animal animal3 = new Dog();//直接赋值
animal3.eat();
animal3.voice();
System.out.println("*********************************");
Animal pet = pickPet("cat");//方法传参
}
}
注意:向上转型是不能调用子类的方法的,这也是其缺点。
2.向下转型
2.1概念
一个子类对象经过向上转型被父类引用后,再将其还原成被子类引用的子类对象。
2.2向下转型实例
class Animal{
private String name;
private int age;
public void eat(){
System.out.println("吃东西");
}
public void voice(){
System.out.println("一般声音");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("吃小鱼干");
}
@Override
public void voice() {
System.out.println("喵喵喵");
}
public void play(){
System.out.println("玩毛线球");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("啃骨头");
}
@Override
public void voice() {
System.out.println("汪汪汪");
}
public void pick(){
System.out.println("捡树枝");
}
}public class Test {
public static void main(String[] args) {
//实例化两个子类对象
Cat cat = new Cat();
Dog dog = new Dog();
//向上转型
Animal animal = cat;//将子类对象给父类引用
//animal.paly();//向上转型后不能调用子类特有的方法,会发生错误
//向下转型
cat = (Cat) animal;
cat.play();//安全
//向下转型可能会发生的错误
//因为我们可能会弄混和父类进行向上转型的子类是哪一个,所以可能会发生一下情况
dog = (Dog) animal;//此处将cat对象强制转换成了dog,这显然是不对的,而编译器此处并没有发生警告
dog.pick();//我们的animal其实是cat对象,cat对象中没有pick方法
}
}
2.3关键词instancof
为了避免上面代码最后出现的错误,java中引入了关键词instancof,他可以确保我们的向下转型在安全的情况下返回true,我们就可以用来检测我们所写的向下转型是否安全
if(animal instanceof Cat){//使用关键词instanceof来确保安全的向下转型
cat = (Cat) animal;
cat.play();
}
if(animal instanceof Dog){//此处instanceof返回false,if内语句不执行
dog = (Dog) animal;
dog.pick();
}