reflect是java的一个关键技术,以前,我也只是零星的知道一些点,也会几下三脚猫的reflect使用,但是没有系统的掌握此知识点。
正好这二天看到CSDN学院中有一个宋红康老师的视频–<<java基础核心技术:Java反射机制(day19-day20)>>,看完之后受益匪浅啊(点个赞),如果你对reflect不熟,强烈建议大家好好的看看。
看完视频后,我花了点时间,也是参考此视频写了一个Demo,相信应该在此Demo中把reflect系统的学习。
reflect是java的反射机制,功能十分强大。
在java的java.lang.reflect包中提供了对该功能的支持。
我可以查看java.lang.reflect包,可以看到下面几个关键的类:
关键类 | 说明 |
---|---|
Constructor-构造类 | This class represents a constructor. |
Field-属性类 | This class represents a field. |
Method-方法类 | This class represents a method. |
Modifier-修饰符类 | This class provides static methods to decode class and member modifiers. |
而reflect的源头是java.lang.Class类,Class类是reflect的总导演,所有java类都继承Object类,在Object类中有getClass()方法,该方法返回一个类型为Class的对象。如代码:
Class c = persion.getClass();//persion为类Persion的一个对象
java.lang.Class类的几个关键方法:
关键方法 | 说明 |
---|---|
getPackage() | 返回包的路径 |
getName() | 返回类的名称 |
getSuperclass() | 返回父类 |
getInterfaces() | 返回其实现的接口 |
getConstructors() | 返回其所有的public构造方法 |
getConstructors(Class… parameterTypes) | 返回其指定参数的public构造方法 |
getDeclaredConstructors() | 返回其所有声明的构造方法,包括private构造方法 |
getDeclaredConstructors(Class… parameterTypes) | 返回其指定参数的构造方法,包括private构造方法 |
getMethods() | 返回其所有的public的方法,包括其父类的public方法 |
getMethod(String name, Class… parameterTypes) | 返回其指定的public的方法 |
getDeclaredFields() | 返回其声明的所有的方法,包括private类型的方法 |
getDeclaredMethod(String name, Class… parameterTypes) | 返回其指定参数的方法,包括private类型的方法 |
getFields() | 返回其所有的public属性,包括其父类的public属性 |
getField(String name) | 返回其指定的public属性,包括其父类的public属性 |
getDeclaredFields() | 返回其声明的所有的属性,包括其private类型的属性 |
getDeclaredField(String name) | 返回其指定的属性,包括其private类型的属性 |
getClasses() | 返回其public的内部类 |
getDeclaredClasses() | 返回其所有的内部类,包括private类型的内部类 |
—–java.lang.reflect.Constructor
访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。如:
c.getDeclaredConstructor(String.class,int.class);
c.getDeclaredConstructor(new Class[]{String.class,int.class});
Constructor类的常用方法:
关键方法 | 说明 |
---|---|
isVarArgs() | 查看该构造方法是否带有可变数量的参数 |
getParameterTypes() | 返回构造方法的参数列表 |
getExceptionTypes() | 返回构造方法的异常列表 |
newInstance(Object… args) | 返回该构造方法创建的类的对象 |
setAccessible(boolean flag) | 让private类型的构造方法可以创建类的对象 |
getModifiers() | 返回构造方法的类型 |
—–java.lang.reflect.Field
访问指定的属性,需要根据该属性的名称来访问。如:
c.getDeclaredField("name_field");
Field类的常用方法:
关键方法 | 说明 |
---|---|
getName() | 返回成员变量的名称 |
getType() | 返回成员变量的类型 |
get(Object object) | 返回指定对象object的成员变量的值 |
set(Object object, Object value) | 给指定对象object的成员变量设置value值 |
setAccessible(boolean flag) | 让private类型的成员变量拥有public权限 |
getModifiers() | 返回成员变量的类型 |
—– java.lang.reflect.Method
访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。如:
c.getDeclaredMethod("method_name",String.class,int.class);
c.getDeclaredMethod("method_name",new Class[]{String.class,int.class});
Method类的常用方法:
关键方法 | 说明 |
---|---|
getName() | 返回该方法的名称 |
getParameterTypes() | 返回方法的参数列表 |
getReturnType() | 返回该方法的返回值类型 |
getExceptionTypes() | 返回方法的异常列表 |
getModifiers() | 返回方法的类型 |
isVarArgs() | 查看该方法是否带有可变数量的参数 |
invoke(Object receiver, Object… args) | 用入口参数来调用指定对象的方法 |
setAccessible(boolean flag) | 让private类型的方法拥有public权限 |
java.lang.Class 反射的源头,反射涉及到的类都在java.lang.reflect目录下,如Field,Method,ConstructorType等等。
实例化Class的方法(4种方法):
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());
在这个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使用,需要对应的Class对象,对应的类的对象,为了方便,我们定义一个变量保存类的类名。
private static Class c;
private static Person person = new Person();
private static String className = "com.java.reflect.demo.Person";
//实例化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]);
}
}
输出信息:
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
参考资料:
1.Java基础核心技术:Java反射机制(day19-day20)
http://edu.csdn.net/course/detail/809
内容来源于网络,如有侵权,请联系作者删除!