//可以动态查找出工作空间中已知父类的所有子类。 package util; import java.io.File; import java.io.IOException; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Comparator; import java.util.Enumeration; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * <code>ClassUtil</code> file contains code used for loading all * implementations of specified <em>interface</em> or <em>abstract class</em> * found in classpath. As a result of calling some functions you can have * <code>Set</code> containing all required classes. * * <p> * </p> */ public class ClassUtil { private static final String[] SKIP_CONTAINS = { ".ui.", ".swing", ".awt", ".sql.", ".xml.", ".terracotta." }; private static final String[] SKIP_STARTS = { "com.mysql", "tigase.pubsub.Utils", "org.apache.derby", "org.apache.xml", "org.postgresql", "com.sun", "groovy", "org.codehaus.groovy", "org.netbeans", "org.python" }; /** * Method description * * * @param fileName * * @return */ public static String getClassNameFromFileName(String fileName) { String class_name = null; if (fileName.endsWith(".class")) { // class_name = fileName.substring(0, // fileName.length()-6).replace(File.separatorChar, '.'); // Above code does not works on MS Windows if we load // files from jar file. Jar manipulation code always returns // file names with unix style separators String tmp_class_name = fileName.substring(0, fileName.length() - 6).replace('\\', '.'); class_name = tmp_class_name.replace('/', '.'); } // end of if (entry_name.endsWith(".class")) return class_name; } /** * Method description * * * @param dir * * @return */ public static Set<String> getClassNamesFromDir(File dir) { Set<String> tmp_set = getFileListDeep(dir); Set<String> result = new TreeSet<String>(); for (String elem : tmp_set) { String class_name = getClassNameFromFileName(elem); if (class_name != null) { result.add(class_name); // System.out.println("class name: "+class_name); } // end of if (class_name != null) } // end of for () return result; } /** * Method description * * * @param jarFile * * @return * * @throws IOException */ public static Set<String> getClassNamesFromJar(File jarFile) throws IOException { Set<String> result = new TreeSet<String>(); JarFile jar = new JarFile(jarFile); Enumeration<JarEntry> jar_entries = jar.entries(); while (jar_entries.hasMoreElements()) { JarEntry jar_entry = jar_entries.nextElement(); String class_name = getClassNameFromFileName(jar_entry.getName()); if (class_name != null) { result.add(class_name); // System.out.println("class name: "+class_name); } // end of if (entry_name.endsWith(".class")) } // end of while (jar_entries.hasMoreElements()) return result; } /** * Method description * * * @return * * @throws ClassNotFoundException * @throws IOException */ public static Set<Class<?>> getClassesFromClassPath() throws IOException, ClassNotFoundException { Set<Class<?>> classes_set = new TreeSet<Class<?>>(new ClassComparator()); String classpath = System.getProperty("java.class.path"); // System.out.println("classpath: "+classpath); StringTokenizer stok = new StringTokenizer(classpath, File.pathSeparator, false); while (stok.hasMoreTokens()) { String path = stok.nextToken(); File file = new File(path); if (file.exists()) { if (file.isDirectory()) { // System.out.println("directory: "+path); Set<String> class_names = getClassNamesFromDir(file); classes_set.addAll(getClassesFromNames(class_names)); } // end of if (file.isDirectory()) if (file.isFile()) { // System.out.println("jar file: "+path); Set<String> class_names = getClassNamesFromJar(file); classes_set.addAll(getClassesFromNames(class_names)); // System.out.println("Loaded jar file: "+path); } // end of if (file.isFile()) } // end of if (file.exists()) } // end of while (stok.hasMoreTokens()) return classes_set; } /** * Method description * * * @param names * * @return * * @throws ClassNotFoundException */ public static Set<Class<?>> getClassesFromNames(Set<String> names) throws ClassNotFoundException { Set<Class<?>> classes = new TreeSet<Class<?>>(new ClassComparator()); for (String name : names) { try { boolean skip_class = false; for (String test_str : SKIP_CONTAINS) { skip_class = name.contains(test_str); if (skip_class) { break; } } if (!skip_class) { for (String test_str : SKIP_STARTS) { skip_class = name.startsWith(test_str); if (skip_class) { break; } } } if (!skip_class) { // System.out.println(new Date() + " - Class name: " + name); Class cls = Class.forName(name, false, ClassLoader.getSystemClassLoader()); classes.add(cls); } } catch (SecurityException e) { } catch (NoClassDefFoundError e) { } catch (UnsatisfiedLinkError e) { } catch (Throwable e) { Throwable cause = e.getCause(); System.out.println("Class name: " + name); e.printStackTrace(); if (cause != null) { cause.printStackTrace(); } } } // end of for () return classes; } /** * Method description * * * @param classes * @param cls * @param <T> * * @return */ @SuppressWarnings({ "unchecked" }) public static <T extends Class> Set<T> getClassesImplementing(Collection<Class<?>> classes, T cls) { Set<T> classes_set = new TreeSet<T>(new ClassComparator()); for (Class c : classes) { // System.out.println("Checking class: " + c.getName()); if (cls.isAssignableFrom(c)) { int mod = c.getModifiers(); if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) { classes_set.add((T) c); } // end of if (!Modifier.isAbstract(mod) && !Modifier.isInterface(mod)) } // end of if (cls.isAssignableFrom(c)) } // end of for () return classes_set; } /** * Method description * * * @param cls * @param <T> * * @return * * @throws ClassNotFoundException * @throws IOException */ public static <T extends Class> Set<T> getClassesImplementing(T cls) throws IOException, ClassNotFoundException { return getClassesImplementing(getClassesFromClassPath(), cls); } /** * Method description * * * @param path * * @return */ public static Set<String> getFileListDeep(File path) { Set<String> set = new TreeSet<String>(); if (path.isDirectory()) { String[] files = path.list(); for (String file : files) { walkInDirForFiles(path, file, set); } // end of for () } else { set.add(path.toString()); } // end of if (file.isDirectory()) else return set; } /** * Method description * * * @param obj * @param <T> * * @return * * @throws ClassNotFoundException * @throws IOException * @throws IllegalAccessException * @throws InstantiationException */ @SuppressWarnings("unchecked") public static <T> Set<T> getImplementations(Class<T> obj) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { Set<T> result = new TreeSet<T>(new ObjectComparator()); for (Class cls : getClassesImplementing(obj)) { result.add((T) cls.newInstance()); } // end of for () return result; } /** * Method description * * * @param base_dir * @param path * @param set */ public static void walkInDirForFiles(File base_dir, String path, Set<String> set) { File tmp_file = new File(base_dir, path); if (tmp_file.isDirectory()) { String[] files = tmp_file.list(); for (String file : files) { walkInDirForFiles(base_dir, new File(path, file).toString(), set); } // end of for () } else { // System.out.println("File: " + path.toString()); set.add(path); } // end of if (file.isDirectory()) else } public static void main(String[] args) { try { Set<Class<Comparator>> procs= ClassUtil.getClassesImplementing(Comparator.class); System.out.println(procs.size()); for (Class<Comparator> c:procs) { System.out.println(c.getName()); } //2 //util.ClassComparator //util.ObjectComparator } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // ClassUtil
/* * Tigase Jabber/XMPP Utils * Copyright (C) 2004-2012 "Artur Hefczyc" <artur.hefczyc@tigase.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. Look for COPYING file in the top folder. * If not, see http://www.gnu.org/licenses/. * * $Rev$ * Last modified by $Author$ * $Date$ */ package util; import java.util.Comparator; import java.io.Serializable; /** * In a few cases classes have to be kept in <code>Set</code>. This * <code>Comparator</code> implementation has been created to return proper * value for <code>compare</code> method and to make it possible to store * classes in any <code>Set</code>. * * <p> * Created: Sat Oct 9 22:27:54 2004 * </p> * @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a> * @version $Rev$ */ public class ClassComparator implements Comparator<Class>, Serializable { private static final long serialVersionUID = 1L; // Implementation of java.util.Comparator /** * Method <code>compare</code> is used to perform * * @param c1 an <code>Object</code> value * @param c2 an <code>Object</code> value * @return an <code>int</code> value */ // @Override public int compare(Class c1, Class c2) { return c1.getName().compareTo(c2.getName()); } }// ClassComparator
/* * Tigase Jabber/XMPP Utils * Copyright (C) 2004-2012 "Artur Hefczyc" <artur.hefczyc@tigase.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. Look for COPYING file in the top folder. * If not, see http://www.gnu.org/licenses/. * * $Rev$ * Last modified by $Author$ * $Date$ */ package util; import java.util.Comparator; import java.io.Serializable; /** * Describe class ObjectComparator here. * * * Created: Tue May 17 23:53:20 2005 * * @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a> * @version $Rev$ */ public class ObjectComparator implements Comparator<Object>, Serializable { private static final long serialVersionUID = 1L; /** * Describe <code>compare</code> method here. * * @param object an <code>Object</code> value * @param object1 an <code>Object</code> value * @return an <code>int</code> value */ public int compare(final Object o1, final Object o2) { return o1.getClass().getName().compareTo(o2.getClass().getName()); } } // ObjectComparator
相关推荐
在Java中,所有的类都间接或直接地继承自根类`Object`,并且Java遵循单根继承的原则,即一个类只能有一个直接父类。然而,接口打破了这一限制,一个类可以实现多个接口,接口提供了一种规范性的约束,定义了类必须...
- 如果子类方法抛出异常,那么父类方法也必须声明抛出相同的异常。 #### 五、多线程 **继承Thread类,为什么要重写run方法** - 继承`Thread`类创建线程时,需要重写`run`方法。 - `run`方法中包含了线程要执行的...
讨论了父类的虚函数在子类中的覆盖情况,以及子类是否能访问父类的私有成员。在C++中,即使子类没有显式声明函数为virtual,只要它覆盖了基类的虚函数,仍然可以实现多态。但是,子类无法直接访问父类的私有成员,...
在创建一个对象时,执行顺序如下:父类静态变量、父类静态初始化块、子类静态变量、子类静态初始化块、父类实例变量、父类构造函数、子类实例变量、子类构造函数。这个顺序是Java类加载机制的一部分,有助于理解类的...
在Java中,可以将父类引用指向子类对象,也可以将子类对象显式转换为父类类型。 #### 四、面向对象(2) ##### 1. 基本数据类型的包装类 Java为每种基本数据类型都提供了对应的包装类,这些包装类提供了更多的...
- **知识点概述**:面向对象编程中,子类可以通过继承获得父类的所有成员(属性和方法)。 - **错误理解**:子类拥有的成员数目不一定大于等于父类。子类可以通过覆盖或新增成员来扩展功能,但也可以保持与父类相同...
在这个版本中,实例变量变得更为健壮,即使修改了父类中的实例变量布局,也不会影响到其子类,除非显式地选择这样做。 对于平台的支持方面,iPhone程序以及Mac OS X v10.5及以上版本中的64位程序均采用了现行版本的...
子类可以覆盖继承自父类的方法,也可以继承父类的所有属性和行为。 Java中的接口(Interface)定义了一种规范,它规定了实现该接口的类必须实现接口中定义的所有方法。接口与类不同,类可以继承多个接口,但不能...
- **重写**(Overriding):子类中定义了与父类完全相同的非私有方法。 **6. 匿名内部类中对接口的方法为什么要加public** - 在Java中,接口中的方法默认是`public`。 - 当在匿名内部类中实现接口时,即使不显式...
- 子类抛出的异常类型不能比父类更广泛,这是为了保持方法的兼容性。 #### 五、多线程 **1. 继承Thread类,为什么要继承run方法** - 继承`Thread`类是为了重写`run`方法,其中定义了线程的主体逻辑。 **2. 进程...
**知识点**:多态的实现无需在子类中显式声明虚函数,但函数签名必须匹配。 **解释**:在继承体系中,即使子类没有显式声明父类中的虚函数为虚函数,只要函数签名(参数列表)相同,仍可以实现多态。这依赖于C++的...
- 示例代码展示如何在子类中调用父类的构造方法。 **Java接口和C++的虚类区别** - Java中接口只能包含抽象方法。 - C++中虚类可以包含虚函数,但也可以包含非虚函数。 - 示例代码说明两者的特点及其适用场景。 **...
- 模板方法模式是通过定义算法的骨架,而将一些步骤延迟到子类中的一种设计模式。 **7.9 Object类** - Object类是所有Java类的父类,提供了如toString()、equals()等常用方法。 **7.10 封装类** - Java为每种...
虚表允许实现多态性,使得子类能够重写父类的方法,并在运行时动态调用正确的方法。这种机制对于实现继承和接口非常关键,为代码提供了更大的灵活性和可扩展性。 虚表通常由编译器自动生成,存储了类的虚函数指针。...
- **private**:抽象方法需要在子类中被实现,而private方法是不可见的。 - **static**:抽象方法依赖于子类的实现,而静态方法不属于对象,与子类无关。 - **final**:抽象方法需要被子类重写,而final方法禁止被...
- 覆盖(Override):子类可以覆盖父类的方法以提供不同的实现。 - 多态的体现:通过父类引用指向子类对象,调用子类特有的方法。 8. **实验8-继承与多态2**: - 抽象类:包含抽象方法的类,不能实例化,通常...
9. 继承:在面向对象编程中,子类可以继承父类的所有方法和状态,包括私有和非私有。 10. 网页浏览:要访问网页,需要知道网页的URL(统一资源定位符)。 11. 程序流程图:题中提到的图是程序流程图,用于描述程序...