Java:反思过度使用?

时间:2011-01-12 06:59:09

标签: java reflection

我想知道我是否过度使用java反射 我有一个类,它是几个地图的数据持有者。我有公共的get(...)方法,它们给出一个键作为输入,返回相应映射中与之关联的值 由于地图很大,我只在我真正想要访问它们时加载它们。因此,在每个get(...)方法中,我检查映射是否为null。如果是,我调用相应的loadMap(..)方法 以下是示例代码段

 public getId(String name)  
 {
     try
     {
     if(nameMap1 == null)
        loadNameMap1();
     } catch(...) {....}

     return nameMap1.getId(name);
 }

问题是我有多张地图。因此,为了加载每个映射,我在get(...)方法中有一个不同的loadMap(..)方法和try catch块。因此,我写了一个名为loadMap(Object map,String methodName)的方法,它使用反射来调用适当的方法,并处理所有异常。

private synchronized void loadMap(Object map, String methodName)
{
if (map == null)
    try
    {
    Method method = this.getClass().getDeclaredMethod(methodName, new Class[0]);
    method.invoke(this, new Object[0]);
    } 
    catch (..)
}

我在这里过度反思吗?有一个更好的方法吗?这是否有资格作为Effective Java by Joshua Bloch中所写的“有限使用反思” (旁注:我无法将类重构为多个类)

3 个答案:

答案 0 :(得分:3)

// could also be static
private Map<String, Callable<Map>> myLoaders;

private synchronized void loadMap(Object map, String mapName)
{
if (map == null)
    try
    {
       Callable<Map> mapLoader = myLoaders.get(mapName);
       map = mapLoader.call();
    } 
    catch (..)
}

// and in the constructor or other init code
myLoaders.put("map1", new Callable<Map>(){
     Map call(){
        // load map 1
     }});

我认为,虽然如果你所做的只是从一些方法移动一个常见的try / catch逻辑,它需要重复到一个地方,这是错误的方法。你以这种方式失去了很多编译器错误检查支持。有些人会使用像Aspect / J这样的工具,但我认为你只需要接受这样一个事实,即Java没有真正的设施,通过使用共享的私有函数将混乱减少到最小,并接受几个复制/粘贴线。只要这些行中没有“真正的代码”,它就不是真正有害的代码重复。

所以:

 public getId(String name){
     try{
        if (nameMap1 == null)
            loadNameMap1();
        }
      catch (....){
          privateHelperFunctionThatCutsThisDownToOneLine(name, "id", "nameMap1");
      }
  }

  // you are left with the above repetitive three (or seven) lines,
  // but that is Java for you...
  // in return, you get nice, static compile-time error checking


 private void privateHelperFunctionThatCutsThisDownToOneLine(){
      // all the long repeated code in the exception handler
      // goes here.
 }

答案 1 :(得分:2)

我会说你是在过度反思。

也许你应该采取更多的OO方法

public interface MapMaker <K,V> {
public Map<K,V> create();
}

public class LazyMap<K,V> implements Map<K,V> {

private MapMaker<K,V> creation;
private Map<K,V> theMap = null;

public LazyMap( MapMaker<K,V> creation) {
  this.creation=creation;
}

protected Map<K,V> getMap() {
  if( theMap == null) {
    synchronized(this) {
      if( theMap == null ) {
         theMap = creation.create();
      }
    }
  }
  return theMap;
}
//Map interface
public V get(Object key) { return getMap().get(key); }
//repeat for all
}

答案 2 :(得分:2)

您不想加载所有地图,因为它们太大了。但是使用你的方法,你最终会得到内存中加载的所有东西。您可以查看ehcache,可以配置一个不再需要的元素驱逐的惰性地图系统。