构造函数重载的工作原理

How constructor overloading works

如果我不能修改 Factory.create 方法(只能修改 TaskSubType 类)?

public class Test {

    public static void main(String[] args) {
        Factory.create(new SubType());
        // OUTPUT:
        // task instanceof SubType: true
        // callable  (PROBLEM: I want SubType constructor to be invoked)
    }

    public static class SubType implements Callable {
        @Override
        public Object call() throws Exception {
            return null;
        }
    }

    public static class Task {
        private Callable callable;
        private SubType subType;

        public Task(SubType subType) {
            System.out.println("Subtype");
            this.subType = subType;
        }
        public Task(Callable callable) {
            System.out.println("callable");
            this.callable = callable;
        }
    }

    public static class Factory {

        // If change method argument type to SubType it will invoke 
        // Task.<init>(SubType) constructor, but I can't modify it
        public static Task create(Callable task) {
            System.out.println("task instanceof SubType: " + (task instanceof SubType));
            return new Task(task);
        }
    }
}

Task class 上创建一个 public 工厂静态方法,并将构造函数设为私有,或包私有

public static class Task {
    private Callable callable;
    private SubType subType;

    private Task(SubType subType) {
        System.out.println("Subtype");
        this.subType = subType;
    }
    private Task(Callable callable) {
        System.out.println("callable");
        this.callable = callable;
    }

    public static Task create ( final Callable callable )
    {
       if ( callable instance of SubTask )
       {
         return new Task( (SubType) callable );
       }

       return new Task( callable );

    }
}

public static class Factory {

    // Note that we are now calling Task's factory method
    public static Task create(Callable task) {
        System.out.println("task instanceof SubType: " + (task instanceof SubType));
        return Task.create(task);
    }
}

选择调用哪个重载方法或构造函数是在编译时根据参数的声明类型完成的。所以,即使 task 的实际 具体 类型是 SubType,它的 声明的 类型是 Callable ,第二个构造函数,以 Callable 作为参数,将始终被调用。

因此,如果您希望在使用 SubType 构造 Task 时发生不同的事情,那么您应该在 Task 构造函数中测试 Callable 的类型:

 public static class Task {
    private Callable callable;
    private SubType subType;

    public Task(Callable callable) {
        if (callable instanceof SubTask) {
            System.out.println("Subtype");
            this.subType = subType;
        }
        else {
            System.out.println("callable");
            this.callable = callable;
        }
    }
}