与Class.forName()松散耦合


interface Bank {
    void connect();
}
class SBI implements Bank {
    static{
        System.out.println("Hello from SBI static");
    }   
    public void connect() {
        System.out.println("Connected to SBI");
    }
}
class LooseCouplingTest {
    public static void main(String... args)throws Exception {
        String className = args[0];
        Class.forName(className);
    }
}

上面代码的输出看起来是
Hello from SBI static

我应该添加什么到我的代码和Y到also打印语句
Connected to SBI

请详细解释

注:

您必须创建对象的新实例(使用Class#newInstance()),将其转换为您想要的类型(在您的场景SBI中),然后调用它。

工作代码:

public class LooseCouplingTest {
    public static void main(String... args)throws Exception {
        String className = args[0];
        Class<?> clazz = Class.forName(className);
        Object obj = clazz.newInstance();
        SBI mySBI = (SBI) obj;
        mySBI.connect();
    }
}

解释:

  • Class.forName("pkg.SBI")获取clazz对象中pkg.SBI类的引用。
  • 由于clazz持有对SBI的引用,所以调用clazz.newInstance();与调用new SBI();是一样的。
  • 调用clazz.newInstance();之后,变量obj将接收一个SBI实例。
  • 当你想调用SBI方法和obj的类型是Object(这是newInstance()方法的返回类型),你必须将其强制转换为SBI,然后才调用connect()

使用Java的反射API:

如果你想更进一步,甚至不做转换(这样LooseCouplingTest就不需要导入SBI),你可以使用Java的反射API来调用connect()方法。

下面是工作代码:

public class LooseCouplingTest {
    public static void main(String... args) throws Exception {
        String className = args[0];
        Class<?> clazz = Class.forName(className);
        Object obj = clazz.newInstance();
        java.lang.reflect.Method connect = clazz.getMethod("connect");
        connect.invoke(obj);
    }
}

Class.forName()加载类。加载类的一部分是执行静态初始化块。这就是为什么你看到"Hello from SBI static"打印出来(static { ... }部分是静态初始化块)。

要使"Connected To SBI"出现,您必须创建该类的实例并在其上调用connect()方法:

Class<? extends Bank> bankClass = (Class<? extends Bank>)Class.forName(className);
Bank bank = bankClass.newInstance();
bank.connect();

相关内容

  • 没有找到相关文章

最新更新