2014-11-21 101 views
0

我有幾個擴展抽象父類的子類。我想要父類有一個靜態ArrayList持有每個孩子的實例。如果可能,我希望能夠添加更多的子類而不必更改父類的代碼。在沒有實例化類的情況下運行靜態塊 - Java

我想出的一個解決方案是給每個子類一個靜態塊,它將自己的一個實例添加到ArrayList。唯一的問題是,我需要給每個孩子打電話,讓它加載並運行該塊。

abstract public class Parent { 
    protected static ArrayList<Parent> children = new ArrayList<Parent>(); 
} 

public class ChildA extends Parent { 
    static { 
     children.add(new ChildA()); 
    }  
} 

public class ChildB extends Parent { 
    static { 
     children.add(new ChildB()); 
    }  
} 

有沒有辦法解決這個問題?我可以在沒有打電話的情況下加載課程嗎?有沒有更好的方法來做到這一點?

編輯: 這實際上是一個基於瓷磚的遊戲。我有一個抽象的「瓷磚」類和任意數量的瓷磚類型擴展它。我希望能夠輕鬆地將新的瓷磚添加到遊戲中,而無需在整個地方更改代碼。如果你對如何做到這一點有更好的想法,我願意提出建議。

+0

可能重複http://stackoverflow.com/questions/492184/how -do-you-find-a-given-class-in-java) – A4L 2014-11-21 23:20:25

回答

0

您可以在類層次結構之外執行此操作。有一個效用函數,它使用反射來查找Parent的所有後代,然後將它們添加到您的列表中。

+1

感謝您的快速響應。看起來我終於有了一個理解反思的藉口:)然後效用函數不需要知道子類的名字嗎? – Camander 2014-11-21 23:21:58

+0

@Camander,不需要知道名稱,在掃描包的時候獲得類對象,使用方法[Class#isAssignableFrom(java.lang.Class)](https://docs.oracle.com/javase/8 /docs/api/java/lang/Class.html#isAssignableFrom-java.lang.Class-)來確定類是否爲調用類的子類型:'Parent.class.AssignableFrom(protetialChild)',如果此調用重新調用' true「,那麼你已經找到了一個孩子,創建一個實例並將其添加到列表中。 – A4L 2014-11-22 15:24:46

0

你想做這件事的動機不明確,但有些解決方案不一定涉及反思。

將創建子類的責任轉移到工廠類中。在該工廠類中,也將兒童類插入到您的列表中。

這是一個可以做到這一點的片段。請記住:因爲您的列表綁定到Parent,您將不得不將其轉換爲正確的子類類型,以便以後的類使用

public final class ChildFactory { 

    private static ChildFactory instance = new ChildFactory(); 

    private ChildFactory() { 

    } 

    public <C extends Parent> C generateChild(Class<C> childClass) { 
     try { 
      final C child = childClass.newInstance(); 
      Parent.children.add(child); 
      return child; 
     } catch(InstantiationException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static ChildFactory getInstance() { 
     return instance; 
    } 
} 
0

我想threre可能是一個更簡單的方法來做到這一點,但這個類可能是有用的:

package classFinder; 

import java.io.File; 
import java.io.IOException; 
import java.lang.reflect.Modifier; 
import java.util.Enumeration; 
import java.util.HashSet; 
import java.util.Set; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 

public class ClassFinder { 
    protected static Class<?> getClass(String prefix, String classPath) 
      throws ClassNotFoundException { 
     if (!classPath.endsWith(".class") || !classPath.startsWith(prefix)) { 
      return null; 
     } 
     return Class.forName(classPath.substring(prefix.length(), 
       classPath.length() - ".class".length()).replace('/', '.')); 
    } 

    protected static Class<?> getClass(File rootFile, File classFile) 
      throws ClassNotFoundException { 
     return getClass(rootFile.getPath() + '/', classFile.getPath()); 
    } 

    @SuppressWarnings("unchecked") 
    protected static <T> Set<Class<T>> searchAllSubclassesInDirectory(
      File rootFile, File searchFile, Class<?> cls, 
      boolean abstractClasses) throws ClassFinderException { 
     Set<Class<T>> result = new HashSet<Class<T>>(); 
     if (searchFile.isDirectory()) { 
      for (File file : searchFile.listFiles()) { 
       result.addAll(ClassFinder.<T> searchAllSubclasses(
         rootFile.getPath(), file.getPath(), cls, 
         abstractClasses)); 
      } 
      return result; 
     } 

     String fileName = searchFile.getName(); 
     if (!fileName.endsWith(".class")) { 
      return result; 
     } 
     try { 
      Class<?> entry = getClass(rootFile, searchFile); 
      if (entry != null 
        && (abstractClasses || !Modifier.isAbstract(entry 
          .getModifiers()))) { 
       Class<?> superClass = entry; 
       while (!((superClass = superClass.getSuperclass()) == null)) { 
        if (superClass.equals(cls)) { 
         result.add((Class<T>) entry); 
         return result; 
        } 
       } 
      } 
      return result; 
     } catch (ClassNotFoundException e) { 
      // e.printStackTrace(); //DEBUG only 
      return result; 
     } 
    } 

    @SuppressWarnings("unchecked") 
    protected static <T> Set<Class<T>> searchAllSubclassesInJar(File jar, 
      Class<?> cls, boolean abstractClasses) { 
     Set<Class<T>> result = new HashSet<Class<T>>(); 
     try { 
      JarFile jarFile = new JarFile(jar); 
      Enumeration<JarEntry> entries = jarFile.entries(); 
      while (entries.hasMoreElements()) { 
       JarEntry file = entries.nextElement(); 
       if (file.isDirectory()) { 
        continue; 
       } 
       Class<?> entry = getClass("", file.getName()); 
       if (entry != null 
         && (abstractClasses || !Modifier.isAbstract(entry 
           .getModifiers()))) { 
        Class<?> superClass = entry; 
        while (!((superClass = superClass.getSuperclass()) == null)) { 
         if (superClass.equals(cls)) { 
          result.add((Class<T>) entry); 
         } 
        } 
       } 
      } 
      jarFile.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return result; 
    } 

    protected static <T> Set<Class<T>> searchAllSubclasses(String rootPath, 
      String searchPath, Class<?> cls, boolean abstractClasses) 
      throws ClassFinderException { 
     if (searchPath.endsWith(".jar")) { 
      return searchAllSubclassesInJar(new File(searchPath), cls, 
        abstractClasses); 
      // return new HashSet<Class<T>>(); 
     } else { 
      return searchAllSubclassesInDirectory(new File(rootPath), new File(
        searchPath), cls, abstractClasses); 
     } 
    } 

    // TODO create public method to search inside a not root directory/package 

    public static <T> Set<Class<T>> searchAllSubclasses(Class<?> cls, 
      boolean abstractClasses) throws ClassFinderException { 
     Set<Class<T>> result = new HashSet<Class<T>>(); 
     String classpath = System.getProperty("java.class.path"); 
     for (String path : classpath 
       .split(System.getProperty("path.separator"))) { 
      result.addAll(ClassFinder.<T> searchAllSubclasses(path, path, cls, 
        abstractClasses)); 
     } 

     return result; 
     // return ClassFinder.<T> searchAllSubclasses(ROOT_URL, cls, 
     // abstractClasses, ""); 
    } 
} 

如果你有一個標準的Java桌面應用程序可能運行工作。 該類在您的程序目錄樹上搜索給定超類的實現。也適用於jar文件。

然後,您可以初始化靜態字段:

abstract public class Parent { 
    protected static Set<Parent> children = ClassFinder 
       .<Parent> searchAllSubclasses(Parent.class, true); 
} 
的[?你怎麼找到Java中的給定類的子類(
相關問題