JAVA字段存在多态性吗

简介: JAVA字段存在多态性吗

概述


最近看到了一道关于多态的题目,总之我做错了,归根到底还是基础知识不够扎实,现在也拿来考考大家。

public class FieldHasNoPolymorphic {
    static class Animal {
        public String name = "animal";
        public Animal() {
            name = "new animal";
            callMyName();
        }
        public void callMyName() {
            System.out.println("my name is " + name);
        }
    }
    static class Cat extends Animal {
        public String name = "cat";
        public Cat() {
            name = "new Cat";
            this.callMyName();
        }
        @Override
        public void callMyName() {
            System.out.println("cat say my name is " + name);
        }
    }
    public static void main(String[] args) {
        Animal cat = new Cat();
        cat.callMyName();
        System.out.println(cat.name);
        System.out.println(((Cat)cat).name);
    }
}

运行结果:

1671176167268.jpg

是不是和大家心理想的一样呢? cat.name最终输出的竟然是new animal, 而不是 new Cat。虽然在真实情况下,我们不会这样写代码,但是可以拿来帮我们理解Java的多态,字段没有多态。


字节码分析


我们利用idea的jclasslib插件查看相应的字节码,

  1. 查看主函数的字节码

1671176176167.jpg

  1. 查看Cat类构造方法的字节码

1671176183141.jpg

  1. 查看Animal类构造方法的字节码

1671176189225.jpg

运行结果分析:

  1. main方法调用Cat的构造函数,Cat的构造函数会默认调用父类Animal的构造函数,父类构造函数会用invokevirtual指令调用callMyName方法,invokevirtual指令具有多态性,会调用实际类型的callMyName方法,也就是Cat类的方法, 此时Cat类的的name还没有初始化,他需要在子类构造函数中初始化, 所以第一行是 cat say my name is null
  2. 后面是子类构造函数中的this.callMyName,最终输出cat say my name is new Cat
  3. 第三行cat say my name is new Cat是由 cat.callMyName();输出得到的。
  4. System.out.println(cat.name); 最终输出的是new animal,是不是出乎大家的意料,我看字节码可以知道它是用的Animal中的name。

1671176196763.jpg

  1. 强转后,它就用的Cat类的name,所以输出的是new Cat。

1671176205826.jpg


总结


从这个例子我们知道了以下几点:

  1. 类中的字段没有多态性,如果子类和父类定义了同样的字段,最终会用引用类型的字段。
  2. 类的方法存在多态性,最终会调用运行时确定的实际类型的方法,如果方法中没有就调用父类的,依次类推,这个过程是依赖invokevirtual指令实现的。
目录
相关文章
|
6月前
|
JSON Java 数据格式
【Java反序列化】@JsonAlias字段别名
 @JsonAlias 是 Jackson 库提供的一个注解,用于在反序列化 JSON 数据时,为字段或方法指定多个可接受的名称或别名。
131 0
|
7月前
|
Java
深入理解Java中的多态性
在Java编程中,多态性是一个非常重要的概念。它允许我们以一种灵活的方式处理不同类型的对象,并根据具体的对象类型调用相应的方法。
51 0
|
6月前
|
Java Maven 开发工具
【mapstruct】Java 中 mapstruct mapper 转换器部分字段转换无效的解决方案
【mapstruct】Java 中 mapstruct mapper 转换器部分字段转换无效的解决方案
156 0
|
8天前
|
Java Maven
【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“
【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“
32 3
|
3月前
|
Java
Java | 获取实体类中的所有字段,包括继承自其父类的字段
需要通过反射获取一个实体类中的所有字段,包括继承自其父类的字段。
185 0
|
12天前
|
Java
在Java中,多态性允许不同类的对象对同一消息做出响应
【4月更文挑战第7天】在Java中,多态性允许不同类的对象对同一消息做出响应
17 2
|
1月前
|
Java
Java中的多态性
Java中的多态性
13 0
|
2月前
|
XML Java 数据库连接
|
2月前
|
Java
深入理解Java中的多态性
【2月更文挑战第5天】Java是一门具有强大可扩展性的面向对象编程语言,其中最重要的特性之一就是多态性。本篇文章将深入探讨Java中的多态性,从多个角度进行分析与解释,并介绍其实际应用。
|
6月前
|
IDE Java Maven
【Java异常】Error:(14,35) java:程序包eu.bitwalker.useragentutils不存在 的解决方案
【Java异常】Error:(14,35) java:程序包eu.bitwalker.useragentutils不存在 的解决方案
206 0