上周上课老师点我起来回答问题,问了一下JAVA反射机制,我本来对JAVA用得不多,加上有一段时间没有看过了,所以并没有能够答出来,之后就想要好好理解理解,加上老师布置作业让弄懂JAVA反射和Class类,所以CSDN第一次写博客,就来写写我对反射和Class的学习之后的感受吧。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一.什么是JAVA的反射机制。
JAVA反射是指在程序运行时获取已知名称的类或已有对象的相关信息的一种机制。简单说来,就是可以在程序运行过程中得到刚刚知道的一个类的内部结构。就像老师所说的,反射是和动态挂钩的,反射就意味着我们可以动态地获取信息,动态地调用,创建对象。
在这里还是先给出一个简单的例子让大家稍微熟悉一下。也方便接下来Class的学习。
import java.util.Scanner; import java.lang.reflect.Method; public class ClassForName { public ClassForName(){ try { Scanner inScanner = new Scanner(System.in); Class> classinstance=Class.forName(inScanner.next()); //根据输入返回一个类对象 Method[] method=classinstance.getDeclaredMethods();//利用得到的Class对象,返回该类对象的方法集合 System.out.println("forName:"+classinstance); for(Method me:method){ System.out.println("方法有:"+me.toString()); }//输出所有方法的名称 }catch (ClassNotFoundException e) { e.printStackTrace(); } } public static void main(String[] args) { new ClassForName(); } }
这里给出这个例子的输出,当我输入java.lang.Class时,返回所有方法,输出为:方法有:private java.lang.Object java.lang.Class.newInstance0() throws java.lang.InstantiationException,java.lang.IllegalAccessException
方法有:public static java.lang.Class java.lang.Class.forName(java.lang.String,boolean,java.lang.ClassLoader) throws java.lang.ClassNotFoundException
方法有:public static java.lang.Class java.lang.Class.forName(java.lang.String) throws java.lang.ClassNotFoundException
方法有:private static native java.lang.Class java.lang.Class.forName0(java.lang.String,boolean,java.lang.ClassLoader) throws java.lang.ClassNotFoundException方法有:public native boolean java.lang.Class.isAssignableFrom(java.lang.Class)
方法有:public native boolean java.lang.Class.isInstance(java.lang.Object)
方法有:public native int java.lang.Class.getModifiers()
方法有:public native boolean java.lang.Class.isInterface()
方法有:public native boolean java.lang.Class.isArray()
方法有:public native boolean java.lang.Class.isPrimitive()
方法有:public native java.lang.Class java.lang.Class.getSuperclass()
方法有:public native java.lang.Class java.lang.Class.getComponentType()
方法有:private static native void java.lang.Class.registerNatives()
方法有:public java.lang.String java.lang.Class.toString()
方法有:public java.lang.String java.lang.Class.getName()
方法有:static boolean java.lang.Class.access$100(java.lang.Object[],java.lang.Object[])
方法有:static boolean java.lang.Class.access$202(boolean)
方法有:static boolean java.lang.Class.access$302(boolean)
方法有:private static void java.lang.Class.addAll(java.util.Collection,java.lang.reflect.Field[])
方法有:private static java.lang.String java.lang.Class.argumentTypesToString(java.lang.Class[])
方法有:private static boolean java.lang.Class.arrayContentsEq(java.lang.Object[],java.lang.Object[])
方法有:public java.lang.Class java.lang.Class.asSubclass(java.lang.Class)
方法有:public java.lang.Object java.lang.Class.cast(java.lang.Object)
方法有:private static void java.lang.Class.checkInitted()
方法有:private void java.lang.Class.checkMemberAccess(int,java.lang.ClassLoader)
方法有:private void java.lang.Class.clearCachesOnClassRedefinition()
方法有:private static java.lang.reflect.Constructor[] java.lang.Class.copyConstructors(java.lang.reflect.Constructor[])
方法有:private static java.lang.reflect.Field[] java.lang.Class.copyFields(java.lang.reflect.Field[])
方法有:private static java.lang.reflect.Method[] java.lang.Class.copyMethods(java.lang.reflect.Method[])
方法有:public boolean java.lang.Class.desiredAssertionStatus()
方法有:private static native boolean java.lang.Class.desiredAssertionStatus0(java.lang.Class)
方法有:java.util.Map java.lang.Class.enumConstantDirectory()
方法有:public java.lang.annotation.Annotation java.lang.Class.getAnnotation(java.lang.Class)
方法有:sun.reflect.annotation.AnnotationType java.lang.Class.getAnnotationType()
方法有:public java.lang.annotation.Annotation[] java.lang.Class.getAnnotations()
方法有:public java.lang.String java.lang.Class.getCanonicalName()
方法有:public java.lang.ClassLoader java.lang.Class.getClassLoader()
方法有:native java.lang.ClassLoader java.lang.Class.getClassLoader0()
方法有:public java.lang.Class[] java.lang.Class.getClasses()
方法有:native sun.reflect.ConstantPool java.lang.Class.getConstantPool()
方法有:public java.lang.reflect.Constructor java.lang.Class.getConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException
方法有:private java.lang.reflect.Constructor java.lang.Class.getConstructor0(java.lang.Class[],int) throws java.lang.NoSuchMethodException
方法有:public java.lang.reflect.Constructor[] java.lang.Class.getConstructors() throws java.lang.SecurityException
方法有:public java.lang.annotation.Annotation[] java.lang.Class.getDeclaredAnnotations()
方法有:public java.lang.Class[] java.lang.Class.getDeclaredClasses() throws java.lang.SecurityException
方法有:private native java.lang.Class[] java.lang.Class.getDeclaredClasses0()
方法有:public java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructor(java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException
方法有:public java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors() throws java.lang.SecurityException
方法有:private native java.lang.reflect.Constructor[] java.lang.Class.getDeclaredConstructors0(boolean)
方法有:public java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String) throws java.lang.NoSuchFieldException,java.lang.SecurityException
方法有:public java.lang.reflect.Field[] java.lang.Class.getDeclaredFields() throws java.lang.SecurityException
方法有:private native java.lang.reflect.Field[] java.lang.Class.getDeclaredFields0(boolean)
方法有:public java.lang.reflect.Method java.lang.Class.getDeclaredMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException
方法有:public java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods() throws java.lang.SecurityException
方法有:private native java.lang.reflect.Method[] java.lang.Class.getDeclaredMethods0(boolean)
方法有:public native java.lang.Class java.lang.Class.getDeclaringClass()
方法有:public java.lang.Class java.lang.Class.getEnclosingClass()
方法有:public java.lang.reflect.Constructor java.lang.Class.getEnclosingConstructor()
方法有:public java.lang.reflect.Method java.lang.Class.getEnclosingMethod()
方法有:private native java.lang.Object[] java.lang.Class.getEnclosingMethod0()
方法有:private java.lang.Class$EnclosingMethodInfo java.lang.Class.getEnclosingMethodInfo()
方法有:public java.lang.Object[] java.lang.Class.getEnumConstants()
方法有:java.lang.Object[] java.lang.Class.getEnumConstantsShared()
方法有:private sun.reflect.generics.factory.GenericsFactory java.lang.Class.getFactory()
方法有:public java.lang.reflect.Field java.lang.Class.getField(java.lang.String) throws java.lang.NoSuchFieldException,java.lang.SecurityException
方法有:private java.lang.reflect.Field java.lang.Class.getField0(java.lang.String) throws java.lang.NoSuchFieldException
方法有:public java.lang.reflect.Field[] java.lang.Class.getFields() throws java.lang.SecurityException
方法有:private sun.reflect.generics.repository.ClassRepository java.lang.Class.getGenericInfo()
方法有:public java.lang.reflect.Type[] java.lang.Class.getGenericInterfaces()
方法有:private native java.lang.String java.lang.Class.getGenericSignature()
方法有:public java.lang.reflect.Type java.lang.Class.getGenericSuperclass()
方法有:public native java.lang.Class[] java.lang.Class.getInterfaces()
方法有:public java.lang.reflect.Method java.lang.Class.getMethod(java.lang.String,java.lang.Class[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException
方法有:private java.lang.reflect.Method java.lang.Class.getMethod0(java.lang.String,java.lang.Class[])
方法有:public java.lang.reflect.Method[] java.lang.Class.getMethods() throws java.lang.SecurityException
方法有:private native java.lang.String java.lang.Class.getName0()
方法有:public java.lang.Package java.lang.Class.getPackage()
方法有:static native java.lang.Class java.lang.Class.getPrimitiveClass(java.lang.String)
方法有:public java.security.ProtectionDomain java.lang.Class.getProtectionDomain()
方法有:private native java.security.ProtectionDomain java.lang.Class.getProtectionDomain0()
方法有:private native byte[] java.lang.Class.getRawAnnotations()
方法有:private static sun.reflect.ReflectionFactory java.lang.Class.getReflectionFactory()
方法有:public java.net.URL java.lang.Class.getResource(java.lang.String)
方法有:public java.io.InputStream java.lang.Class.getResourceAsStream(java.lang.String)
方法有:public native java.lang.Object[] java.lang.Class.getSigners()
方法有:private java.lang.String java.lang.Class.getSimpleBinaryName()
方法有:public java.lang.String java.lang.Class.getSimpleName()
方法有:public java.lang.reflect.TypeVariable[] java.lang.Class.getTypeParameters()
方法有:private synchronized void java.lang.Class.initAnnotationsIfNecessary()
方法有:public boolean java.lang.Class.isAnnotation()
方法有:public boolean java.lang.Class.isAnnotationPresent(java.lang.Class)
方法有:public boolean java.lang.Class.isAnonymousClass()
方法有:private static boolean java.lang.Class.isAsciiDigit(char)
方法有:public boolean java.lang.Class.isEnum()
方法有:public boolean java.lang.Class.isLocalClass()
方法有:private boolean java.lang.Class.isLocalOrAnonymousClass()
方法有:public boolean java.lang.Class.isMemberClass()
方法有:public boolean java.lang.Class.isSynthetic()
方法有:public java.lang.Object java.lang.Class.newInstance() throws java.lang.InstantiationException,java.lang.IllegalAccessException
方法有:private java.lang.reflect.Constructor[] java.lang.Class.privateGetDeclaredConstructors(boolean)
方法有:private java.lang.reflect.Field[] java.lang.Class.privateGetDeclaredFields(boolean)
方法有:private java.lang.reflect.Method[] java.lang.Class.privateGetDeclaredMethods(boolean)
方法有:private java.lang.reflect.Field[] java.lang.Class.privateGetPublicFields(java.util.Set)
方法有:private java.lang.reflect.Method[] java.lang.Class.privateGetPublicMethods()
方法有:private java.lang.String java.lang.Class.resolveName(java.lang.String)
方法有:private java.lang.reflect.Field java.lang.Class.searchFields(java.lang.reflect.Field[],java.lang.String)
方法有:private static java.lang.reflect.Method java.lang.Class.searchMethods(java.lang.reflect.Method[],java.lang.String,java.lang.Class[])
方法有:void java.lang.Class.setAnnotationType(sun.reflect.annotation.AnnotationType)
方法有:native void java.lang.Class.setProtectionDomain0(java.security.ProtectionDomain)
方法有:native void java.lang.Class.setSigners(java.lang.Object[])
方法有:private static java.lang.Class java.lang.Class.toClass(java.lang.reflect.Type)
跟官方文档给出的方法一样,这里我们将Class的所有方法列举了出来,这恰恰体现反射中的动态获取信息。 ps.在这里,将比较重要的方法加黑标记出来。
二.反射的重要“嘉宾”--Class类解读
上面我们用一个小例子,列举除了Class类的方法,下面是时候来好好分析分析Class类了,首先Class类没有公共的构造方法,它的对象是在加载类的时候由java虚拟机以及通过调用类加载器中的defineClass方法自动构造的,虚拟机为每一种类型都生成管理着一个Class对象。说白了,Class类就是一个大的模板,每一种具体的类型加载的时候,JVM都会生成一个相对应的Class对象来负责获取这一类型的所有内部信息。 这让我想到了一个小例子,Class就把它看作是一个模具,每一个空缺的不同图案都是类型中的一个部分,或是方法,或是属性,每当加载一个具体的类型的时候,往模具上一拍,就能够去得到所有想要的信息。
感觉这已经很白话文了,这个具体的过程在我看来就是这样,假如有错误的地方,欢迎批评指正。
在这之后,我先说说如何去生成Class对象,然后再挑选几个比较重要的方法谈谈理解。
如何生成Class对象
首先,老师给的方法是用到了Class类里面的静态方法forName()。
Class c =Class.forName("String"); Object obj = c.newInstance(); return obj;
其次,第二种方法,通过Object类中的getClass()方法来得到Class对象。String s; Class c = s.getClass();
第三种,就是直接用已经存在的类名去生成。Class c1 = String.class; Class c2 = double [] .class;
Class类中的方法
public static Class> forName(String className)
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.For example:
Class t = Class.forName("java.lang.Thread")
A call to forName("X") causes the class named X to be initialized.
public T newInstance()
Creates a new instance of the class represented by this Class object.Returns:
a newly allocated instance of the class represented by this object.
public ClassLoader getClassLoader()
Returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader.
Returns:
the class loader that loaded the class or interface represented by this object.
public String getName()
Returns the name of the entity (class, interface, array class, primitive type, or void) represented by this Class object, as a String.
三.小结与实例public T cast(Object obj)
Casts an object to the class or interface represented by this Class object.Returns:
the object after casting, or null if obj is null
最后写了一个工厂模式的实例,也算是重新好好地梳理了一下反射机制,作为对反射机制的总结。
import javax.xml.parsers.*; import org.w3c.dom.*; import org.xml.sax.SAXException; import java.io.*; public class TVFactory { public static void main(String args[]) { try { TV tv; TvFactory factory; factory=(TvFactory)XMLUtil.getBean(); tv=factory.produceTV(); tv.play(); } catch(Exception e) { System.out.println(e.getMessage()); } } } class HaierTV implements TV { public void play() { System.out.println("海尔电视机播放中......"); } } class HaierTVFactory implements TvFactory { public TV produceTV() { System.out.println("海尔电视机工厂生产海尔电视机。"); return new HaierTV(); } } class HisenseTV implements TV { public void play() { System.out.println("海信电视机播放中......"); } } class HisenseTVFactory implements TvFactory { public TV produceTV() { System.out.println("海信电视机工厂生产海信电视机。"); return new HisenseTV(); } } interface TV { public void play(); } interface TvFactory { public TV produceTV(); } class XMLUtil { public static Object getBean() { try { DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("config.xml")); NodeList nl = doc.getElementsByTagName("className"); Node classNode=nl.item(0).getFirstChild(); String cName=classNode.getNodeValue(); Class c=Class.forName(cName); Object obj=c.newInstance(); return obj; } catch(Exception e) { e.printStackTrace(); return null; } } }
欢迎批评指正 email:[email protected]