反射这门技术在做一些比较通用的工具类的开发的时候,就非常有用了。
反射: 当一个class文件被加载到内存中的时候,那么jvm就会马上对该class文件的成员进行解剖,然后将class文件的成员数据封装到一个Class对象中
,我们如果可以获取到Class对象,那么我们就可以通过该Class对象来操作该类的所有成员。
,我们如果可以获取到Class对象,那么我们就可以通过该Class对象来操作该类的所有成员。
话不多说。直接上代码。
获取Class对象的三种方法
@Test
//获取Class对象的三种方法
public void test1() throws Exception{
//方式一:通过Class.forName获取Class对象。推荐使用.
Class clazz1=Class.forName("com.shyleo.reflect.Person");
System.out.println(clazz1);// class com.shyleo.reflect.Person
//方式二:可以通过类名获取Class对象
Class clazz2=Person.class;
System.out.println(clazz2);// class com.shyleo.reflect.Person
//方式三:可以通过对象获取Class对象
Class clazz3=new Person().getClass();
System.out.println(clazz3);// class com.shyleo.reflect.Person
// clazz1,clazz2,clazz3是同一个对象。因为class文件只会加载一次。而这个对象只在class文件在加载时创建。
System.out.println(clazz1==clazz2);//true
System.out.println(clazz1==clazz3);//true
}
通过Class对象获取构造方法
@Test
//通过Class对象获取构造方法
public void test2() throws Exception{
Class clazz=Class.forName("com.shyleo.reflect.Person");
//Constructor类 是用于表述一个构造方法的
//通过class对象找到所有的构造方法.
/*
Constructor[] constructors=clazz.getConstructors();//只获取了公共的构造方法。
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();//获取一个类 的所有构造方法,包括私有的。
for(Constructor constructor:declaredConstructors){
System.out.println(constructor);
}
*/
//获取单个构造方法
/*
Constructor constructor=clazz.getConstructor(String.class,int.class,String.class);
//System.out.println(constructor);// public com.shyleo.reflect.Person(java.lang.String,int,java.lang.String)
//通过Constructor对象创建对象
Person p= (Person) constructor.newInstance("小明",23,"男");
System.out.println(p);// 姓名:小明 年龄:23 性别:男
*/
//获取私有的构造方法
/*
Constructor constructor=clazz.getDeclaredConstructor(String.class);
//设置构造方法的访问权限(暴力反射);
constructor.setAccessible(true);
Person p=(Person) constructor.newInstance("小李");
System.out.println(p);// 姓名:小李 年龄:0 性别:null
*/
}
通过Class获取,创建对象
@Test
//通过Class对象获取,创建对象
public void test5() throws Exception{
Class clazz=Class.forName("com.shyleo.reflect.Person");
//方式一:这种方式只能获取无参构造方法
/*
Person p=(Person) clazz.newInstance();
System.out.println(p);//姓名:null 年龄:0 性别:null
*/
//方式二:通过Constructor对象创建对象
Constructor constructor=clazz.getConstructor(String.class,int.class,String.class);
//System.out.println(constructor);// public com.shyleo.reflect.Person(java.lang.String,int,java.lang.String)
//constructor的newInstance方法是这样的: public T newInstance(Object... initargs)
Person p= (Person) constructor.newInstance("小明",23,"男");
System.out.println(p);// 姓名:小明 年龄:23 性别:男
}
通过Class对象获取成员函数-----java.lang.reflect.Method类
@Test
//通过Class对象获取成员函数----java.lang.reflect.Method类
public void test3() throws Exception{
Class clazz=Class.forName("com.shyleo.reflect.Person");
//获取所有的方法
/*
//Method[] methods = clazz.getMethods(); // 获取所有公共 的方法,包括继承下来的方法。
//Method[] methods = clazz.getDeclaredMethods(); //获取所有的方法,包括私有的,但是不包括继承下来的方法。
for(Method m : methods){
System.out.println(m);
}
*/
Person p=new Person("小明",23,"男");
//获取单个方法
/*
//第一个参数是方法名, 第二参数是形参列表的数据类型。
Method m=clazz.getMethod("eat", int.class,String[].class);
//执行一个方法
//第一个参数:方法的调用者对象, 第二参数: 方法执行所需要的参数。
m.invoke(p,300,new String[]{"aaa","bbb"});
Method m1=clazz.getMethod("sleep", int.class);//注意:public static void sleep(int hours){
m1.invoke(null, 22); //sleep是静态方法
*/
//私有的方法
Method m = clazz.getDeclaredMethod("study", null);
//设置方法的访问权限是可以访问
m.setAccessible(true);
m.invoke(p, null);
}
通过Class对象获取一个类的成员变量----java.lang.reflect.Field类
@Test
//通过Class对象获取一个类的成员变量----java.lang.reflect.Field类
public void test4() throws Exception{
Class clazz=Class.forName("com.shyleo.reflect.Person");
//获取该类的所有成员变量
/*
Field[] fields=clazz.getDeclaredFields();
for(Field field:fields){
System.out.println(field);
}
*/
Person p=new Person("小明",23,"男");
Field field=clazz.getDeclaredField("sex");
field.setAccessible(true);
field.set(p, "女");//给属性赋值
System.out.println(p);// 姓名:小明 年龄:23 性别:女
//field.get(p)是获取属性值
System.out.println(field.get(p));// 女
}
以上代码使用到的
Person类
package com.shyleo.reflect;
public class Person {
String name;
int age;
private String sex;
public Person(String name,int age,String sex){
this.name=name;
this.age=age;
this.sex=sex;
}
public Person(){
System.out.println("无参构造方法...");
}
private Person(String name){
this.name=name;
}
public void eat(int num,String[] arr){
System.out.println(name+"吃"+num+"斤");
}
public static void sleep(int hours){
System.out.println("睡"+hours+"小时");
}
private void study(){
System.out.println(name+"学习...");
}
@Override
public String toString() {
return "姓名:"+ this.name+" 年龄:"+this.age+" 性别:"+this.sex;
}
}