java学习总结之反射(reflection)

反射中要用到的类

首先给大家推荐一个在线文档工具 http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

这是一个在线的java api文档,当然你点一下左上角会有更多好工具。

说到反射,我们得先了解一下反射中可能要用到的包和相关类。很明显,文档里已经写得很明白了。

Class类

这是反射中最重要的类,有句话是这样的。

每个class 都是Class类的实例对象。而我们反射就是通过这个实例对象对类进行各种骚操作。

其中会使用的方法都可以在这个类中查看。这里是它最重要的方法forName。

java.lang.reflect包

通过Class类中的方法可以得到这些类的实例对象,如下,字段,构造器,方法。基本会使用的都有。Field,Method,Constructor<T> 

哈哈哈哈哈哈~~~~~

我自横刀向天笑,笑完我就去睡觉,睡完我又举起刀,我又横刀向天笑。 

获得Class类实例对象的方式

一般反射跟注解是会一起用的,所以先创了一个注解,和一个骚类。

好,骚话到此结束,接下来,这个Father类就是我们要反复鞭挞的对象了。

package F;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface My_Annotation {
String value();
}
package F;
@My_Annotation("你好")
public class Father {
	public String str1="我是你爸爸";
	String str2="你且不要随意走动,我去买两个橘子";
	public void say() {
		System.out.println("在下叶良辰");
	}
	void stop() {
		System.out.println("阁下有何指教");
	}
}

(1)调用类的class属性来获得Class类的实例对象

好像基本按照的活动跳转都是通过这种方法传入class,一不需要new,二的话要跳转的活动也基本是已知类名的。

Class myClass=Father.class;

(2)通过实例对象的getClass()方法来获得Class类的实例对象

这种方式。。。基本应用的话,emmmm~~~

Father father=new Father();
Class myClass2=father.getClass();

(3)通过Class类的forName()方法来获得Class类的实例对象

这种方式就是我们经常用到的了,动态的加载类,参数要填全名,感觉这些要深入的话,就得学习一波java虚拟机了。

【转】JVM类装载机制的解析,热更新的探讨

我们暂时不管这些,反正知道给它一个名字,它给你一个class就行了。

Class myClass3=Class.forName("F.Father");

反射之应用

基本上拿到了class之后就可以通过以下方法获得该Class的方法,注解,字段,构造器,返回形式就是单个的对象,或者一个一维数组。

方法摘要
A  extends Annotation getAnnotation(Class<A> annotationClass) 
          如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
 Annotation[] getAnnotations() 
          返回此元素上存在的所有注释。
 Constructor<T> getConstructor(Class<?>... parameterTypes) 
          返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
 Constructor<?>[] getConstructors() 
          返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
 Annotation[] getDeclaredAnnotations() 
          返回直接存在于此元素上的所有注释。
 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
          返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
 Constructor<?>[] getDeclaredConstructors() 
          返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
 Field getDeclaredField(String name) 
          返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
 Field[] getDeclaredFields() 
          返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
 Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
          返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
 Method[] getDeclaredMethods() 
          返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
 Method getEnclosingMethod() 
          如果此 Class 对象表示某一方法中的一个本地或匿名类,则返回 Method 对象,它表示底层类的立即封闭方法。
 Field getField(String name) 
          返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
 Field[] getFields() 
          返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
 Type[] getGenericInterfaces() 
          返回表示某些接口的 Type,这些接口由此对象所表示的类或接口直接实现。
 Type getGenericSuperclass() 
          返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。
 Method getMethod(String name, Class<?>... parameterTypes) 
          返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
 Method[] getMethods() 
          返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

(1)获得注解

骚年,这里有一本绝世武功的秘籍,以后保家卫国的重任就交于你了     九阳神功   (里面貌似写着两个大字  注解)

Class myClass=Father.class;
System.out.println("----------------获得注解");
Annotation annotation=myClass.getAnnotation(My_Annotation.class);
System.out.println("注解:"+((My_Annotation) annotation).value());

当然现在我们是在Father类对象中调用的getAnnotation(Class<A> annotationClass)方法,其中还有getAnnotations()方法,不只这些,Method,Field,Constructor类中都有对应的两个方法,不同的是一个返回单个注解,一个返回一个注解的一维数组。详情可以在对应的api文档中查看。

(2)获得字段

获得字段也是调用对应方法即可,注意的是有多个获得字段的方法,其中有访问权限的问题,看仔细了。

System.out.println("----------------获得字段");
Field myField=myClass.getField("str1");
System.out.println(myField.get(father));
			

这里的str1访问权限是public,所以可以用getField();如过不是public的访问权限。就会出现如下错误。所以当访问权限非public时,我们需要使用getDeclaredField(String name)  或 getDeclaredFields() 

值得注意的是get()方法中传的参数,普通类是传实例对象,而接口类,没有实例对象,所以是传class实例对象。如果弄错了也会报错。

(3)获得方法

      瞧,我发现了什么,invoke()方法,这是之前我看别人库的源代码经常看见却不知道是干什么的代码,现在也不太清楚,值得研究。

其实获得方法,获得注解,获得字段等都是大同小异,详情还是看api文档。

System.out.println("----------------获得方法");
Method myMethod=myClass.getMethod("say");
myMethod.invoke(father);

(4)获得构造器

哈哈哈哈,class类中的这些方法里面需要传的参数我也没看,大致就是名字,类型之类的。

System.out.println("----------------获得构造器");
Constructor<Father> myConstructor=myClass.getConstructor(null);
myConstructor.newInstance(null);

小结

其实只是简单的了解了下反射,讲述的方法也是针对单个的,多个话的通过数组进行操作,各种方法如何使用的,通过api文档配合百度就ok了,反射中还有修改类这种操作,后续再了解吧,invoke,这东西,哈哈。

小弟写的博客主要是通过写,来加深自己的学习,记述一下踩了什么坑和接下来需要了解的东西,要是有什么讲错了的,或者说了什么骚话得罪了各位大佬,打我可以,不要打我的脸就行。

猜你喜欢

转载自blog.csdn.net/qq_40687864/article/details/84646513