为什么写这篇文章reflect是java的一个关键技术,以前,我也只是零星的知道一些点,也会几下三脚猫的reflect使用,但是没有系统的掌握此知识点。 正好这二天看到CSDN学院中有一个宋红康老师的视频–<<java基础核心技术:Java反射机制(day19-day20)>>,看完之后受益匪浅啊(点个赞),如果你对reflect不熟,强烈建议大家好好的看看。 看完视频后,我花了点时间,也是参考此视频写了一个Demo,相信应该在此Demo中把reflect系统的学习。 reflect的几个关键点reflect是java的反射机制,功能十分强大。 关键一:包java.lang.reflect在java的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等等。
c = Persion.class;
System.out.println('方法一 : 调用运行时类的.class属性: ' c.toString());
c = persion.getClass();
System.out.println('方法二 : 通过运行时类的对象,调用getClass()方法: ' c.toString());
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实例之后,可以做什么?
这个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类: 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]
输出信息分析: 获取对应的运行时类的完整结构获取类的构造方法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]);
}
}
输出信息: getConstructs
getConstructors 此方法为获取类的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]);
}
}
输出信息: getMethods
getMethods 此方法为获取类的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.InterruptedException
method1 [15] :public final void java.lang.Object.wait() throws java.lang.InterruptedException
method1 [16] :public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
getDeclaredMethods 此方法为获取类本身声明的所有方法,包括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]);
}
}
信息输出: GetFields
getFields 此方法为获取类的public属性,包括父类的public属性
field1 [0] :public int com.java.reflect.demo.Person.id
field1 [1] :public static java.lang.String com.java.reflect.demo.Person.weather
field1 [2] :public int com.java.reflect.demo.Creature.weight
getDeclaredFields 此方法为获取类的本身声明的所有属性,包括private
field2 [0] :private java.lang.String com.java.reflect.demo.Person.name
field2 [1] :private int com.java.reflect.demo.Person.age
field2 [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.ISpeakLister
interfaces[1] :interface java.io.Serializable
类的所有内部类 ,包括private:
innerClass1[0] :class com.java.reflect.demo.Person$innerClass
innerClass1[1] :class com.java.reflect.demo.Person$innerPriClass
类的public内部类,包括父类的public内部类:
innerClass2[0] :class com.java.reflect.demo.Person$innerClass
innerClass2[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);
}
输出信息: callConstruct
person: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);
}
输出信息: callMethod
getDeclaredMethod 方法获取类本身声明的方法,包括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 参考资料: |
|