反射是java的一种机制,对于任意一个类可以动态获取该类的对象和方法,对于任意一个对象,可以调用对象的属性或者方法。
说白了,就是有一个 Student 类,它有很多方法,对象,属性,构造方法。我在另一个类中想要获取并调用它的方法。必须把这个对象类中的方法,属性,构造方法包装成一个个对象,再根据自己的需要通过反射机制提供的方法【class.forName , getConstructor…】来获取对象类中的属性,方法。。。
package mylove.home.demo;
public class Student{//mylove.home.demo.Student
//成员变量(属性)
public String name;
protected int age;
private String six;
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
Student(String str) {//默认构造方法
System.out.println("默认构造方法"+str);
}
public Student() { //无参构造方法
System.out.println("无参构造函数");
}
//有参构造方法(公有方法)
public Student(char name) {
System.out.println("姓名"+name);
}
public Student(char name,int age) {
System.out.println("姓名"+name+"年龄"+age);
}
//(受保护的)实参构造方法
protected Student(boolean n) {
System.out.println("受保护的构造方法"+ n);
}
//(私有的)实参构造方法
private Student(int age){
System.out.println("我是私有的构造方法"+age);
}
public void show1(String s){
System.out.println("调用了:公有的,String参数的show1(): s = " + s);
}
protected void show2(){
System.out.println("调用了:受保护的,无参的show2()");
}
void show3(){
System.out.println("调用了:默认的,无参的show3()");
}
private String show4(int age){
System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
return "abcd";
}
}
1,获取类class对象的三种方式,如下(反射类):
方法三用的多 class.forName(“对象路径”)
package mylove.home.demo;
/**
* 测试 通过反射获取类对象的三种实现方式
* @author Administrator
*/
public class TestReflect {
public static void main(String[] args) {
Student stu1 = new Student();
//方法一
Class<? extends Student> class1 = stu1.getClass(); //获取类对象
System.out.println("获取类对象 :"+class1.getName());
//方法2
Class<Student> class2 = Student.class;//获取类对象
System.out.println(class1==class2); //true class1与class2 获取的类对象是同一个
//方法3 :一般这种方法使用比较多(.forName)
try {
Class class3 = Class.forName("mylove.home.demo.Student");//获取类对象
System.out.println(class2 == class3); //获取的类对象是同一个
} catch (ClassNotFoundException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
,2,反射获取构造方法
1)通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员
2)获取构造方法
(批量获取)
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
3)(获取单个方法)
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
package mylove.home.demo;
import java.lang.reflect.Constructor;
/**
* 通过反射机制获取类的构造方法
* @author RioNice#XWX
*批量的方法:
* public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
* 2).获取单个的方法,并调用:
* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
*
* 调用构造方法:
* Constructor-->newInstance(Object... initargs)
*/
public class Constructors {
public static void main(String[] args) throws Exception {
//1,加载类对象
Class<?> clazz = Class.forName("mylove.home.demo.Student");
//获取所有公有构造方法
System.out.println("..................所有的公有构造方法");
Constructor<?>[] cs = clazz.getConstructors();
for (Constructor<?> c : cs) {
System.out.println(c);
}
System.out.println("---------获取所有的构造方法(私有,受保护的,公有)");
Constructor<?>[] dc = clazz.getDeclaredConstructors();
for (Constructor<?> cr : dc) {
System.out.println(cr);
}
//System.out.println(dc);
System.out.println("获取公有的 ==========无参的构造方法");
Constructor<?> ct = clazz.getConstructor(null);
System.out.println(ct);
System.out.println("获取私有构造方法,并调用===============");
Constructor<?> con = clazz.getDeclaredConstructor(char.class);
System.out.println(con);
//调用构造方法
// con.setAccessible(true);//暴力服务
// con.newInstance("男");
/*
* 总结:这个类为了练习通过反射机制提供的方法来获取类的构造方法
*
* */
}
}
3,反射获取成员变量
获取成员变量并调用:
1.批量的
1).Field[] getFields():获取所有的"公有字段"
2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
2.获取单个的:
1).public Field getField(String fieldName):获取某个"公有的"字段;
2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
package mylove.home.demo;
import java.lang.reflect.Field;
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/
public class Fields {
public static void main(String[] args) throws Exception {
//1.获取Class对象
Class stuClass = Class.forName("mylove.home.demo.Student");
//2.获取字段
System.out.println("************获取所有公有的字段********************");
Field[] fArray = stuClass.getFields();
//Field[] fieldArray = stuClass.getFields();
for(Field f : fArray){
System.out.println(f);
}
System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
fArray = stuClass.getDeclaredFields();
for(Field f : fArray){
System.out.println(f);
}
System.out.println("*************获取公有字段**并调用***********************************");
Field f = stuClass.getField("name");
System.out.println(f);
//获取一个对象
Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student();
//为字段设置值
f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华"
//验证
Student stu = (Student)obj;
System.out.println("验证姓名:" + stu.name);
System.out.println("**************获取私有字段****并调用********************************");
f = stuClass.getDeclaredField("six");
System.out.println(f);
f.setAccessible(true);//暴力反射,解除私有限定
f.set(obj, "18888889999");
System.out.println("验证电话:" + stu);
}
}
4,反射获取对象方法
获取成员方法并调用:
1.批量的:
public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
2.获取单个的:
public Method getMethod(String name,Class<?>… parameterTypes):
参数:
name : 方法名;
Class … : 形参的Class类型对象
public Method getDeclaredMethod(String name,Class<?>… parameterTypes)
package mylove.home.demo;
import java.lang.reflect.Method;
/*
* 获取成员方法并调用:
*
* 1.批量的:
* public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
* 2.获取单个的:
* public Method getMethod(String name,Class<?>... parameterTypes):
* 参数:
* name : 方法名;
* Class ... : 形参的Class类型对象
* public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
*
* 调用方法:
* Method --> public Object invoke(Object obj,Object... args):
* 参数说明:
* obj : 要调用方法的对象;
* args:调用方式时所传递的实参;
):
*/
public class MethodClass {
public static void main(String[] args) throws Exception {
//1.获取Class对象
Class stuClass = Class.forName("mylove.home.demo.Student");
//2.获取所有公有方法
System.out.println("***************获取所有的”公有“方法*******************");
stuClass.getMethods();
Method[] methodArray = stuClass.getMethods();
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("***************获取所有的方法,包括私有的*******************");
methodArray = stuClass.getDeclaredMethods();
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("***************获取公有的show1()方法*******************");
Method m = stuClass.getMethod("show1", String.class);
System.out.println(m);
//实例化一个Student对象
Object obj = stuClass.getConstructor().newInstance();
m.invoke(obj, "刘德华");
System.out.println("***************获取私有的show4()方法******************");
m = stuClass.getDeclaredMethod("show4", int.class);
System.out.println(m);
m.setAccessible(true);//解除私有限定
Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
System.out.println("返回值:" + result);
}
}