我可以在Java中用构造函数调用方法吗?

Sam*_*hra 45 java constructor

我有情况,我想在实例化类时只读取一次配置文件.

假设我有一个名为的方法readConfig(),它读取配置并将其放入Map对象中.当程序需要使用配置值时,它会使用它的define键读取对象.我想知道构造函数只调用它的生命周期.我可以将我的方法readConfig()放入构造函数中,这会给我一次性调用的好处,还是有其他机制可以做到这一点?

Tom*_*icz 64

你可以:这是构造函数的用途.此外,您清楚地表明该对象永远不会构建在未知状态(未加载配置).

你不应该:在构造函数中调用实例方法是危险的,因为该对象尚未完全初始化(这主要适用于可被覆盖的方法).此外,已知构造函数中的复杂处理对可测试性具有负面影响.


Jig*_*shi 24

更好的设计

public static YourObject getMyObject(File configFile){
    //process and create an object configure it and return it
}
Run Code Online (Sandbox Code Playgroud)

  • 我无法弄清楚该代码如何匹配您提供的工厂方法模式的链接.常见的错误.但是,+1用于分割文件的读取(可以进一步分解为可测试的方法)和构造使用该数据的对象. (3认同)

dav*_*xxx 8

我可以将我的方法readConfig()放入构造函数中吗?

在构造函数中调用不可重写的方法是一种可接受的方法.
如果该方法仅由构造函数使用,您可能想知道是否private真的需要将其提取到方法(偶数)中.

如果您选择将构造函数完成的某些逻辑提取到方法中,则对于任何方法,您必须选择适合方法要求的访问修饰符,但在此特定情况下,进一步重要的是保护方法不受覆盖方法的影响必须要做有可能使超类构造函数不一致.

所以它应该private只是由类的构造函数(和实例方法)使用.
否则它应该是两者package-private,final如果方法在包内或子类中重用.

这会给我一次性电话的好处,还是有另一种机制可以做到这一点?

使用这种方式没有任何好处或缺点.
我不鼓励在构造函数中执行很多逻辑,但在某些情况下,在构造函数中初始化多个东西可能是有意义的.
例如,复制构造函数可以执行很多操作.
多个JDK类说明了这一点.
例如,使用与指定参数相同的映射HashMap构造new 的复制构造函数:HashMapMap

public HashMap(Map<? extends K, ? extends V> m) {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
    putMapEntries(m, false);
}

final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
    int s = m.size();
    if (s > 0) {
        if (table == null) { // pre-size
            float ft = ((float)s / loadFactor) + 1.0F;
            int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                     (int)ft : MAXIMUM_CAPACITY);
            if (t > threshold)
                threshold = tableSizeFor(t);
        }
        else if (s > threshold)
            resize();
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
            K key = e.getKey();
            V value = e.getValue();
            putVal(hash(key), key, value, false, evict);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

提取填充的地图的逻辑putMapEntries()是一件好事,因为它允许:

  • 在其他环境中重用该方法.例如clone(),也可以putAll()使用它
  • (次要但有趣)给出一个有意义的名称,传达执行的逻辑