简体   繁体   English

与Class.forName()的松耦合

[英]Loose coupling with 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);
    }
}

The output for the above code appears to be 上面代码的输出似乎是
Hello from SBI static

What should I add to my code and Y to also print the statement 我应该添加到我的代码和Y到also打印声明
Connected to SBI

In detail explanation is much appreciated 详细解释非常感谢

PS Noob here PS Noob在这里

You have to create a new instance of the object (using Class#newInstance() ), cast it to the type you want (in your scenario SBI ), and then call it. 您必须创建一个新的对象实例(使用Class#newInstance() ),将其Class#newInstance()为所需的类型(在方案SBI ),然后调用它。

Working code: 工作代码:

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();
    }
}

Explanation: 说明:

  • Class.forName("pkg.SBI") gets a reference for pkg.SBI class in the clazz object. Class.forName("pkg.SBI")获取clazz对象中pkg.SBI类的引用。
  • As clazz holds a reference to SBI , calling clazz.newInstance(); 由于clazz拥有对SBI的引用,因此调用clazz.newInstance(); is the same as calling: new SBI(); 与调用相同: new SBI(); .
  • After calling clazz.newInstance(); 调用clazz.newInstance(); , then, the variable obj will receive a SBI instance. ,那么变量obj将收到一个SBI实例。
  • As you want to call a SBI method and obj 's type is Object (that's the newInstance() method's return type) you have to cast it to SBI and only then call connect() . 当您要调用SBI方法且obj的类型为Object (即newInstance()方法的返回类型)时,必须将其SBISBI ,然后再调用connect()

Using Java's Reflection API: 使用Java的Reflection API:

If you wish to go even further and not even do the cast (this way LooseCouplingTest never needs to import SBI ), you can use Java's Reflection API to invoke the connect() method. 如果您想走得更远甚至不进行LooseCouplingTest (这样LooseCouplingTest永远不需要导入SBI ),则可以使用Java的Reflection API来调用connect()方法。

Here's the working code for that: 这是工作代码:

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() loads the class. Class.forName()加载类。 and part of loading the class is executing the static initializer block. 加载类的一部分是执行静态初始化程序块。 That's why you see "Hello from SBI static" printed (the static { ... } part is the static initializer block). 这就是为什么您看到“从SBI静态开始的Hello”( static { ... }部分是静态初始化程序块)的原因。

To make "Connected to SBI" appear, you have to create an instance of the class and call the connect() method on it: 要显示“已连接到SBI”,您必须创建该类的实例并在其上调用connect()方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM