强制类型转换

问题

最近在研读公司项目的时候发现一段很有意思的代码:

if (a instanceof b) {
    B ent = (B) a;
    if (!useGivenAuditAttributes) {
        ent.createdAt = MyDateUtils.now();
        ent.createdBy = AppContext.instance.loginUser.userId;
        ent.lastUpdatedAt = ent.createdAt;
        ent.lastUpdatedBy = ent.createdBy;
    }
}

后续并没有对ent对象进行操作,在 if 块结束后,它的作用域就结束了。因此,从表面上看,这个变量会被销毁,后续代码无法直接访问这个局部变量。

那么这段代码有什么作用呢?

查阅资料之后我发现了一个被遗忘的知识点。

解析

先说结论

ent 虽然是局部变量,但它本质上引用的是 a对象,这意味着对 ent 的修改实际上是在修改 a对象本身。

ent 在 if 块内被销毁只是引用被销毁,它指向的 a对象本身并不会被销毁。ent 对 a属性的修改是直接作用在 a对象上的,因此,后续代码依然能访问这些修改过的属性。

 是不是很疑惑?如果不疑惑说明你很强!

首先总所周知的是,在 Java 中,对象引用是指一个变量存储了对象在内存中的地址,而不是对象本身。

在 Java 中,类的实例(对象)存在于内存中,而引用类型的变量(如 B entT a,这里的T代表泛型)则存在于内存中,它们存储的是指向堆中实际对象的引用(即对象的内存地址)。

其次我们要知道,java当中强制类型转换的原理

当执行 B ent = (B) a; 时:

  • 编译时检查: 编译器会验证 a的静态类型是否可以被转换为 B类型。因为 a的实际类型是A,即 B 的子类,所以这个转换在编译时是合法的。
  • 运行时转换: 在运行时,JVM 会检查 a的实际类型,并将 a的引用(指向堆中对象的地址)赋值给 ent。注意,这里的转换只是更改了引用的静态类型(ent 是 B类型),而堆中对象本身并没有发生改变。

因此在类型转换后,变量 ent 和 a都存储了相同的内存地址,因此它们指向同一个对象,即堆中相同的 A实例。

内存中即为这样:

因为 ent 和 a都指向同一个对象,所以通过 ent 修改该对象的属性会影响到 a对象。

实例

下面上代码


public class A {
    private String name;

    public A(String name) {
        this.name = name;
    }

    public A() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


public class B extends A{
    private int age;

    public B(String name, int age) {
        super(name);
        this.age = age;
    }

    public B(int age) {
        this.age = age;
    }

    public B(String name) {
        super(name);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 public static void main(String[] args) {
        B b = new B("jack", 10);
        A a = (A) b;
        System.out.println(a.getName());
        a.setName("vivian");
        System.out.println(b.getName());
    }

运行截图如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值