确定是否由于派生类实例创建而调用构造函数的最佳方法

时间:2014-04-14 21:44:35

标签: java constructor

假设我有两个类A和B,其中B扩展A.当我创建B的实例时,调用A和B的构造函数。确定在创建实例B时是否正在调用A的构造函数的最佳方法是什么?

我做了类似下面的事情,但看起来并不美观。我正在使用getClass(),有更好的方法吗?我实际上是在尝试计算A和B的实例。

public class A {
    private static int counter = 0;

    public A() {
        if (this.getClass().getName().equals("A")) {
            counter++;
        }
    }

    public static void main(String[] args) {
        A a = new B();
        A a1 = new A();
        A a2 = new B();
        System.out.println(A.getCount());
        System.out.println(B.getCount());
    }

    public static int getCount() {
        return counter;
    }
}

class B extends A {
    private static int counter = 0;

    public B() {
        counter++;
    }

    public static int getCount() {
        return counter;
    }
}

输出

1
2

4 个答案:

答案 0 :(得分:4)

最好避免检查名称

if (this.getClass() == A.class)

除此之外,您可以考虑使用protected构造函数 - 但仍然可以在同一个包中访问。

通常,最好的解决方案是不需要这样做 - 如果你的设计真的需要知道你正在构建的对象是否只是一个A"或者是子类的一个实例,那么上面的测试非常清楚地表示了这个条件......但是从一开始就是一个奇怪的要求。

答案 1 :(得分:1)

我建议你在多个构造函数的情况下使用initialization block,否则你必须在每个构造函数中重复你的代码。

示例代码:

public class A {
    private static int counter = 0;

    // initialization block
    {
        if (this.getClass() == A.class) {
            counter++;
        }
    }

    public A() {
    }

    public A(int i) {
    }

    public A(String s) {
    }

    public static int getCount() {
        return counter;
    }
}

答案 2 :(得分:0)

编辑:在阅读之前,我只是看到别人的答案,这有助于以类似的方式。这种方式不会使用反射。


正如其他人所说,你不应该担心你的超类中的子类。如果你真的想要这样的控制:

public class Test {
    public static void main(String[] args) {
        B b = new B("hey");
        C c = new C(5);
    }
}

class A {
    public A(int age) { //specifically for B
        System.out.println("B created");
    }

    public A(String name) { //specifically for C
        System.out.println("C created");
    }

    { //for all constructors
        System.out.println("An instance that extend A have been created");
    }
}

class B extends A {
    public B(String name) {
        super(name);
    }
}

class C extends A {
    public C(int age) {
        super(age);
    }
}

虽然这是不好的做法,因为构造函数中的params不应该以这种方式被忽略(无用的参数只是为了排序)。这将使阅读代码的其他开发人员感到困惑。这是可能的,但问题是,你为什么要这样做?最有可能是更好/更清洁/更有效的方式来完成任务

答案 3 :(得分:0)

来自@Braj @JonSkeet的好建议

我实现了类似下面的内容

import java.util.HashMap;


class ClassCounter{
    private static HashMap<Class<?>, Integer> mapClassCount= new HashMap<>();

    public static void increment(Class<?> clz){
        Integer cnt = mapClassCount.get(clz);
        if(cnt == null){
            cnt = new Integer(0);
        }

        mapClassCount.put(clz, ++cnt);
    }

    public static Integer get(Class<?> clz){
        Integer cnt = mapClassCount.get(clz);
        return ((cnt == null) ? 0: cnt);
    }
}

public class A {

    {
        if (this.getClass().equals(A.class)) {
            ClassCounter.increment(A.class);
        }
    }

    public A() {
    }

    public static void main(String[] args) {
        A a = new B();
        A a1 = new A();
        A a2 = new B();
        System.out.println(ClassCounter.get(A.class));
        System.out.println(ClassCounter.get(B.class));
    }

}

class B extends A {

    {
        ClassCounter.increment(B.class);
    }

    public B() {

    }

}