前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 解决父构造器中拿到对象

java 解决父构造器中拿到对象

作者头像
潇洒
发布2023-10-20 12:35:07
1130
发布2023-10-20 12:35:07
举报
文章被收录于专栏:石头岛

这两天被问到一个有意思的问题,就是如果在构造器中拿到匿名对象。 这个问题有意思在,直觉上是可以通过外部放一个成员变量去接,然后后续就可以使用了,但实际不行。

问题复现

下面这个是构造器,当通过 supper 去调用父类构造器。由于问题出现在Spring项目当中,所以我复现的例子也基于Spring重新搭了一个项目来复现这个过程,代码放github上。

复现demo:

代码语言:javascript
复制
package com.test;

import org.springframework.beans.factory.annotation.Autowired;

public class TransactionCache extends RevokingDB {

  @Autowired
  public TransactionCache(String dbName) {
    // 其他代码不能在 supper 之前,但是又要拿到 TxCacheDB,不能再new一次,否则会初始化两次TxCacheDB。
    super(new TxCacheDB(dbName));
    // 需要是在这里调一下 txCacheDB.init();
  }
}
代码语言:javascript
复制
public class TxCacheDB {

  public TxCacheDB(String dbName) {
    System.out.println("TxCacheDB: " + dbName);
  }

  public void init() {
    System.out.println("TxCacheDB: init");
  }
}

这里可以偿试几种解决方案:

  1. 方案一 直接成员变量中 new TxCacheDB(dbName); 构造器中再使用
  2. 方案二 super调用一个方法,而不直接new TxCacheDB();
  3. 方案三 将对象保在ThreadLocal中,再拿出来

验证方案

方案一

这种在直觉上没有问题,但是实际有问题:

  1. 成员变量不知道 dbName,传入的具体值是什么,如果写死就失去灵活性。
  2. 写死。如果写死,你不能确定会传入dbName将会是什么,实际中这个dbName有很多个,没有办法写死

方案二

这个方法看着就可行,来验证一下。

代码语言:javascript
复制
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class TransactionCache2 extends RevokingDB {

  private static TxCacheDB txCacheDB = null;

  @Autowired
  public TransactionCache2(String dbName) {
    // 其他代码不能在 supper 之前
    super(getTxCache(dbName));
    txCacheDB.init();
  }

  private static TxCacheDB getTxCache(String dbName) {
    txCacheDB = new TxCacheDB(dbName);
    return txCacheDB;
  }
}

输出结果:

TxCacheDB: trans-cache TxCacheDB: init

结查证明可行。 但是有个问题,我就用一次,还有开辟一段元数据区态内存来放 这个 static TxCacheDB,不划算。 我就想用一次,不想还占用内存。

方案三

将对象放入本地线程中,使用后就移除。 这样即可以使用对象,也不需要一直占用部分内存。

代码语言:javascript
复制
public class TransactionCache3 extends RevokingDB {

  @Autowired
  public TransactionCache3(String dbName) {
    // 其他代码不能在 supper 之前
    super(new TxCacheDB(dbName));
    try {
      TxCacheDB txCacheDB = ThreadLocalUtil.get();
      txCacheDB.init();
    } finally {
      ThreadLocalUtil.remove();
    }
  }
}

TxCacheDB: trans-cache3 TxCacheDB: init

总结

java 对象在初始化的时候构造器中 supper 是永远放在第一行不能变。这一特性决定了这个问题的解决只能曲线救国。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题复现
  • 验证方案
    • 方案一
      • 方案二
        • 方案三
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档