Java/Reflection/Interface

Материал из Java эксперт
Перейти к: навигация, поиск

Class Reflection: implemented interfaces

   
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for NON-COMMERCIAL purposes and without fee is hereby granted
 * provided that this copyright notice appears in all copies. Please refer to
 * the file "copyright.html" for further important copyright and licensing
 * information.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
import java.io.IOException;
import java.io.RandomAccessFile;
public class SampleInterface {
  public static void main(String[] args) {
    try {
      RandomAccessFile r = new RandomAccessFile("myfile", "r");
      printInterfaceNames(r);
    } catch (IOException e) {
      System.out.println(e);
    }
  }
  static void printInterfaceNames(Object o) {
    Class c = o.getClass();
    Class[] theInterfaces = c.getInterfaces();
    for (int i = 0; i < theInterfaces.length; i++) {
      String interfaceName = theInterfaces[i].getName();
      System.out.println(interfaceName);
    }
  }
}





Class Reflection: is it an interface

   
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for NON-COMMERCIAL purposes and without fee is hereby granted
 * provided that this copyright notice appears in all copies. Please refer to
 * the file "copyright.html" for further important copyright and licensing
 * information.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
import java.util.Observable;
import java.util.Observer;
public class SampleCheckInterface {
  public static void main(String[] args) {
    Class observer = Observer.class;
    Class observable = Observable.class;
    verifyInterface(observer);
    verifyInterface(observable);
  }
  static void verifyInterface(Class c) {
    String name = c.getName();
    if (c.isInterface()) {
      System.out.println(name + " is an interface.");
    } else {
      System.out.println(name + " is a class.");
    }
  }
}





Determining If a Class Object Represents a Class or Interface

   
public class Main {
  public static void main(String[] argv) throws Exception {
    Class cls = java.lang.String.class;
    boolean isClass = !cls.isInterface(); // true
    cls = java.lang.Cloneable.class;
    isClass = !cls.isInterface(); // false
  }
}





Get Super Interfaces

  
/*
 * The contents of this file are subject to the Sapient Public License
 * Version 1.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * http://carbon.sf.net/License.html.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is The Carbon Component Framework.
 *
 * The Initial Developer of the Original Code is Sapient Corporation
 *
 * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
 *
 *
 * Copyright 2003 Sapient
 * @since carbon 2.0
 * @author Greg Hinkle, March 2003
 * @version $Revision: 1.5 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $)
 */
public class ClassUtil {
    /**
     * Retrieves all interfaces implemented by a specified interface
     * including all recursively extended interfaces and the classes supplied
     * int the parameter.
     * @param childInterfaces a set of interfaces
     * @return Class[] an array of interfaces that includes those specifed
     * in childInterfaces plus all of those interfaces" super interfaces
     */
    public static Class[] getSuperInterfaces(Class[] childInterfaces) {
        List allInterfaces = new ArrayList();
        for (int i = 0; i < childInterfaces.length; i++) {
            allInterfaces.add(childInterfaces[i]);
            allInterfaces.addAll(
                Arrays.asList(
                    getSuperInterfaces(childInterfaces[i].getInterfaces())));
        }
        return (Class[]) allInterfaces.toArray(new Class[allInterfaces.size()]);
    }
    /**
     * Builds an <b>unordered</b> set of all interface and object classes that
     * are generalizations of the provided class.
     * @param classObject the class to find generalization of.
     * @return a Set of class objects.
     */
    public static Set getGeneralizations(Class classObject) {
        Set generalizations = new HashSet();
        generalizations.add(classObject);
        Class superClass = classObject.getSuperclass();
        if (superClass != null) {
            generalizations.addAll(getGeneralizations(superClass));
        }
        Class[] superInterfaces = classObject.getInterfaces();
        for (int i = 0; i < superInterfaces.length; i++) {
            Class superInterface = superInterfaces[i];
            generalizations.addAll(getGeneralizations(superInterface));
        }
        return generalizations;
    }
}





Listing the Interfaces That a Class Implements

   
public class Main {
  public static void main(String[] argv) throws Exception {
    Class cls = java.lang.String.class;
    Class[] intfs = cls.getInterfaces();
  }
}





Listing the Interfaces That an Interface Extends

   
public class Main {
  public static void main(String[] argv) throws Exception {
    Class cls = java.util.List.class;
    Class[] intfs = cls.getInterfaces(); // java.util.Collection
  }
}





Returns true if a class implements Serializable and false otherwise.

 
import java.io.Serializable;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

public class Main {
  /**
   * Returns <code>true</code> if a class implements <code>Serializable</code>
   * and <code>false</code> otherwise.
   *
   * @param c  the class.
   *
   * @return A boolean.
   */
  public static boolean isSerializable(final Class c) {
      /**
      final Class[] interfaces = c.getInterfaces();
      for (int i = 0; i < interfaces.length; i++) {
          if (interfaces[i].equals(Serializable.class)) {
              return true;
          }
      }
      Class cc = c.getSuperclass();
      if (cc != null) {
          return isSerializable(cc);
      }
       */
      return (Serializable.class.isAssignableFrom(c));
  }
}





Returns true if type is implementing Map

  
// $Id: ReflectionHelper.java 16271 2009-04-07 20:20:12Z hardy.ferentschik $
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,  
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
 * Some reflection utility methods.
 *
 * @author Hardy Ferentschik
 */
public class ReflectionHelper {
  /**
   * @param type the type to check.
   *
   * @return Returns <code>true</code> if <code>type</code> is implementing <code>Map</code>, <code>false</code> otherwise.
   */
  public static boolean isMap(Type type) {
    if ( type instanceof Class && isMapClass( ( Class ) type ) ) {
      return true;
    }
    if ( type instanceof ParameterizedType ) {
      return isMap( ( ( ParameterizedType ) type ).getRawType() );
    }
    if ( type instanceof WildcardType ) {
      Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds();
      return upperBounds.length != 0 && isMap( upperBounds[0] );
    }
    return false;
  }
  /**
   * Checks whether the specified class parameter is an instance of a collection class.
   *
   * @param clazz <code>Class</code> to check.
   *
   * @return <code>true</code> is <code>clazz</code> is instance of a collection class, <code>false</code> otherwise.
   */
  private static boolean isMapClass(Class<?> clazz) {
    List<Class<?>> classes = new ArrayList<Class<?>>();
    computeClassHierarchy( clazz, classes );
    return classes.contains( Map.class );
  }
  /**
   * Get all superclasses and interfaces recursively.
   *
   * @param clazz The class to start the search with.
   * @param classes List of classes to which to add all found super classes and interfaces.
   */
  private static void computeClassHierarchy(Class<?> clazz, List<Class<?>> classes) {
    for ( Class current = clazz; current != null; current = current.getSuperclass() ) {
      if ( classes.contains( current ) ) {
        return;
      }
      classes.add( current );
      for ( Class currentInterface : current.getInterfaces() ) {
        computeClassHierarchy( currentInterface, classes );
      }
    }
  }
}





Search over classpath retrieving classes that implement a certain interface

   
/*
 * The contents of this file are subject to the Sapient Public License
 * Version 1.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * http://carbon.sf.net/License.html.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is The Carbon Component Framework.
 *
 * The Initial Developer of the Original Code is Sapient Corporation
 *
 * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
 */

import java.io.File;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * <p>This class implements the capability to search over the current classpath
 * retrieving classes that implement a certain interface.</p>
 *
 * Copyright 2001 Sapient
 * @since carbon 1.0
 * @author Greg Hinkle, June 2001
 * @version $Revision: 1.10 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $)
 */
public class ClassFinder {
    /**
     * Tracks the count of classes found that match the
     * provided criteria.
     */
    protected long foundClasses = 0;
    /**
     * The super class criteria
     */
    protected Class superClass = null;
    /**
     * The required substring path criteria for this searcher
     */
    protected String requiredPathSubstring = null;
    /**
     * The set of classes found matching the provided criteria.
     */
    protected Set classes = new HashSet(2000);

    /**
     * <p>Instantiates the type of MBeanHarvester that will return all classes
     * in the entire classpath.</p>
     */
    public ClassFinder() {
    }
    /**
     * <p>Instantiates the type of MBeanHarvester that will return all classes
     * that are assignable to the supplied class. This would include all
     * implementations of it, if it is an interface or it and all subclasses
     * of it if it"s a class.</p>
     *
     * @param superClass the Class that should be searched for along with
     *   implementations and subclasses
     */
    public ClassFinder(Class superClass) {
        this.superClass = superClass;
    }
    /**
     * <p>Instantiates the type of MBeanHarvester that will return all classes
     * that are assignable to the supplied class and are part of the supplied
     * package. This would include all  implementations of it, if it is an
     * interface or it and all subclasses of it if it"s a class. The
     * supplied <code>requiredPathSubstring must be part of the fully
     * qualified classname.</p>
     *
     * @param superClass the Class that should be searched for along with
     *   implementations and subclasses
     * @param requiredPathSubstring the String part that must be found in the
     *   classes FQN
     */
    public ClassFinder(Class superClass, String requiredPathSubstring) {
        this.superClass = superClass;
        this.requiredPathSubstring = requiredPathSubstring;
    }

    /**
     * <p>Adds a class name to the list of found classes if and only if it meets
     * the configured requirements.</p>
     *
     * @param className the FQN String name of the class to add
     */
    protected void addClassName(String className) {
        // Only add this class if we"re not checking for a particular
        // substring of the FQN or we find that substring
        if ((this.requiredPathSubstring == null) ||
            (className.indexOf(this.requiredPathSubstring) >= 0)) {
            if (this.superClass == null) {
                this.classes.add(className);
            } else {
                try {
                    // TODO: GH - add a way to search other classpaths and the
                    // system classpath.
                    Class theClass =
                        Class.forName(
                            className,
                            false,
                            this.getClass().getClassLoader());
                    if (this.superClass.isAssignableFrom(theClass)) {
                        this.classes.add(className);
                    }
                } catch (ClassNotFoundException cnfe) {
                    // Used to catch mis-parsed classnames
                } catch (Throwable t) {
                    // Used to catch JVM security and linkage errors
                }
            }
        }
    }

    /**
     * <p>Used to retrieve the results <code>Set</code> from this harvester"s
     * search.</p>
     *
     * @return Set the set of classes that meet this harvester"s requirements
     */
    public Set getClasses() {
        // 1) tokenize classpath
        String classpath = System.getProperty("java.class.path");
        String pathSeparator = System.getProperty("path.separator");
        StringTokenizer st = new StringTokenizer(classpath,pathSeparator);
        // 2) for each element in the classpath
        while (st.hasMoreTokens()) {
            File currentDirectory = new File(st.nextToken());
            processFile(currentDirectory.getAbsolutePath(),"");
        }
        return this.classes;
    }

    /**
     * Recursively search through Directories with special checks to recognize
     * zip and jar files. (Zip and Jar files return true from
     * &lt;File&gt;.isDirectory())
     * @param base the base file path to search
     * @param current the current recursively searched file path being searched
     */
    private void processFile(String base, String current) {
        File currentDirectory = new File(base + File.separatorChar + current);
        // Handle special for archives
        if (isArchive(currentDirectory.getName())) {
            try {
                processZip(new ZipFile(currentDirectory));
            } catch (Exception e) {
                // The directory was not found so the classpath was probably in
                // error or we don"t have rights to it
            }
            return;
        } else {
            Set directories = new HashSet();
            File[] children = currentDirectory.listFiles();
            // if no children, return
            if (children == null || children.length == 0) {
                return;
            }
            // check for classfiles
            for (int i = 0; i < children.length; i++) {
                File child = children[i];
                if (child.isDirectory()) {
                    directories.add(children[i]);
                } else {
                    if (child.getName().endsWith(".class")) {
                        String className =
                            getClassName(
                                current +
                                ((current == "") ? "" : File.separator) +
                                child.getName());
                        addClassName(className);
                        this.foundClasses++;
                    }
                }
            }
            //call process file on each directory.  This is an iterative call!!
            for (Iterator i = directories.iterator(); i.hasNext(); ) {
                processFile(base, current + ((current=="")?"":File.separator) +
                    ((File)i.next()).getName());
            }
        }
    }

    /**
     * <p>Looks at the name of a file to determine if it is an archive</p>
     * @param name the name of a file
     * @return true if a file in the classpath is an archive
     * such as a Jar or Zip file
     */
    protected boolean isArchive(String name) {
        if ((name.endsWith(".jar") ||
            (name.endsWith(".zip")))) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * <p>Returns the Fully Qualified Class name of a class from it"s path
     * @param fileName the full path to a class
     * @return the FQN of a class
     */
    protected String getClassName(String fileName) {
        String newName =  fileName.replace(File.separatorChar,".");
        // Because zipfiles don"t have platform specific seperators
        newName =  newName.replace("/",".");
        return newName.substring(0, fileName.length() - 6);
    }

    /**
     * <P>Iterates through the files in a zip looking for files that may be
     * classes. This is not recursive as zip"s in zip"s are not searched by the
     * classloader either.</p>
     *
     * @param file The ZipFile to be searched
     */
    protected void processZip(ZipFile file) {
        Enumeration files = file.entries();
        while (files.hasMoreElements()) {
            Object tfile = files.nextElement();
            ZipEntry child = (ZipEntry) tfile;
            if (child.getName().endsWith(".class")) {
                addClassName(getClassName(child.getName()));
                this.foundClasses++;
            }
        }
    }
}





The interfaces for a primitive type is an empty array

   
public class Main {
  public static void main(String[] argv) throws Exception {
    Class cls = int.class;
    Class[] intfs = cls.getInterfaces(); // []
  }
}





The superclass of interfaces is always null

   
public class Main {
  public static void main(String[] argv) throws Exception {
    Class cls = java.lang.Cloneable.class;
    Class sup = cls.getSuperclass(); // null
  }
}