java核心技术之reflect(一):一个系统学习reflect的Demo(精)
来源:互联网 发布:美橙域名管理地址 编辑:程序博客网 时间:2024/06/06 09:53
为什么写这篇文章
reflect是java的一个关键技术,以前,我也只是零星的知道一些点,也会几下三脚猫的reflect使用,但是没有系统的掌握此知识点。
正好这二天看到CSDN学院中有一个宋红康老师的视频–<<java基础核心技术:Java反射机制(day19-day20)>>,看完之后受益匪浅啊(点个赞),如果你对reflect不熟,强烈建议大家好好的看看。
看完视频后,我花了点时间,也是参考此视频写了一个Demo,相信应该在此Demo中把reflect系统的学习。
reflect的几个关键点
reflect是java的反射机制,功能十分强大。
关键一:包java.lang.reflect
在java的java.lang.reflect包中提供了对该功能的支持。
我可以查看java.lang.reflect包,可以看到下面几个关键的类:
关键二:类java.lang.Class
而reflect的源头是java.lang.Class类,Class类是reflect的总导演,所有java类都继承Object类,在Object类中有getClass()方法,该方法返回一个类型为Class的对象。如代码:
Class c = persion.getClass();//persion为类Persion的一个对象
java.lang.Class类的几个关键方法:
关键三:类Constructor
—–java.lang.reflect.Constructor
访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。如:
c.getDeclaredConstructor(String.class,int.class);c.getDeclaredConstructor(new Class[]{String.class,int.class});
Constructor类的常用方法:
关键四:类Field
—–java.lang.reflect.Field
访问指定的属性,需要根据该属性的名称来访问。如:
c.getDeclaredField("name_field");
Field类的常用方法:
关键五:类Method
—– java.lang.reflect.Method
访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。如:
c.getDeclaredMethod("method_name",String.class,int.class);c.getDeclaredMethod("method_name",new Class[]{String.class,int.class});
Method类的常用方法:
reflect的作用
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类的完整结构
如属性,方法,构造方法,父类等等 - 在运行时调用任意一个类的对象的属性和方法
- 生成动态代理
reflect的详细使用指南
创建对应的Class实例
java.lang.Class 反射的源头,反射涉及到的类都在java.lang.reflect目录下,如Field,Method,ConstructorType等等。
实例化Class的方法(4种方法):
- 调用运行时类的.class属性
c = Persion.class;System.out.println("方法一 : 调用运行时类的.class属性: "+c.toString());
- 通过运行时类的对象,调用getClass()方法
c = persion.getClass();System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c.toString());
- 调用Class的静态方法forName(String className)
c = Class.forName(Persion.class.getName().toString());System.out.println("方法三 : 调用Class的静态方法forName(String className): "+c.toString());
- 通过类的加载器
//ClassLoader classLoader = this.getClass().getClassLoader();ClassLoader classLoader = Persion.class.getClassLoader();c = classLoader.loadClass(className);System.out.println("方法四:通过类的加载器: "+c.toString());
有了Class实例之后,可以做什么?
- 可以创建对应的运行时类的对象
方法一:调用Class的newInstance方法
方法二:调用指定的构造器创建运行时类的对象 - 可以获取对应的运行时类的完整结构
如属性,方法,构造方法,包,父类,接口,内部类等等 - 可以调用对应的运行时类的指定结构
(如指定的属性,方法,构造方法) - 动态代码
反射的应用,体会反射的动态性。
这个Demo如何一一破解reflect的关键点
Demo的几个相关类
在这个Demo中,我们定义一个Creature 类,类中定义了一个public类型的变量weight和private类型的变量color,一个内部类InnerCreature。
package com.java.reflect.demo;public class Creature { public int weight; private int color; @Override public String toString() { return "Creature [weight=" + weight + ", color=" + color + "]"; } public Creature(){ super(); } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } private int getColor() { return color; } private void setColor(int color) { this.color = color; } //内部类 public class InnerCreature{ }}
再定义一个接口ISpeakLister :
package com.java.reflect.demo;public interface ISpeakLister { public void speak(String talk);}
定义一个Person类:
这个类非常简单,其父类是Creature,实现了ISpeakLister和Serializable接口,包括了public类型的,private类型的,static类型的属性,public和private类型的构造方法,public,static和private类型的方法,public和private类型的内部类。
package com.java.reflect.demo;import java.io.Serializable;public class Person extends Creature implements ISpeakLister,Serializable{ private String name; private int age; public int id; public static String weather = "今天天气好晴朗!!"; public Person(){ super(); System.out.println("Person--Person()"); } public Person(String name,int age,int id){ super(); this.name = name; this.age = age; this.id = id; System.out.println("Person--Person(String name,int age,int id)"); } private Person(String name){ super(); this.name = name; } private String getName() { return name; } private void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public static void showWeather(){ System.out.println("weather: "+ weather); } @Override public String toString() { return "Persion [name=" + name + ", age=" + age + ", id=" + id +",weather="+weather+ "]---"+super.toString(); } @Override public void speak(String talk) { // TODO Auto-generated method stub System.out.println("talk: "+ talk); } //inner class public class innerClass { } private class innerPriClass{ }}
reflect的使用
reflect使用,需要对应的Class对象,对应的类的对象,为了方便,我们定义一个变量保存类的类名。
定义Class变量c,Person对象person和类名:
private static Class c;private static Person person = new Person();private static String className = "com.java.reflect.demo.Person";
实例化Class的方法(4种方法)
//实例化Class的方法(4种方法)://java.lang.Class 反射的源头public static void createClass() throws ClassNotFoundException{ System.out.println(" "); System.out.println("createClass()"); //方法一 : 调用运行时类的.class属性 c = Person.class; System.out.println("方法一 : 调用运行时类的.class属性: "+c.toString()); //方法二 : 通过运行时类的对象,调用getClass()方法 c = person.getClass(); System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c.toString()); //方法三 : 调用Class的静态方法forName(String className) c = Class.forName(Person.class.getName().toString()); //c = Class.forName(className); System.out.println("方法三 : 调用Class的静态方法forName(String className): "+c.toString()); //方法四:通过类的加载器// ClassLoader classLoader = this.getClass().getClassLoader(); ClassLoader classLoader = Person.class.getClassLoader(); c = classLoader.loadClass(className); System.out.println("方法四:通过类的加载器: "+c.toString());}
对应的输出信息:
createClass()方法一 : 调用运行时类的.class属性: class com.java.reflect.demo.Person方法二 : 通过运行时类的对象,调用getClass()方法: class com.java.reflect.demo.Person方法三 : 调用Class的静态方法forName(String className): class com.java.reflect.demo.Person方法四:通过类的加载器: class com.java.reflect.demo.Person
创建对应的运行时类的对象
//创建对应的运行时类的对象public static void createInstance(Class c) throws Exception{ //方法一:调用Class的newInstance方法创建运行时类的对象 System.out.println(" "); System.out.println("createInstance()"); person = (Person)c.newInstance(); System.out.println("方法一:调用Class的newInstance方法创建运行时类的对象 --person: "+person); //方法二:调用指定的构造器创建运行时类的对象 //我们指定public类型的构造方法Person(String name,int age,int id)来创建对象 Constructor constructor = c.getDeclaredConstructor(String.class,int.class,int.class); person = (Person) constructor.newInstance("xxx",10,1); System.out.println("方法二:调用指定的构造器(public)创建运行时类的对象 --person: "+person); //我们指定private类型的构造方法Person(String name)来创建对象 constructor = c.getDeclaredConstructor(String.class); constructor.setAccessible(true); person = (Person) constructor.newInstance("****"); System.out.println("方法二:调用指定的构造器(private)创建运行时类的对象 --person: "+person);}
输出信息:
createInstance()Person--Person()方法一:调用Class的newInstance方法创建运行时类的对象 --person: Persion [name=null, age=0, id=0,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]Person--Person(String name,int age,int id)方法二:调用指定的构造器(public)创建运行时类的对象 --person: Persion [name=xxx, age=10, id=1,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]方法二:调用指定的构造器(private)创建运行时类的对象 --person: Persion [name=****, age=0, id=0,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]
输出信息分析:
我们调用Class类的newInstance(),会直接调用Class类的无参构造方法来生成类的对象,也可以调用Class类的getDeclaredConstructor方法来获取Class类的指定构造方法,再调用Constructor类的newInstance方法来生成类的对象。
获取对应的运行时类的完整结构
获取类的构造方法
private static void getConstructs(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("getConstructs"); //getConstructors 此方法为获取类的public的构造方法 System.out.println("getConstructors为获取类的public的构造方法 "); Constructor[] constructors1 = c.getConstructors(); for(int i=0;i<constructors1.length;i++){ System.out.println("constructors ["+i+"] :"+constructors1[i]); } //getDeclaredConstructors为获取类本身自己定义的所有构造方法 System.out.println("getDeclaredConstructors此方法为获取类本身自己定义的所有构造方法 "); Constructor[] constructors2 = c.getDeclaredConstructors(); for(int i=0;i<constructors2.length;i++){ System.out.println("constructors ["+i+"] :"+constructors2[i]); }}
输出信息:
getConstructsgetConstructors 此方法为获取类的public的构造方法 constructors [0] :public com.java.reflect.demo.Person()constructors [1] :public com.java.reflect.demo.Person(java.lang.String,int,int)getDeclaredConstructors 此方法为获取类本身自己定义的所有构造方法 constructors [0] :public com.java.reflect.demo.Person()constructors [1] :private com.java.reflect.demo.Person(java.lang.String)constructors [2] :public com.java.reflect.demo.Person(java.lang.String,int,int)
获取类的方法
//获取类的方法private static void getMethods(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("getMethods"); //getMethods 此方法为获取类的public方法,包括父类的public方法 System.out.println("getMethods 此方法为获取类的public方法,包括父类的public方法 "); Method[] method1 = c.getMethods(); for(int i=0;i<method1.length;i++){ System.out.println("method1 ["+i+"] :"+method1[i]); } //getDeclaredMethods 此方法为获取类本身声明的所有方法,包括private System.out.println(" "); System.out.println("getDeclaredMethods 此方法为获取类本身声明的所有方法,包括private "); Method[] method2 = c.getDeclaredMethods(); for(int i=0;i<method2.length;i++){ System.out.println("method2 ["+i+"] :"+method2[i]); }}
输出信息:
getMethodsgetMethods 此方法为获取类的public方法,包括父类的public方法 method1 [0] :public void com.java.reflect.demo.Person.setAge(int)method1 [1] :public static void com.java.reflect.demo.Person.showWeather()method1 [2] :public int com.java.reflect.demo.Person.getAge()method1 [3] :public void com.java.reflect.demo.Person.setId(int)method1 [4] :public void com.java.reflect.demo.Person.speak(java.lang.String)method1 [5] :public java.lang.String com.java.reflect.demo.Person.toString()method1 [6] :public int com.java.reflect.demo.Person.getId()method1 [7] :public int com.java.reflect.demo.Creature.getWeight()method1 [8] :public void com.java.reflect.demo.Creature.setWeight(int)method1 [9] :public final native java.lang.Class java.lang.Object.getClass()method1 [10] :public native int java.lang.Object.hashCode()method1 [11] :public boolean java.lang.Object.equals(java.lang.Object)method1 [12] :public final native void java.lang.Object.notify()method1 [13] :public final native void java.lang.Object.notifyAll()method1 [14] :public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedExceptionmethod1 [15] :public final void java.lang.Object.wait() throws java.lang.InterruptedExceptionmethod1 [16] :public final native void java.lang.Object.wait(long) throws java.lang.InterruptedExceptiongetDeclaredMethods 此方法为获取类本身声明的所有方法,包括private method2 [0] :public void com.java.reflect.demo.Person.setAge(int)method2 [1] :public static void com.java.reflect.demo.Person.showWeather()method2 [2] :public int com.java.reflect.demo.Person.getAge()method2 [3] :public void com.java.reflect.demo.Person.setId(int)method2 [4] :public void com.java.reflect.demo.Person.speak(java.lang.String)method2 [5] :public java.lang.String com.java.reflect.demo.Person.toString()method2 [6] :private java.lang.String com.java.reflect.demo.Person.getName()method2 [7] :public int com.java.reflect.demo.Person.getId()method2 [8] :private void com.java.reflect.demo.Person.setName(java.lang.String)
获取类的属性
//获取类的属性private static void GetFields(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("GetFields"); //getFields 此方法为获取类的public属性,包括父类的public属性 System.out.println("getFields 此方法为获取类的public属性,包括父类的public属性 "); Field[] field1 = c.getFields(); for(int i=0;i<field1.length;i++){ System.out.println("field1 ["+i+"] :"+field1[i]); } System.out.println(" "); //getDeclaredFields 此方法为获取类的本身声明的所有属性,包括private System.out.println("getDeclaredFields 此方法为获取类的本身声明的所有属性,包括private "); Field[] field2 = c.getDeclaredFields(); for(int i=0;i<field2.length;i++){ System.out.println("field2 ["+i+"] :"+field2[i]); }}
信息输出:
GetFieldsgetFields 此方法为获取类的public属性,包括父类的public属性 field1 [0] :public int com.java.reflect.demo.Person.idfield1 [1] :public static java.lang.String com.java.reflect.demo.Person.weatherfield1 [2] :public int com.java.reflect.demo.Creature.weightgetDeclaredFields 此方法为获取类的本身声明的所有属性,包括private field2 [0] :private java.lang.String com.java.reflect.demo.Person.namefield2 [1] :private int com.java.reflect.demo.Person.agefield2 [2] :public int com.java.reflect.demo.Person.id
获取类的其它信息
如包,父类,接口,内部类等等
//获取类的其它信息,如包,父类,接口,内部类等等private static void getClassOtherInfo(Class c) { // TODO Auto-generated method stub System.out.println(" "); System.out.println("getClassOtherInfo"); //获取类的包 String p = c.getPackage().toString(); System.out.println("类的包名:"+p); //获取类的父类 Class parentClass = c.getSuperclass(); System.out.println("类的父类:"+parentClass.getName()); //获取类的接口 Class[] interfaces =c.getInterfaces(); if(interfaces.length >0){ System.out.println("类的接口:"); for(int i=0;i<interfaces.length;i++){ System.out.println("interfaces["+i+"] :"+interfaces[i]); } } //获取类的内部类 //getDeclaredClasses方法获取类本身定义的所有内部类,包括private Class[] innerClass1 =c.getDeclaredClasses(); if(innerClass1.length >0){ System.out.println("类的所有内部类 ,包括private:"); for(int i=0;i<innerClass1.length;i++){ System.out.println("innerClass1["+i+"] :"+innerClass1[i]); } } //同理getClasses方法获取类的public内部类,包括父类的public内部类 Class[] innerClass2 =c.getClasses(); if(innerClass2.length >0){ System.out.println("类的public内部类,包括父类的public内部类:"); for(int i=0;i<innerClass2.length;i++){ System.out.println("innerClass2["+i+"] :"+innerClass2[i]); } }}
输出信息:
getClassOtherInfo类的包名:package com.java.reflect.demo类的父类:com.java.reflect.demo.Creature类的接口:interfaces[0] :interface com.java.reflect.demo.ISpeakListerinterfaces[1] :interface java.io.Serializable类的所有内部类 ,包括private:innerClass1[0] :class com.java.reflect.demo.Person$innerClassinnerClass1[1] :class com.java.reflect.demo.Person$innerPriClass类的public内部类,包括父类的public内部类:innerClass2[0] :class com.java.reflect.demo.Person$innerClassinnerClass2[1] :class com.java.reflect.demo.Creature$InnerCreature
对类的对象的指定方法,属性,构造方法进行操作
对指定构造方法进行操作
//2.3.1 对指定构造方法进行操作private static void callConstruct(Class c) throws Exception { // TODO Auto-generated method stub System.out.println(" "); System.out.println("callConstruct"); //对private类型的构造方法进行操作 Constructor constructor1 = c.getDeclaredConstructor(String.class); constructor1.setAccessible(true); person = (Person)constructor1.newInstance("zsmj"); System.out.println("person:"+person); //对public类型的构造方法进行操作 Constructor constructor2 = c.getDeclaredConstructor(String.class,int.class,int.class); //constructor2.setAccessible(true); person = (Person)constructor2.newInstance("yyf",10,2); System.out.println("person:"+person);}
输出信息:
callConstructperson:Persion [name=zsmj, age=0, id=0,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]Person--Person(String name,int age,int id)person:Persion [name=yyf, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]
对指定方法进行操作
//2.3.2 对指定方法进行操作private static void callMethod(Class c) throws Exception { // TODO Auto-generated method stub System.out.println(" "); System.out.println("callMethod"); //1.对private类型的方法进行操作 //getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法 System.out.println("getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName方法为例:"); Method m1 = c.getDeclaredMethod("setName", String.class); m1.setAccessible(true); System.out.println("修改前的person:"+person); m1.invoke(person, "yyf_01"); System.out.println("修改后的person:"+person); //2.对public类型的方法进行操作,包括父类的方法 //getMethod 对public类型的方法进行操作,包括父类的方法 //2.1 以运行类的本身声明的public类型的setAge方法为例 System.out.println("getMethod 对public类型的方法进行操作,包括父类的方法,以类本身的setAge方法为例:"); Method m2 = c.getMethod("setAge", int.class); System.out.println("修改前的person:"+person); m2.invoke(person, 11); System.out.println("修改后的person:"+person); //2.2 以运行类的父类声明的public类型的setWeight方法为例 System.out.println("getMethod 对public类型的方法进行操作,包括父类的方法,以父类的setWeight方法为例:"); Method m3 = c.getMethod("setWeight", int.class); System.out.println("修改前的person:"+person); m3.invoke(person, 100); System.out.println("修改后的person:"+person); //3.对static类型的方法进行操作,以类本身的showWeather静态方法为例 System.out.println("getMethod 对public类型的方法进行操作,包括父类的方法,以父类的showWeather方法为例:"); Method m4 = c.getMethod("showWeather"); m4.invoke(null); //4 获取指定方法的返回值,以类本身的private类型的getName方法为例 System.out.println("获取指定方法的返回值,以类本身的private类型的getName方法为例:"); Method m5 = c.getDeclaredMethod("getName"); m5.setAccessible(true); String name = (String)m5.invoke(person); System.out.println("name:"+name);}
输出信息:
callMethodgetDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName方法为例:修改前的person:Persion [name=yyf, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]修改后的person:Persion [name=yyf_01, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]getMethod 对public类型的方法进行操作,包括父类的方法,以类本身的setAge方法为例:修改前的person:Persion [name=yyf_01, age=10, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]修改后的person:Persion [name=yyf_01, age=11, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]getMethod 对public类型的方法进行操作,包括父类的方法,以父类的setWeight方法为例:修改前的person:Persion [name=yyf_01, age=11, id=2,weather=今天天气好晴朗!!]---Creature [weight=0, color=0]修改后的person:Persion [name=yyf_01, age=11, id=2,weather=今天天气好晴朗!!]---Creature [weight=100, color=0]getMethod 对public类型的方法进行操作,包括父类的方法,以父类的showWeather方法为例:weather: 今天天气好晴朗!!获取指定方法的返回值,以类本身的private类型的getName方法为例:name:yyf_01
对指定属性进行操作
//2.3.3 对指定属性进行操作private static void callField(Class c) throws Exception { // TODO Auto-generated method stub System.out.println(" "); System.out.println("callField"); //1.对public类型的属性进行操作,以类本身的public属性id为例: System.out.println("对public类型的属性进行操作,以类本身的public属性id为例"); Field f1 = c.getField("id"); int id = (int)f1.get(person); System.out.println("修改前person对象的id="+id); f1.set(person, 3); id = (int)f1.get(person); System.out.println("修改后person对象的id="+id); //2.对private类型的属性进行操作,以类本身的private属性age为例: System.out.println("对private类型的属性进行操作,以类本身的private属性age为例:"); Field f2 = c.getDeclaredField("age"); f2.setAccessible(true); int age = (int)f2.get(person); System.out.println("修改前person对象的age="+age); f2.set(person, 12); age = (int)f2.get(person); System.out.println("修改后person对象的age="+age); //3.对static类型的属性进行操作,以类本身的static属性weather为例: System.out.println("对static类型的属性进行操作,以类本身的static属性weather为例:"); Field f3 = c.getDeclaredField("weather"); f3.setAccessible(true); String weather = (String)f3.get(person); System.out.println("修改前person对象的weather="+weather); //f3.set(person, "今天天气好凉爽!!"); f3.set(null, "今天天气好凉爽!!"); weather = (String)f3.get(person); System.out.println("修改后person对象的weather="+weather); }
输出信息:
callField对public类型的属性进行操作,以类本身的public属性id为例修改前person对象的id=2修改后person对象的id=3对private类型的属性进行操作,以类本身的private属性age为例:修改前person对象的age=11修改后person对象的age=12对static类型的属性进行操作,以类本身的static属性weather为例:修改前person对象的weather=今天天气好晴朗!!修改后person对象的weather=今天天气好凉爽!!
源码下载地址
http://download.csdn.net/detail/hfreeman2008/9175627
参考资料:
1.Java基础核心技术:Java反射机制(day19-day20)
http://edu.csdn.net/course/detail/809
- java核心技术之reflect(一):一个系统学习reflect的Demo(精)
- demo-java.lang.reflect
- java reflect 学习
- java.lang.reflect学习
- Java的reflect
- java的reflect
- Orm之Reflect(一)
- reflect学习
- java.lang.reflect反射学习
- Java之reflect 反射机制
- java reflect
- java reflect
- java reflect
- Java Reflect
- java .reflect
- Java reflect
- java-reflect
- Reflect-Java
- gdb调试时 Missing separate debuginfos, use: debuginfo-install
- Android 如何让EditText不自动获取焦点
- git的详细介绍
- iPhone 开发常用工具
- POJ 3071 Football(0)
- java核心技术之reflect(一):一个系统学习reflect的Demo(精)
- 安卓开发艺术探索笔记知识点
- viewpage与scrollview共存,viewpager不显示的解决办法
- vs2008快捷键极其技巧 转载
- Linux Pmap 命令:查看进程用了多少内存
- Swift - 简单实现一个tableView
- C++对象模型
- Reactjs 之 mixins
- Hibernate4探索之旅之前言