关于反射的一些小验证
关于反射的一些方法
获取Class对象的方式:
- 1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象多用于配置文件,将类名定义在配置文件中.读取文件,加载类
- 2.类名.class:通过类名的属性class获取 多用于参数的传递
- 3.对象.getClass():getClass()方法在Object类中定义着. 多用于对象的获取字节码的方式
注意:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个.
Class对象功能: (获取功能)
- 获取成员变量们
-
Field[] getFields() :获取所有public修饰的成员变量
-
Field[] getDeclaredFields() :获取所有的成员变量,不考虑修饰符
-
Field getField(String name) :获取指定名称的 public修饰的成员变量
-
Field getDeclaredField(String name) :获取指定名称的成员变量(可得private修饰的)
- 获取构造方法们
-
Constructor<?>[] getConstructor() :获取所有public修饰的构造方法
-
Constructor<?>[] getDeclaredConstructor() :获取所有的构造方法
-
Constructor<?> getConstructor(Class<?>...parameterTypes) :获取指定参数类型的public修饰的构造方法
-
Constructor<?> getDeclaredConstructors(Class<?>... parameterTypes) :获取指定参数类型的的构造方法
- 获取成员方法们:
-
Method[] getMethods() :**调用getMethods方法输出的是自身的public方法和父类Object的public方法.**
-
Method[] getDeclaredMethods() :**调用getDeclaredMethods方法输出的是自身的public、protected、private方法**
-
Method getMethod(String name) :获取指定名称的public修饰的成员方法 :
-
Method getMethod(String name, Class<?>... parameterTypes) :
-
Method getDeclaredMethod(String name) :获取指定名称的public、protected、private修饰的成员方法
-
Method getDeclaredMethod(String name, Class<?>... parameterTypes) :
- 获取全类名:
-
String getName()
Field:成员变量
常用操作:
- 设置值 void set(Object obj, Object value)
- 获取值get(Object obj)
- 忽略访问权限修饰符的安全检查 setAccessible(true):暴力反射
Constructor: 构造方法
常用操作:
- 创建对象: T newInstance(Object… initargs)
- 如果使用无参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
Class clazz = Person.class;
Person p = (Person) clazz.newInstance();
Method:方法对象
常用操作:
- 执行方法: Object invoke(Object obj, Object… args)–>如果是私有属性,得先设置method对象的 Method.setAccessible(true)
- 获取方法名称: String getName:获取方法名
操作私有对象前需将该对象.setAccessible为true
代码验证
实体类
// An highlighted block
package demo;
/**
* 人类
*
* @author ming
*
*/
public class Person {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
/**
* 性别
*/
public int gender;
/**
* 钱
*/
public int puMoney = 1000;
/**
* 私钱
*/
private int prMoney = 10;
public Person() {
};
public Person(int age, String name) {
this.age = age;
this.name = name;
}
private Person(int age) {
this.age = age;
}
private Person(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void puSay() {
System.out.println("hello!这里是无参公有方法!");
}
public void puSay(String str) {
System.out.println("hello!" + str + " 这里是带参公有方法!");
}
private void prSay() {
System.out.println("hello!这里是无参私有方法!");
}
private void prSay(String str) {
System.out.println("hello!" + str + " 这里是带参私有有方法!");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", puMoney=" + puMoney + ", prMoney="
+ prMoney + "]";
}
}
;
测试类
// An highlighted block
package demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
/*
*
*获取Class对象的方式:
*
* 1.Class.forName("全类名"):将字节码文件加载进内存,返回Class对象多用于配置文件,将类名定义在配置文件中.读取文件,加载类
* 2.类名.class:通过类名的属性class获取 多用于参数的传递
* 3.对象.getClass():getClass()方法在Object类中定义着. 多用于对象的获取字节码的方式
*注意:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个.
*
*Class对象功能: 获取功能:
* 1. 获取成员变量们
* Field[] getFields() :获取所有public修饰的成员变量
* Field[] getDeclaredFields() :获取所有的成员变量,不考虑修饰符
* Field getField(String name) :获取指定名称的 public修饰的成员变量
* Field getDeclaredField(String name) :获取指定名称的成员变量(可得private修饰的)
* 2. 获取构造方法们
* Constructor<?>[] getConstructors():获取所有public修饰的构造方法
* Constructor<?>[] getDeclaredConstructors():获取所有的构造方法
* Constructor<T> getConstructor(Class<?>... parameterTypes):获取指定参数类型的public修饰的构造方法
* Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):获取指定参数类型的的构造方法
* 3. 获取成员方法们:
* Method[] getMethods() :**调用getMethods方法输出的是自身的public方法和父类Object的public方法.**
* Method[] getDeclaredMethods() :**调用getDeclaredMethods方法输出的是自身的public、protected、private方法**
* Method getMethod(String name) :获取指定名称的public修饰的成员方法 :
* Method getMethod(String name, Class<?>... parameterTypes) :
* Method getDeclaredMethod(String name) :获取指定名称的public、protected、private修饰的成员方法
* Method getDeclaredMethod(String name, Class<?>... parameterTypes) :
* 4. 获取全类名:
* String getName()
*
*Field:成员变量
* 常用操作::
* 1. 设置值 void set(Object obj, Object value)
* 2. 获取值get(Object obj)
* 3. 忽略访问权限修饰符的安全检查 setAccessible(true):暴力反射
*
*Constructor:构造方法
* 常用操作:
* 创建对象: T newInstance(Object... initargs)
* 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
* Person p = (Person) clazz.newInstance();
*
*Method:方法对象
* 常用操作:
* 执行方法: Object invoke(Object obj, Object... args)-->如果是私有属性,得先设置method对象的 Method.setAccessible(true)
* 获取方法名称: String getName:获取方法名
*/
/**
*
* @author ming
*
*/
public class ReflectionTest {
/**
*
* 关于方法对象
*
* Class类对象
*
* 1:调用getMethods方法输出的是自身的public方法和父类Object的public方法.
*
* 2:调用getDeclaredMethods方法输出的是自身的public、protected、private方法.
*
* 3:调用getMethod(String name,Class<?>... parameterTypes)得到的是公共方法对象,
* 传入的是方法名,和参数类型包装类 ...为不定个数[为0,为1,为多都行]
*
* 4:调用getDeclaredMethod(String name,Class<?>... parameterTypes)得到的是私有方法对象,
* 但是要处理的话,得先设置此方法对象的accessable为true-->method对象.setAccessible(true)
*
* Method: 方法对象
*
* 执行私有方法对象得先设置method.setAccessible(true)
*
* 执行方法: Object invoke(Object obj,Object... args) 传入的是类对象,和参数对象
*
* 获取方法名称:String getName()
*
*/
@Test
public void testMethods() {
System.out.println("====testMethods=======================================");
Class clazz = Person.class;
Method[] methods1 = clazz.getMethods();
System.out.println(
"Person中public方法 :toString() getName() setName(String) puSay(String) puSay() getAge() setAge(int)");
System.out.println("Person中private方法:prSay(String) prSay()");
System.out.println("");
System.out.println("getMethods获取到的方法数组:(注意输出的是自身的public方法和父类Object的public方法)");
for (Method m : methods1) {
// System.out.println(m.getName());
System.out.println("方法名:" + m.getName() + " --> " + m.toString());
}
Method[] methods2 = clazz.getDeclaredMethods();
System.out.println("");
System.out.println("getDeclaredFields获取到的方法数组:");
for (Method m : methods2) {
// System.out.println(m.getName());
System.out.println("方法名:" + m.getName() + " --> " + m.toString());
}
System.out.println("");
try {
Person p = (Person) clazz.newInstance();// 调用默认构造方法
// 调用公共方法
Method puSay = clazz.getMethod("puSay");
Method puSays = clazz.getMethod("puSay", String.class);
System.out.println("调用公共无参方法puSay.invoke(p):");
puSay.invoke(p);
System.out.println("");
System.out.println("调用公共有参方法puSays.invoke(p, 'ming'):");
puSays.invoke(p, "ming");
System.out.println("");
// 调用私有方法
Method prSay = clazz.getDeclaredMethod("prSay");
Method prSays = clazz.getDeclaredMethod("prSay", String.class);
prSay.setAccessible(true);// // ☆私有方法运行前得先设置可允许(私有权限)
/**
* 不设置方法对象的setAccessible为true会报 java.lang.IllegalAccessException:
* Class demo.ReflectionTest can not access a member of class
* demo.Person with modifiers "private"
*/
System.out.println("调用私有无参方法puSay.invoke(p):");
prSay.invoke(p);
System.out.println("");
prSays.setAccessible(true);// 获取私有权限
System.out.println("调用私有含参方法prSays.invoke(p, 'ming'):");
prSays.invoke(p, "ming");
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* 关于属性对象
*
* Class类对象
*
* 1:调用getFields方法输出的是自身的public属性.
*
* 2:调用getDeclaredFields方法输出的是自身的public、protected、private属性.
*
* 3:调用getField(String name)得到的是公共属性对象, 传入的是属性名
*
* 4:调用getDeclaredField(String name)得到的是私有属性对象,但是要处理的话,得先设置此方法对象的accessable为true-->puField对象.setAccessible(true)
*
* Filed: 方法对象
*
* 执行私有属性对象方法,得先设置method.setAccessible(true)才能使用方法
*
* 1:设置值 void set(Object obj, Object value)-->obj为类对象
*
* 2:获取值get(Object obj)
*
* 3:获得属性名getName()
*
*
*/
@Test
public void testFields() {
System.out.println("====testFields=======================================");
Class clazz = Person.class;
System.out.println("Class clazz = Person.class;");
System.out.println("clazz.getFields获取到的属性数组:");
Field[] fields1 = clazz.getFields();
for (Field f : fields1) {
System.out.println("属性名:" + f.getName() + " ==> " + f.toString());
}
System.out.println("");
Field[] fields2 = clazz.getDeclaredFields();
System.out.println("clazz.getDeclaredFields获取到的属性数组:");
for (Field f : fields2) {
System.out.println("属性名:" + f.getName() + " ==> " + f.toString());
}
System.out.println("");
try {
Person p = (Person) clazz.newInstance();// 默认构造
Field puField = clazz.getField("puMoney");
puField.get(p);
System.out.println("Field puField = clazz.getField('puMoney')");
System.out.println("puField.get(p) --> " + puField.get(p));
puField.set(p, 5000);
System.out.println("puField.set(p, 5000);后puField.get(p) -->" + puField.get(p));
System.out.println("");
/**
* 不是getDeclaredField获取私有属性会报此错java.lang.NoSuchFieldException:
* prMoney
*/
Field prField = clazz.getDeclaredField("prMoney");
prField.setAccessible(true);
/**
* 不设置属性对象的setAccessible为true会报 java.lang.IllegalAccessException:
* Class demo.ReflectionTest can not access a member of class
* demo.Person with modifiers "private"
*/
System.out.println("Field prField = clazz.getDeclaredField('prMoney')");
System.out.println("设置prField.setAccessible(true)后");
System.out.println("prField.get(p) --> " + prField.get(p));
prField.set(p, 2);
System.out.println("prField.set(p, 2);后prField.get(p) -->" + prField.get(p));
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* 关于构造方法对象
*
* Class类对象
*
* Constructor<?>[] getConstructors():获取所有public修饰的构造方法
*
* Constructor<?>[] getDeclaredConstructors():获取所有的构造方法
*
* Constructor<T> getConstructor(Class<?>... parameterTypes):获取指定参数类型的public修饰的构造方法
*
* Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):获取指定参数类型的的构造方法
*
* 要处理私有对象,得先设置此构造方法对象的accessable为true-->puField对象.setAccessible(true)
*
* Constructor:构造方法
*
* 创建对象: T newInstance(Object... initargs)
*
* 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
*/
@Test
public void testConstructor() {
System.out.println("====testConstructor=======================================");
Class clazz = Person.class;
System.out.println("getConstructors获取到的构造函数数组:");
Constructor[] constructors1 = clazz.getConstructors();
for (Constructor c : constructors1) {
System.out.println(c.toString());
}
Constructor[] constructors2 = clazz.getDeclaredConstructors();
System.out.println("getDeclaredConstructors获取到的构造函数数组:");
for (Constructor f : constructors2) {
System.out.println(f.toString());
}
System.out.println("");
try {
Person p = (Person) clazz.newInstance();// 默认构造
System.out.println("Person p =(Person) clazz.newInstance():");
System.out.println("-->" + p);
System.out.println("");
Constructor constructor0 = clazz.getConstructor(int.class, String.class);// 获取指定参数类型的构造函数
Person p0 = (Person) constructor0.newInstance(18, "moming");
System.out.println("Constructor constructor0 = clazz.getConstructor(int.class, String.class)");
System.out.println("Person p0 = (Person) constructor0.newInstance(18, 'moming')");
System.out.println("-->" + p0);
System.out.println("");
// Constructor constructor2 = clazz.getConstructor(int.class);//
// 获取指定参数类型的构造函数
// Person p2 = (Person) constructor1.newInstance(18);
// System.out.println(p2);
/**
* 如果没用对应参数的public构造方法,获取构造器会报此错java.lang.NoSuchMethodException:
* demo.Person.<init>(int),---->即找不到找不到此方法
*
* Person p1 = (Person) constructor1.newInstance(18, "moming");
* System.out.println(p1);
*/
Constructor constructor1 = clazz.getDeclaredConstructor(int.class, String.class);// 获取指定参数类型的构造函数
Person p1 = (Person) constructor1.newInstance(18, "moming");
System.out.println("Constructor constructor1 = clazz.getDeclaredConstructor(int.class, String.class)");
System.out.println("Person p1 = (Person) constructor1.newInstance(18, 'moming')");
System.out.println("-->" + p1);
System.out.println("");
// Constructor constructor11 =
// clazz.getDeclaredConstructor(int.class,int.class,int.class);//
// 获取指定参数类型的构造函数
// Person p11 = (Person) constructor1.newInstance(18);
// System.out.println(p11);
/**
* 如果没用对应参数的public和private构造方法,获取构造器会报此错java.lang.
* NoSuchMethodException: demo.Person.<init>(int),---->即找不到找不到此方法
*
* Person p1 = (Person) constructor1.newInstance(18, "moming");
* System.out.println(p1);
*/
Constructor constructor3 = clazz.getDeclaredConstructor(int.class);// 获取指定参数类型的构造函数
constructor3.setAccessible(true);
/**
* 构造器对象不设置setAccessible(true);会报此错
* java.lang.IllegalAccessException: Class demo.ReflectionTest can
* not access a member of class demo.Person with modifiers "private"
*/
Person p3 = (Person) constructor3.newInstance(18);
System.out.println("Constructor constructor3 = clazz.getDeclaredConstructor(int.class)");
System.out.println("constructor3.setAccessible(true)");
System.out.println("Person p3 = (Person) constructor3.newInstance(18)");
System.out.println("-->" + p3);
System.out.println("");
Constructor constructor4 = clazz.getDeclaredConstructor(String.class);// 获取指定参数类型的构造函数
constructor4.setAccessible(true);
Person p4 = (Person) constructor4.newInstance("moming");
System.out.println("Constructor constructor4 = clazz.getDeclaredConstructor(String.class)");
System.out.println("constructor4.setAccessible(true);");
System.out.println("Person p4 = (Person) constructor4.newInstance('moming')");
System.out.println("-->" + p4);
System.out.println("");
// Person p5 = (Person) constructor4.newInstance(18, "moming");
// System.out.println(p5);
/**
* 参数对象数量与构造器对象不同时,抛出此异常 java.lang.IllegalArgumentException: wrong
* number of arguments
*/
// Person p5 = (Person) constructor4.newInstance(18);
// System.out.println(p5);
/**
* java.lang.IllegalArgumentException: argument type mismatch
*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果
====testMethods=======================================
Person中public方法 :toString() getName() setName(String) puSay(String) puSay() getAge() setAge(int)
Person中private方法:prSay(String) prSay()
getMethods获取到的方法数组:(注意输出的是自身的public方法和父类Object的public方法)
方法名:toString --> public java.lang.String demo.Person.toString()
方法名:getName --> public java.lang.String demo.Person.getName()
方法名:setName --> public void demo.Person.setName(java.lang.String)
方法名:puSay --> public void demo.Person.puSay(java.lang.String)
方法名:puSay --> public void demo.Person.puSay()
方法名:getAge --> public int demo.Person.getAge()
方法名:setAge --> public void demo.Person.setAge(int)
方法名:wait --> public final void java.lang.Object.wait() throws java.lang.InterruptedException
方法名:wait --> public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
方法名:wait --> public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
方法名:equals --> public boolean java.lang.Object.equals(java.lang.Object)
方法名:hashCode --> public native int java.lang.Object.hashCode()
方法名:getClass --> public final native java.lang.Class java.lang.Object.getClass()
方法名:notify --> public final native void java.lang.Object.notify()
方法名:notifyAll --> public final native void java.lang.Object.notifyAll()
getDeclaredFields获取到的方法数组:
方法名:toString --> public java.lang.String demo.Person.toString()
方法名:getName --> public java.lang.String demo.Person.getName()
方法名:setName --> public void demo.Person.setName(java.lang.String)
方法名:puSay --> public void demo.Person.puSay(java.lang.String)
方法名:puSay --> public void demo.Person.puSay()
方法名:prSay --> private void demo.Person.prSay(java.lang.String)
方法名:prSay --> private void demo.Person.prSay()
方法名:getAge --> public int demo.Person.getAge()
方法名:setAge --> public void demo.Person.setAge(int)
调用公共无参方法puSay.invoke(p):
hello!这里是无参公有方法!
调用公共有参方法puSays.invoke(p, 'ming'):
hello!ming 这里是带参公有方法!
调用私有无参方法puSay.invoke(p):
hello!这里是无参私有方法!
调用私有含参方法prSays.invoke(p, 'ming'):
hello!ming 这里是带参私有有方法!
====testFields=======================================
Class clazz = Person.class;
clazz.getFields获取到的属性数组:
属性名:gender ==> public int demo.Person.gender
属性名:puMoney ==> public int demo.Person.puMoney
clazz.getDeclaredFields获取到的属性数组:
属性名:name ==> private java.lang.String demo.Person.name
属性名:age ==> private int demo.Person.age
属性名:gender ==> public int demo.Person.gender
属性名:puMoney ==> public int demo.Person.puMoney
属性名:prMoney ==> private int demo.Person.prMoney
Field puField = clazz.getField('puMoney')
puField.get(p) --> 1000
puField.set(p, 5000);后puField.get(p) -->5000
Field prField = clazz.getDeclaredField('prMoney')
设置prField.setAccessible(true)后
prField.get(p) --> 10
prField.set(p, 2);后prField.get(p) -->2
====testConstructor=======================================
getConstructors获取到的构造函数数组:
public demo.Person(int,java.lang.String)
public demo.Person()
getDeclaredConstructors获取到的构造函数数组:
private demo.Person(java.lang.String)
private demo.Person(int)
public demo.Person(int,java.lang.String)
public demo.Person()
Person p =(Person) clazz.newInstance():
-->Person [name=null, age=0, gender=0, puMoney=1000, prMoney=10]
Constructor constructor0 = clazz.getConstructor(int.class, String.class)
Person p0 = (Person) constructor0.newInstance(18, 'moming')
-->Person [name=moming, age=18, gender=0, puMoney=1000, prMoney=10]
Constructor constructor1 = clazz.getDeclaredConstructor(int.class, String.class)
Person p1 = (Person) constructor1.newInstance(18, 'moming')
-->Person [name=moming, age=18, gender=0, puMoney=1000, prMoney=10]
Constructor constructor3 = clazz.getDeclaredConstructor(int.class)
constructor3.setAccessible(true)
Person p3 = (Person) constructor3.newInstance(18)
-->Person [name=null, age=18, gender=0, puMoney=1000, prMoney=10]
Constructor constructor4 = clazz.getDeclaredConstructor(String.class)
constructor4.setAccessible(true);
Person p4 = (Person) constructor4.newInstance('moming')
-->Person [name=moming, age=0, gender=0, puMoney=1000, prMoney=10]