`
jianfulove
  • 浏览: 120048 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
社区版块
存档分类
最新评论

可以动态查找出工作空间中已知父类的所有子类

    博客分类:
  • util
 
阅读更多
//可以动态查找出工作空间中已知父类的所有子类。



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--工作面试总结.doc

    在Java中,所有的类都间接或直接地继承自根类`Object`,并且Java遵循单根继承的原则,即一个类只能有一个直接父类。然而,接口打破了这一限制,一个类可以实现多个接口,接口提供了一种规范性的约束,定义了类必须...

    Java经典问题答案(带书签).pdf

    - 如果子类方法抛出异常,那么父类方法也必须声明抛出相同的异常。 #### 五、多线程 **继承Thread类,为什么要重写run方法** - 继承`Thread`类创建线程时,需要重写`run`方法。 - `run`方法中包含了线程要执行的...

    软件笔试题汇总

    讨论了父类的虚函数在子类中的覆盖情况,以及子类是否能访问父类的私有成员。在C++中,即使子类没有显式声明函数为virtual,只要它覆盖了基类的虚函数,仍然可以实现多态。但是,子类无法直接访问父类的私有成员,...

    Java面试资料.docx

    在创建一个对象时,执行顺序如下:父类静态变量、父类静态初始化块、子类静态变量、子类静态初始化块、父类实例变量、父类构造函数、子类实例变量、子类构造函数。这个顺序是Java类加载机制的一部分,有助于理解类的...

    java精华总结

    在Java中,可以将父类引用指向子类对象,也可以将子类对象显式转换为父类类型。 #### 四、面向对象(2) ##### 1. 基本数据类型的包装类 Java为每种基本数据类型都提供了对应的包装类,这些包装类提供了更多的...

    2021-2022计算机二级等级考试试题及答案No.12457.docx

    - **知识点概述**:面向对象编程中,子类可以通过继承获得父类的所有成员(属性和方法)。 - **错误理解**:子类拥有的成员数目不一定大于等于父类。子类可以通过覆盖或新增成员来扩展功能,但也可以保持与父类相同...

    Objective-C 2.0 运行时系统编程指南

    在这个版本中,实例变量变得更为健壮,即使修改了父类中的实例变量布局,也不会影响到其子类,除非显式地选择这样做。 对于平台的支持方面,iPhone程序以及Mac OS X v10.5及以上版本中的64位程序均采用了现行版本的...

    Java练习题库(含答案及解析).pdf

    子类可以覆盖继承自父类的方法,也可以继承父类的所有属性和行为。 Java中的接口(Interface)定义了一种规范,它规定了实现该接口的类必须实现接口中定义的所有方法。接口与类不同,类可以继承多个接口,但不能...

    Java经典面试题+答案(带书签)pdf

    - **重写**(Overriding):子类中定义了与父类完全相同的非私有方法。 **6. 匿名内部类中对接口的方法为什么要加public** - 在Java中,接口中的方法默认是`public`。 - 当在匿名内部类中实现接口时,即使不显式...

    经典的问题

    - 子类抛出的异常类型不能比父类更广泛,这是为了保持方法的兼容性。 #### 五、多线程 **1. 继承Thread类,为什么要继承run方法** - 继承`Thread`类是为了重写`run`方法,其中定义了线程的主体逻辑。 **2. 进程...

    C_C 面试题集锦.pdf

    **知识点**:多态的实现无需在子类中显式声明虚函数,但函数签名必须匹配。 **解释**:在继承体系中,即使子类没有显式声明父类中的虚函数为虚函数,只要函数签名(参数列表)相同,仍可以实现多态。这依赖于C++的...

    Java极品学习资料

    - 示例代码展示如何在子类中调用父类的构造方法。 **Java接口和C++的虚类区别** - Java中接口只能包含抽象方法。 - C++中虚类可以包含虚函数,但也可以包含非虚函数。 - 示例代码说明两者的特点及其适用场景。 **...

    Java入门学习笔记

    - 模板方法模式是通过定义算法的骨架,而将一些步骤延迟到子类中的一种设计模式。 **7.9 Object类** - Object类是所有Java类的父类,提供了如toString()、equals()等常用方法。 **7.10 封装类** - Java为每种...

    虚表列表支持库

    虚表允许实现多态性,使得子类能够重写父类的方法,并在运行时动态调用正确的方法。这种机制对于实现继承和接口非常关键,为代码提供了更大的灵活性和可扩展性。 虚表通常由编译器自动生成,存储了类的虚函数指针。...

    java面试问题集锦

    - **private**:抽象方法需要在子类中被实现,而private方法是不可见的。 - **static**:抽象方法依赖于子类的实现,而静态方法不属于对象,与子类无关。 - **final**:抽象方法需要被子类重写,而final方法禁止被...

    java上机实验1-10

    - 覆盖(Override):子类可以覆盖父类的方法以提供不同的实现。 - 多态的体现:通过父类引用指向子类对象,调用子类特有的方法。 8. **实验8-继承与多态2**: - 抽象类:包含抽象方法的类,不能实例化,通常...

    2021-2022计算机二级等级考试试题及答案No.4761.docx

    9. 继承:在面向对象编程中,子类可以继承父类的所有方法和状态,包括私有和非私有。 10. 网页浏览:要访问网页,需要知道网页的URL(统一资源定位符)。 11. 程序流程图:题中提到的图是程序流程图,用于描述程序...

Global site tag (gtag.js) - Google Analytics