Java反射学习:深入学习Java反射机制
一、Java反射的理解(反射是研究框架的基础之一)
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
二、逐步分析
参考:https://blog.csdn.net/u012585964/article/details/52011138
1、关于Class
1、Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性
2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。 一个 Class 对象包含了特定某个类的有关信息。
4、Class 对象只能由系统建立对象
5、一个类在 JVM 中只会有一个Class实例
下面创建一个例子:后面的分析均以此案例为基准。
创建一个空接口:(后面会不断补充)
- package com.xfwl.reflection;
- public interface IHuman {
- }
创建一个空基类:(后面会不断补充)
- package com.xfwl.reflection;
- public class Human {
- }
创建一个子类:(后面会不断补充)
- package com.xfwl.reflection;
- public class Person extends Human implements IHuman {
- /**
- * 默认default修饰
- */
- String name;
- /**
- * private修饰
- */
- private int age;
- /**
- * public修饰
- */
- public char sex='M';
- /**
- * 无参构造
- */
- public Person(){
- System.out.println("无参构造!!!");
- }
- /**
- * 有参构造
- */
- public Person(String name,int age,char sex){
- System.out.println("有参构造!!!");
- this.name=name;
- this.age=age;
- this.sex=sex;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public char getSex() {
- return sex;
- }
- public void setSex(char sex) {
- this.sex = sex;
- }
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", sex='" + sex + '\'' +
- '}';
- }
- }
2、反射获取类对象的三种方式(通过一个Junit测试来说明)
- package com.xfwl.reflection;
- import org.junit.Test;
- /**
- * 测试类
- * @function
- * @author 小风微凉
- * @time 2018-6-3 下午12:28:38
- */
- public class TestAction {
- /**
- * 反射机制获取类有三种方法
- */
- @Test
- public void testGetClass() throws ClassNotFoundException {
- Class clazz = null;
- //1 直接通过类名.Class的方式得到
- clazz = Person.class;
- System.out.println("通过类名: " + clazz);
- //2 通过对象的getClass()方法获取,这个使用的少(一般是传的是Object,不知道是什么类型的时候才用)
- Object obj = new Person();
- clazz = obj.getClass();
- System.out.println("通过getClass(): " + clazz);
- //3 通过全类名获取,用的比较多,但可能抛出ClassNotFoundException异常
- clazz = Class.forName("com.xfwl.reflection.Person");
- System.out.println("通过全类名获取: " + clazz);
- }
- }
运行结果:
- 通过类名: class com.xfwl.reflection.Person
- 无参构造!!!
- 通过getClass(): class com.xfwl.reflection.Person
- 通过全类名获取: class com.xfwl.reflection.Person
特别注意:(以下2中方式不会调用构造方法,因为没有实例化操作)
- //1 直接通过类名.Class的方式得到
- clazz = Person.class;
- //3 通过全类名获取,用的比较多,但可能抛出ClassNotFoundException异常
- clazz = Class.forName("com.xfwl.reflection.Person");
3、利用newInstance创建对象:调用的类必须有无参的构造器
- /**
- * Class类的newInstance()方法,创建类的一个对象。
- * @throws ClassNotFoundException
- * @throws IllegalAccessException
- * @throws InstantiationException
- */
- @Test
- public void testNewInstance()
- throws ClassNotFoundException, IllegalAccessException, InstantiationException {
- Class clazz = Class.forName("com.xfwl.reflection.Person");
- //使用Class类的newInstance()方法创建类的一个对象
- //实际调用的类的那个 无参数的构造器(这就是为什么写的类的时候,要写一个无参数的构造器,就是给反射用的)
- //一般的,一个类若声明了带参数的构造器,也要声明一个无参数的构造器
- Object obj = clazz.newInstance();
- System.out.println(obj);
- }
测试结果:
那么,如果删除Person.java中的无参构造,继续测试,结果如下:
4、ClassLoader类加载器
- /**
- * ClassLoader类装载器
- */
- @Test
- public void testClassLoader1() throws ClassNotFoundException, IOException {
- //1、获取一个系统的类加载器
- ClassLoader classLoader = ClassLoader.getSystemClassLoader();
- System.out.println("系统的类加载器-->" + classLoader);
- //2、获取系统类加载器的父类加载器(扩展类加载器(extensions classLoader))
- classLoader = classLoader.getParent();
- System.out.println("扩展类加载器-->" + classLoader);
- //3、获取扩展类加载器的父类加载器
- //输出为Null,无法被Java程序直接引用
- classLoader = classLoader.getParent();
- System.out.println("启动类加载器-->" + classLoader);
- //4、测试当前类由哪个类加载器进行加载 ,结果就是系统的类加载器
- classLoader = Class.forName("com.xfwl.reflection.Person").getClassLoader();
- System.out.println("当前类由哪个类加载器进行加载-->"+classLoader);
- //5、测试JDK提供的Object类由哪个类加载器负责加载的
- //输出为Null,无法被Java程序直接引用
- classLoader = Class.forName("java.lang.Object").getClassLoader();
- System.out.println("JDK提供的Object类由哪个类加载器加载-->" + classLoader);
- }
测试结果:
- 系统的类加载器-->sun.misc.Launcher$AppClassLoader@18b4aac2
- 扩展类加载器-->sun.misc.Launcher$ExtClassLoader@614c5515
- 启动类加载器-->null
- 当前类由哪个类加载器进行加载-->sun.misc.Launcher$AppClassLoader@18b4aac2
- JDK提供的Object类由哪个类加载器加载-->null
5、反射机制通过加载器获取流对象:getResourceAsStream方法
- /**
- * 反射机制通过加载器获取流对象:getResourceAsStream方法
- * @throws ClassNotFoundException
- * @throws IOException
- */
- @Test
- public void testGetResourceAsStream() throws ClassNotFoundException, IOException {
- //调用getResourceAsStream 获取类路径下的文件对应的输入流
- /**
- * 特别说明:
- * getResourceAsStream("path"),path的路径和new Person()的位置有关
- */
- InputStream in = new Person().getClass().getClassLoader()
- .getResourceAsStream("com/xfwl/reflection/test.properties");
- System.out.println("in: " +in);
- Properties properties = new Properties();
- properties.load(in);
- System.out.println("文件内容:"+properties);
- System.out.println("name: "+properties.getProperty("name"));
- System.out.println("age: " + properties.getProperty("age"));
- System.out.println("sex: "+properties.getProperty("sex"));
- System.out.println("desc: " + properties.getProperty("desc"));
- }
test.properties文件内容如下:文件编码格式:ISO-8859-1
- name=\u5C0F\u98CE\u5FAE\u51C9\u0087\u0089
- age=23
- sex=M
- desc=\u53CD\u5C04\u673A\u5236\u5B66\u4E60
运行结果:(直接解析会出现乱码问题,这个可以通过new String(乱码格式处理参数)来处理)
- 无参构造!!!
- in: java.io.BufferedInputStream@215be6bb
- 文件内容:{age=23, name=小风微凉??, sex=M, desc=反射机制学习}
- name: 小风微凉??
- age: 23
- sex: M
- desc: 反射机制学习
6、反射机制获取类中的方法:Method: 对应类中的方法
现在给Person类添加一个private 方法、一个public 方法、一个defaut 方法、一个protected方法
- /**
- * Java权限有四个,分别为public,protected,默认,private,其开放程度依次降低
- * public可供所有类访问
- * protected继承可见
- * private只能类本身内部的方法可以访问
- */
- public void method_public(){
- System.out.println("method_public");
- }
- public void method_public_2(String name,int age,char sex){//public 带参数
- System.out.println("method_public_2");
- String info="Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", sex='" + sex + '\'' +
- '}';
- System.out.println(info);
- }
- protected void method_protected(){
- System.out.println("method_protected");
- }
- protected void method_protected_2(String info){//protected 带参数
- System.out.println("method_protected_2:"+info);
- }
- void method_default(){
- System.out.println("method_default");
- }
- void method_default_2(String info){//默认修饰符 带参数
- System.out.println("method_default_2:"+info);
- }
- private void method_private(){
- System.out.println("method_private");
- }
- private void method_private_2(String info){//private 带参数
- System.out.println("method_private_2:"+info);
- }
开始测试如何通过反射机制使用这些方法
- /**
- * 如何通过反射机制使用这些方法
- * @throws ClassNotFoundException
- * @throws NoSuchMethodException
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws InvocationTargetException
- */
- @Test
- public void testMethod() throws ClassNotFoundException, NoSuchMethodException,
- IllegalAccessException, InstantiationException, InvocationTargetException {
- Class clazz = Class.forName("com.xfwl.reflection.Person");
- //1、得到clazz 对应的类中有哪些方法,不能获取private方法
- Method[] methods =clazz.getMethods();
- System.out.println("通过反射机制可以拿到的方法:clazz.getMethods()");
- for (Method method : methods){
- System.out.println(method.getName());
- }
- System.out.println("<-------------------------->");
- //2、获取所有的方法(且只获取当着类声明的方法,包括private方法)
- Method[] methods2 = clazz.getDeclaredMethods();
- System.out.println("通过反射机制可以拿到的方法:clazz.getDeclaredMethods()");
- for (Method method : methods2){
- System.out.println(method.getName());
- }
- System.out.println("<-------------------------->");
- System.out.println("通过反射机制可以拿到指定的方法:clazz.getDeclaredMethod()");
- //3、获取指定的方法
- Method method1= clazz.getDeclaredMethod("method_private");
- System.out.println("private 无参:"+method1);
- Method method2 = clazz.getDeclaredMethod("method_private_2",String.class);//第一个参数是方法名,后面的是方法里的参数
- System.out.println("private 有参:"+method2);
- Method method3 = clazz.getDeclaredMethod("method_public_2",String.class,int.class,char.class);//第一个参数是方法名,后面的是方法里的参数
- System.out.println("public 有参:"+method2);
- //4、执行方法!
- Object obj = clazz.newInstance();
- method3.invoke(obj, "小风微凉", 23,'M'); //执行方法:invoke(类对象)
- }
测试结果:
- 通过反射机制可以拿到的方法:clazz.getMethods():不能获取private/protected/default方法
- toString
- getName
- setName
- method_public_2
- setAge
- method_public
- getSex
- getAge
- setSex
- wait
- wait
- wait
- equals
- hashCode
- getClass
- notify
- notifyAll
- <-------------------------->
- 通过反射机制可以拿到的方法:clazz.getDeclaredMethods():获取所有修饰权限的方法
- toString
- getName
- setName
- method_private_2
- method_private
- method_public_2
- setAge
- method_public
- method_default
- method_default_2
- getSex
- getAge
- setSex
- method_protected
- method_protected_2
- <-------------------------->
- 通过反射机制可以拿到指定的方法:clazz.getDeclaredMethod()
- private 无参:private void com.xfwl.reflection.Person.method_private()
- private 有参:private void com.xfwl.reflection.Person.method_private_2(java.lang.String)
- public 有参:private void com.xfwl.reflection.Person.method_private_2(java.lang.String)
- 无参构造!!!
- method_public_2
- Person{name='小风微凉', age=23, sex='M'}
继续分析一下:
JDK中的获取方法
获取方法:默认只能获取public修饰的方法
- @CallerSensitive
- public Method[] getMethods() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
- return copyMethods(privateGetPublicMethods());
- }
获取方法:所有修饰权限的方法都可以获得
- @CallerSensitive
- public Method[] getDeclaredMethods() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
- return copyMethods(privateGetDeclaredMethods(false));
- }
获取方法:获取指定的方法(所有修饰权限)
- /**
- * @jls 8.2 Class Members
- * @jls 8.4 Method Declarations
- * @since JDK1.1
- */
- @CallerSensitive
- public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
- Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
- if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
- }
- return method;
- }
分析一下上面这个方法:
String name:方法的名称
Class<?>... parameterTypes:一个或多个方法参数的类型,注意要一一对应,否则会报错的哦
执行方法:invoke(方法对象,方法实际参数)
- @CallerSensitive
- public Object invoke(Object obj, Object... args)
- throws IllegalAccessException, IllegalArgumentException,
- InvocationTargetException
- {
- if (!override) {
- if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = Reflection.getCallerClass();
- checkAccess(caller, clazz, obj, modifiers);
- }
- }
- MethodAccessor ma = methodAccessor; // read volatile
- if (ma == null) {
- ma = acquireMethodAccessor();
- }
- return ma.invoke(obj, args);
- }
7、反射机制获取类中的方法:Method: 对应基类或接口中的方法
上面分析了,如何通过反射拿到当前本类里面的各个修饰权限的方法,下面来继续分析一下,如何读取父类或实现的接口中的方法:
现在,给父类添加一些方法,在接口中定义一些方法:
接口中的方法声明:
- package com.xfwl.reflection;
- public interface IHuman {
- void eat();
- void eat(String info);
- }
Person.java实现接口方法
- public void eat() {
- System.out.println("实现接口的方法:eat()无参:");
- }
- public void eat(String info) {
- System.out.println("实现接口的方法:eat()有参:"+info);
- }
父类中的方法定义:
- package com.xfwl.reflection;
- public class Human {
- public void play_public(){
- System.out.println("public无参:play_public");
- }
- public void play_public_2(String info){
- System.out.println("public有参:play_public2:"+info);
- }
- protected void play_protected(){
- System.out.println("protected无参:play_protected");
- }
- protected void play_protected_2(String info){
- System.out.println("protected有参:play_protected_2:"+info);
- }
- void play_default(){
- System.out.println("默认修饰符无参:play_default");
- }
- void play_default_2(String info){//默认修饰符 带参数
- System.out.println("默认修饰符有参:play_default_2:"+info);
- }
- private void play_private(){
- System.out.println("private无参:play_private");
- }
- private void play_private_2(String info){
- System.out.println("private有参:play_private_2:"+info);
- }
- }
开始测试:
1、拿到当前Person类反射对象,能否得到接口中的方法
- /**
- * 反射机制获取类中的方法:Method: 对应基类或接口中的方法
- * @throws ClassNotFoundException
- * @throws SecurityException
- * @throws NoSuchMethodException
- * @throws InstantiationException
- * @throws InvocationTargetException
- * @throws IllegalArgumentException
- * @throws IllegalAccessException
- */
- @Test
- public void testInterfaceOrSupperClass() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
- Class clazz = Class.forName("com.xfwl.reflection.Person");
- //拿到当前Person类反射对象,能否得到接口中的方法
- for (Method method : clazz.getMethods()){
- System.out.println(method.getName());
- }
- //获取当前类实现的接口中的方法
- Method method1= clazz.getDeclaredMethod("eat");
- Method method2= clazz.getDeclaredMethod("eat",String.class);
- //执行
- method1.invoke(clazz.newInstance());
- method2.invoke(clazz.newInstance(),"eat有参数");
- }
测试结果:(可以拿到实现的接口中的方法并执行)
- toString
- getName
- setName
- eat
- eat
- method_public_2
- setAge
- getSex
- setSex
- getAge
- method_public
- play_public_2
- play_public
- wait
- wait
- wait
- equals
- hashCode
- getClass
- notify
- notifyAll
- 无参构造!!!
- 实现接口的方法:eat()无参:
- 无参构造!!!
- 实现接口的方法:eat()有参:eat有参数
2、拿到当前Person类反射对象,能否获取父类中的方法
通过当前反射对象,拿到父类反射对象
- Class clazz = Class.forName("com.xfwl.reflection.Person");
- Class superClazz = clazz.getSuperclass();
- /**
- * 反射机制获取类中的方法:Method: 对应基类或接口中的方法
- * @throws ClassNotFoundException
- * @throws SecurityException
- * @throws NoSuchMethodException
- * @throws InstantiationException
- * @throws InvocationTargetException
- * @throws IllegalArgumentException
- * @throws IllegalAccessException
- */
- @Test
- public void testInterfaceOrSupperClass() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
- Class clazz = Class.forName("com.xfwl.reflection.Person");
- System.out.println("<------------父类中能够使用的公共权限的方法------------------------>");
- //拿到当前Person类反射对象,能否获取父类中的方法
- Class superClazz = clazz.getSuperclass();
- for (Method method : superClazz.getMethods()){
- System.out.println(method.getName());
- }
- System.out.println("<----------------父类中所有的方法:仅仅父类中的方法-------------------->");
- //拿到父类中的所有权限修饰符修饰的方法
- for (Method method : superClazz.getDeclaredMethods()){
- System.out.println(method.getName());
- }
- }
运行结果:
- <------------父类中能够使用的公共权限的方法------------------------>
- play_public
- play_public_2
- wait
- wait
- wait
- equals
- toString
- hashCode
- getClass
- notify
- notifyAll
- <----------------父类中所有的方法:仅仅父类中的方法-------------------->
- play_private_2
- play_public
- play_public_2
- play_private
- play_protected
- play_default
- play_protected_2
- play_default_2
那么可以执行父类中的方法吗?
- //是否可以通过子类对象拿到父类中的方法
- Method method3= clazz.getDeclaredMethod("play_public");
- Method method4= clazz.getDeclaredMethod("play_public_2",String.class);
- Method method5= clazz.getDeclaredMethod("play_private");
- Method method6= clazz.getDeclaredMethod("play_private_2",String.class);
上面代码报错,说明不可以,public修饰的方法也拿不到
- Method method7= superClazz.getDeclaredMethod("play_public");
- Method method8= superClazz.getDeclaredMethod("play_public_2",String.class);
- Method method9= superClazz.getDeclaredMethod("play_private");
- Method method10= superClazz.getDeclaredMethod("play_private_2",String.class);
上面代码正常执行,说明父类的反射对象可以拿到自己的public或private方法
- //使用子类的反射对象执行方法
- method7.invoke(clazz.newInstance());
- method8.invoke(clazz.newInstance(), "play_public_2有参数");
- method9.invoke(clazz.newInstance()); //无法执行,Junit报错
- method10.invoke(clazz.newInstance(), "play_private_2有参数");//无法执行,Junit报错
- //使用父类的反射对象执行方法
- method7.invoke(superClazz.newInstance());
- method8.invoke(superClazz.newInstance(), "play_public_2有参数");
- method9.invoke(superClazz.newInstance()); //无法执行,Junit报错
- method10.invoke(superClazz.newInstance(), "play_private_2有参数");//无法执行,Junit报错
上面代码执行部分报错,说明通过子类的反射对象和拿到的父类反射对象,也仅仅只能执行public和protected和default默认修饰的方法,不能执行private修饰的方法
7、反射机制获取类中的字段属性:Field字段
- /**
- * 默认default修饰
- */
- String name;
- /**
- * private修饰
- */
- private int age;
- /**
- * public修饰
- */
- public char sex='M';
- /**
- * protected修饰
- */
- protected boolean isBeauty=true;
开始测试:如何获取
- /**
- * 反射机制获取类中的字段属性:Field字段
- * @throws ClassNotFoundException
- * @throws SecurityException
- * @throws NoSuchFieldException
- * @throws IllegalAccessException
- * @throws IllegalArgumentException
- */
- @Test
- public void testFiled() throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
- //拿到反射Class对象
- Class clazz = Class.forName("com.xfwl.reflection.Person");
- //获取Field的数组,私有字段也能获取
- Field[] fields = clazz.getDeclaredFields();
- System.out.println("<----遍历拿到字段:开始--------------------->");
- for (Field field: fields) {
- System.out.println(field.getName());
- }
- System.out.println("<------------获取指定名字的Field以及类型--------------------------->");
- //获取指定名字的Field(如果是私有的,见下面的4)
- Field field1 = clazz.getDeclaredField("name");
- System.out.println("获取指定Field名=: " + field1.getName()+",类型:"+field1.getType());
- Field field2 = clazz.getDeclaredField("age");
- System.out.println("获取指定Field名=: " + field2.getName()+",类型:"+field2.getType());
- Field field3 = clazz.getDeclaredField("sex");
- System.out.println("获取指定Field名=: " + field3.getName()+",类型:"+field3.getType());
- Field field4 = clazz.getDeclaredField("isBeauty");
- System.out.println("获取指定Field名=: " + field4.getName()+",类型:"+field4.getType());
- System.out.println("<----------获取指定对象的Field的值 ----------------------------->");
- Person person = new Person("小风微凉", 12,'M');
- //获取指定对象的Field的值
- Object val = field1.get(person);
- System.out.println("获取指定对象字段'name'的Field的值=: " + val);
- System.out.println("<----------设置指定对象的Field的值----------------------------->");
- //设置指定对象的Field的值
- field1.set(person, "反射学习A");
- System.out.println("设置指定对象字段'name'的Field的值=: " + person.name);
- System.out.println("<----------若该字段是私有的,需要调用setAccessible(true)方法----------------------------->");
- //若该字段是私有的,需要调用setAccessible(true)方法
- field2 = clazz.getDeclaredField("age");
- field2.setAccessible(true);
- System.out.println("获取指定私有字段名=: " + field2.getName());
- }
测试结果:
- <----遍历拿到字段:开始--------------------->
- name
- age
- sex
- isBeauty
- <------------获取指定名字的Field以及类型--------------------------->
- 获取指定Field名=: name,类型:class java.lang.String
- 获取指定Field名=: age,类型:int
- 获取指定Field名=: sex,类型:char
- 获取指定Field名=: isBeauty,类型:boolean
- <----------获取指定对象的Field的值 ----------------------------->
- 有参构造!!!
- 获取指定对象字段'name'的Field的值=: 小风微凉
- <----------设置指定对象的Field的值----------------------------->
- 设置指定对象字段'name'的Field的值=: 反射学习A
- <----------若该字段是私有的,需要调用setAccessible(true)方法----------------------------->
- 获取指定私有字段名=: age
8、反射机制获取类中的构造器:构造器(Constructor)
Person的构造器
- /**
- * 无参构造
- */
- public Person(){
- System.out.println("无参构造!!!");
- }
- /**
- * 有参构造
- */
- public Person(String name,int age,char sex){
- System.out.println("有参构造!!!");
- this.name=name;
- this.age=age;
- this.sex=sex;
- }
@Test测试
- /**
- * 构造器:开发用的比较少
- */
- @Test
- public void testConstructor() throws ClassNotFoundException, NoSuchMethodException,
- IllegalAccessException, InvocationTargetException, InstantiationException {
- String className = "com.xfwl.reflection.Person";
- Class<Person> clazz = (Class<Person>) Class.forName(className);
- //1.获取Constructor对象
- Constructor<Person>[] constructors =
- (Constructor<Person>[]) Class.forName(className).getConstructors();
- System.out.println("<-------------打印所有的构造器---------------------->");
- for (Constructor<Person> constructor: constructors) {
- System.out.println(constructor);
- }
- System.out.println("<------------------------------------------------>");
- Constructor<Person> constructor = clazz.getConstructor(String.class, int.class,char.class);
- System.out.println("拿到指定的-->" + constructor);
- //2.调用构造器的newInstance()方法创建对象
- Object obj= constructor.newInstance("changwen", 11,'M');
- }
运行结果:
- <-------------打印所有的构造器---------------------->
- public com.xfwl.reflection.Person()
- public com.xfwl.reflection.Person(java.lang.String,int,char)
- <------------------------------------------------>
- 拿到指定的-->public com.xfwl.reflection.Person(java.lang.String,int,char)
- 有参构造!!!
9、反射机制获取类中的注解:注解(Annotation)
基本的 Annotation
自定义 Annotation
- package com.xfwl.reflection;
- 3 import java.lang.annotation.ElementType;
- 4 import java.lang.annotation.Retention;
- 5 import java.lang.annotation.RetentionPolicy;
- 6 import java.lang.annotation.Target;
- public class Person extends Human implements IHuman {
- @Retention(RetentionPolicy.RUNTIME) //运行时检验
- @Target(value = {ElementType.METHOD}) //作用在方法上
- public @interface AgeValidator {
- int min();
- int max();
- }
- //......其余部分省略
- }
- /**
- * 自定义一个注解:检查年龄范围
- * @function
- * @author 小风微凉
- * @time 2018-6-3 下午3:56:03
- */
- @Retention(RetentionPolicy.RUNTIME) //运行时检验
- @Target(value = {ElementType.METHOD}) //作用在方法上
- public @interface AgeValidator {
- int min();
- int max();
- }
@Test测试
- /**
- * 通过反射才能获取注解
- */
- @Test
- public void testAnnotation() throws Exception {
- //这样的方式不能使用注解
- /*Person person3 = new Person();
- person3.setAge(10);*/
- //拿到反射Class对象
- String className = "com.xfwl.reflection.Person";
- Class clazz = Class.forName(className);
- Object obj = clazz.newInstance();
- //拿到指定方法
- Method method = clazz.getDeclaredMethod("setAge",int.class);
- int val =40;
- //获取注解
- Annotation annotation = method.getAnnotation(AgeValidator.class);
- if (annotation != null){
- if (annotation instanceof AgeValidator){
- AgeValidator ageValidator = (AgeValidator) annotation;
- if (val< ageValidator.min() || val>ageValidator.max()){
- throw new RuntimeException("数值超出范围");
- }
- }
- }
- //执行方法
- method.invoke(obj, val);
- System.out.println(obj);
- }
运行结果:
- 无参构造!!!
- Person{name='null', age=40, sex='M'}
获取指定注解:
- //获取注解
- Annotation annotation = method.getAnnotation(AgeValidator.class);
获取所有注解:
- //获取所有注解
- Annotation[] arr=clazz.getDeclaredAnnotations();
提取 Annotation信息
JDK 的元Annotation
- package com.xfwl.reflect;
- public class UserBean {
- private String uname;
- private String upwd;
- public UserBean(){
- this.setUname("xfwl");
- this.setUpwd("123456");
- }
- public UserBean(String uname,String upwd){
- this.setUname(uname);
- this.setUpwd(uname);
- }
- public void logIn(UserBean user){
- System.out.println("用户登录:uname="+this.getUname()+",upwd="+this.getUpwd());
- }
- public String getUname() {
- return uname;
- }
- private void logOut(UserBean user){
- System.out.println("用户退出:uname="+this.getUname()+",upwd="+this.getUpwd());
- }
- public void setUname(String uname) {
- this.uname = uname;
- }
- public String getUpwd() {
- return upwd;
- }
- public void setUpwd(String upwd) {
- this.upwd = upwd;
- }
- }
测试类:ReflectAction.java
- package com.xfwl.reflect;
- import java.lang.reflect.Method;
- public class ReflectAction {
- /**
- * @param args
- */
- public static void main(String[] args) {
- UserBean jack=null;
- UserBean tom=null;
- Class tomC=null;
- try{
- jack=(UserBean)Class.forName("com.xfwl.reflect.UserBean").newInstance();
- //jack.logIn();
- tomC=Class.forName("com.xfwl.reflect.UserBean");
- tom=(UserBean) tomC.newInstance();
- Method[] methods = tomC.getDeclaredMethods();
- for (Method method : methods){
- if("logOut".equals(method.getName())){
- method=tomC.getDeclaredMethod(method.getName(),UserBean.class);
- System.out.println(method);
- method.invoke(tomC.newInstance(),tom);
- }
- }
- }catch(Exception e){
- }
- }
- }
运行结果:没有执行:logOut()
修改:
- public void logOut(UserBean user){
- System.out.println("用户退出:uname="+this.getUname()+",upwd="+this.getUpwd());
- }
即可执行:logOut()
Java反射学习:深入学习Java反射机制的更多相关文章
- Java学习笔记之使用反射+泛型构建通用DAO
PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完.. 学习内容: 1.如何使用反射+泛型构建通用DAO. 1.使用 ...
- Java学习笔记54(反射详解)
反射概念: java反射机制是在运行状态中,对于任意一个类,都能知道所有属性和方法 对于任意一个对象都能调用它的任意一个方法和属性,这种动态获取和调用的功能称为java的反射机制 实际作用: 已经完成 ...
- Java第三阶段学习(九、类加载器、反射)
一.类加载器 1.类的加载: 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 1.1 加载: 就是指将class文件读入内存,并为之自动 ...
- Java反射:Web学习的灵魂
反射:Web学习的灵魂 我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 -- Class类对 ...
- 【Java语言特性学习之二】反射
一.概念java加载class文件分两种情况:(1)类型是编译器已知的,这种文件的.class文件在编译的时候,编译器会把.class文件打开(不加载)检查,称为Run- Time Type Iden ...
- Java学习笔记--注解和反射
注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...
- Java反射及注解学习- 反射的使用 - JDK动态代理
代理模式基本概念:1.代理模式的作用:为其他对象提供一种以控制对方的访问在某种情况下,一个客户不想或者不能直接引用另一个对象,代理可以在客户端和目标对象之间起到中介的作用代理的角色:(1)抽象角色:声 ...
- Java 基础 类加载器和双亲委派机制 学习笔记
转自博客:https://blog.csdn.net/weixin_38118016/article/details/79579657 文章不是我写的,但是感觉写的挺通俗易懂的,然后防止以后丢失,就转 ...
- 菜鸟学Java(十五)——Java反射机制(二)
上一篇博文<菜鸟学编程(九)——Java反射机制(一)>里面,向大家介绍了什么是Java的反射机制,以及Java的反射机制有什么用.上一篇比较偏重理论,理论的东西给人讲出来总感觉虚无缥缈, ...
- 菜鸟学Java(十四)——Java反射机制(一)
说到反射,相信有过编程经验的人都不会陌生.反射机制让Java变得更加的灵活.反射机制在Java的众多特性中是非常重要的一个.下面就让我们一点一点了解它是怎么一回事. 什么是反射 在运行状态中,对于任意 ...
随机推荐
- int 和 Integer 有什么区别
原文地址:https://blog.csdn.net/chenliguan/article/details/53888018 1 int与Integer的基本使用对比 (1)Integer是int的包 ...
- 中小公司的Java工程师应该如何逆袭冲进BAT?
(1)80% Java工程师都有的迷茫 这篇文章,跟大家聊一聊很多很多很多人问我的一个问题:中小公司的Java工程师应该如何规划准备,才能跳槽进入BAT这类一线互联网公司? 之所以我用了三个 “很多” ...
- videojs集成--播放rtmp流
之前说到已经把流推送过来了,这时候就可以使用videojs来进行显示播放. 首先要先有一个文件,那就是video-js.swf 因为,这种播放方式html已经不能很好的进行播放了,需要用到flash来 ...
- An internal error occurred during: "Map/Reducelocation status updater".java.lang.NullPointerException
当我们运行wordcount代码时,出现报错,如下所示: An internal error occurred during: "Map/Reducelocation status upda ...
- thinkphp模板中for循环与switch的使用
1.for用法 <for start="开始值" end="结束值" comparison="" step="步进值&quo ...
- Oracle 常见hint
Hints 应该慎用,收集相关表的统计信息,根据执行计划,来改变查询方式 只能在SELECT, UPDATE, INSERT, MERGE, or DELETE 关键字后面,只有insert可以用2个 ...
- 转载:Oracle RAC日常基本维护命令
本文转载自: https://blog.csdn.net/tianlesoftware/article/details/5358573 Oracle RAC日常基本维护命令 好文转载, Oracle ...
- php命令执行
php命令执行通过函来执行外部应用程序,函数有shell_exec(),exec(),system(),passthru() <?php $i = $_GET['cmd']; echo exec ...
- js中的class
js中的class 类写法 class SuperClass { constructor(option) { this.a = option; } fn() { console.log(this.b) ...
- 用Dos黑窗口运行Cmd命令
public class BlackWindow { private static BlackWindow _instance; public static BlackWindow Instance ...