代码之家  ›  专栏  ›  技术社区  ›  Puru--

使用基于反射的静态调用而不是接口

  •  1
  • Puru--  · 技术社区  · 12 年前

    我的问题是Java中的一个通用设计问题。在典型的基于控制器的设计(比方说MVC)中,控制器通常创建动作实例并调用从接口实现的方法(比方说动作接口的execute())。

    为什么我们需要创建不必要的对象,为什么不使用静态调用并消除实现接口的需要?

    如下面的示例。正如每个Java程序都需要main()方法一样,每个action方法都需要execute()

    class MyActionClass {
        public static void execute() {
            System.out.println("Hello from execute()!!");
        }
    }
    
    public class StaticTest {
    
        /**
         * @param args
         * @throws ClassNotFoundException
         * @throws SecurityException
         * @throws NoSuchMethodException
         * @throws InvocationTargetException
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         */
        public static void main(String[] args) throws ClassNotFoundException,
                            NoSuchMethodException, SecurityException, IllegalAccessException,
                            IllegalArgumentException, InvocationTargetException {
            Class<?> clazz = Class.forName("MyActionClass");
            Method method = clazz.getMethod("execute");
            method.invoke(null);
        }
    
    }
    
    1 回复  |  直到 12 年前
        1
  •  2
  •   Aman Agnihotri    12 年前

    因为反射API比方法调用慢得多,因为在使用反射时,编译器无法进行任何优化,因为它无法真正了解您正在做什么。

    通过拥有一个接口和实现它的多个具体类,我们可以拥有多态行为的优势。添加 Factory pattern 并且您可以直接使用接口,而实际上不需要知道您正在调用哪个具体的类方法。另一个好处是编译器将能够优化代码,使其运行速度比使用反射API快得多。

    从Java8开始,我们可以在接口中实现静态和实例方法。下面是一个演示:

    public class InterfaceDemo
    {
      public static void main(String... args)
      {
        XYZ.executeStatic("Hello");
    
        XYZ object = new Implementer();
        object.executeInstance("Message");
      }
    }
    
    interface XYZ
    {
      static void executeStatic(String message)
      {
        System.out.println("Static: " + message);
      }
    
      default void executeInstance(String message)
      {
        System.out.println("Instance: " + message);
      }
    }
    
    class Implementer implements XYZ {}
    

    然后有如下功能接口:

    @FunctionalInterface
    public interface Returnable<T>
    {
      public T value();
    }
    

    这允许使用lambda表达式创建不同的实现,如:

    Returnable<Integer> integerReturnable = () -> 42;
    Returnable<String> stringReturnable = () -> "Hello";
    

    并使用如下方式:

    System.out.println(integerReturnable.value()); // Prints 42
    System.out.println(stringReturnable.value()); // Prints Hello
    

    顺便说一下,如果需要创建很多对象,我们使用 Object Pool pattern 或者类似的东西,如果有很多类似的对象,我们使用 Flyweight Pattern 以在保持速度的同时最小化内存使用。