Java/Reflection/Interface
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Class Reflection: implemented interfaces
- 2 Class Reflection: is it an interface
- 3 Determining If a Class Object Represents a Class or Interface
- 4 Get Super Interfaces
- 5 Listing the Interfaces That a Class Implements
- 6 Listing the Interfaces That an Interface Extends
- 7 Returns true if a class implements Serializable and false otherwise.
- 8 Returns true if type is implementing Map
- 9 Search over classpath retrieving classes that implement a certain interface
- 10 The interfaces for a primitive type is an empty array
- 11 The superclass of interfaces is always null
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
* <File>.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
}
}