8

I was wondering if there is any given function that allows me to introspect a class without having to write the packages where the class is contained.

For example, I want to take a look at the methods and superclasses of the class Integer in order to do that I have to specify the packages where the class is located. This will be "java.lang.Integer"

Instead of doing that I want to just type the class name in order to have the information of the class displayed. Just like this "Integer"

How can I make that my program just check the class name, no matter where is it located?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
stbamb
  • 179
  • 2
  • 2
  • 13
  • *"Instead of doing that I want to just type the class name in order to have the information of the class displayed. Just like this "Integer""* Uh-huh. ..and what is supposed to happen if you type `Timer`? – Andrew Thompson Nov 04 '12 at 02:40

3 Answers3

14

Java will not stop you from creating your own my.company.Integer class and my.other.company.Integer class, so how it cannot know which Integer class is the right one.

The closes thing to an answer I can suggest is to create a pre-defined list of packages where you want to search the class for, and keep trying each until you find your class.

So something like:

class ClassFinder{
  public static final String[] searchPackages = {
    "java.lang",
    "java.util",
    "my.company",
    "my.company.other" };

  public Class<?> findClassByName(String name) {
    for(int i=0; i<searchPackages.length; i++){
      try{
        return Class.forName(searchPackages[i] + "." + name);
      } catch (ClassNotFoundException e){
        //not in this package, try another
      } catch (...){
        //deal with other problems...
      }
    }
    //nothing found: return null or throw ClassNotFoundException
    return null;
  }
}

If you want to get a list of all available packages instead of hard-coding them, see here.

Be warned that this method is unlikely to perform very well, so use it sparingly.

Community
  • 1
  • 1
rodion
  • 14,729
  • 3
  • 53
  • 55
  • cool, thanks for your idea, it will be really helpful, thanks for helping me – stbamb Nov 05 '12 at 07:17
  • if you don't actually want to load the class, you could set initialize parameter of forName() to false - I think - I haven't actually tried it myself – ycomp Oct 13 '15 at 18:59
1

Borrowed code, slightly modified (...from @rodion's answer)

/**
 * Returns first loaded Class found in the searchPackages
 * @param classname the simple class name (e.g. "String")
 * @param searchPackages String[] of packages to search.
 *                       <li>Place the more important packages at the top since the first Class
 *                           found is returned</li>
 *                       <code>//Example
 *                        public static final String[] searchPackages = {
 *                          "java.lang",
 *                          "java.util",
 *                          "my.company",
 *                          "my.company.other" };
 *                       </code>
 * @return the loaded Class or null if not found
 */
public static final Class<?> findClassByName(String classname, String[] searchPackages) {
    for(int i=0; i<searchPackages.length; i++){
        try{
            return Class.forName(searchPackages[i] + "." + classname);
        } catch (ClassNotFoundException e){
            //not in this package, try another
        }
    }
    //nothing found: return null or throw ClassNotFoundException
    return null;
}

same code modified to throw an exception if duplicate Class names found

/**
 * Returns the loaded Class found in the searchPackages
 * @param classname the simple class name (e.g. "String")
 * @param searchPackages String[] of packages to search.
 *                       <li>Place the more important packages at the top since the first Class
 *                           found is returned</li>
 *                       <code>//Example
 *                        public static final String[] searchPackages = {
 *                        "java.lang",
 *                        "java.util",
 *                        "my.company",
 *                        "my.company.other" };
 *                       </code>
 * @throws RuntimeException if more than one class of the same classname found in multiple packages
 * @return the loaded Class (guaranteed to be unique among the searchPackages) or null if not found
 */
public static final Class<?> findClassByNameNoDupes(String classname, String[] searchPackages) {

    Class<?> foundClass = null;
    for(int i=0; i<searchPackages.length; i++){
        try{
            boolean wasNull = foundClass == null;
            foundClass = Class.forName(searchPackages[i] + "." + classname);
            if (!wasNull) throw new RuntimeException(classname + " exists in multiple packages!");
        } catch (ClassNotFoundException e){
            //not in this package, try another
        }
    }
    return foundClass;
}
Community
  • 1
  • 1
ycomp
  • 8,316
  • 19
  • 57
  • 95
-2

That's not possible, classes are loaded dynamically once referenced. So, there is no way to drill down the list of available packages as there is no such thing.

However, there are ways to inspect jars as these are zip files (including the standard JVM jars).

thedayofcondor
  • 3,860
  • 1
  • 19
  • 28