一、什么是反射
二、如何使用反射
1.第一步:加载类,获取类的字节码(获取类的Class对象)
public class reflectTest {
public static void main(String[] args) throws Exception {
Class c1 = Student.class; //通过类名得到学生类的Class对象
System.out.println ( c1.getName () );//全类名 study.reflect.Student
System.out.println ( c1.getSimpleName () );//简名: Student
Class c2 = Class.forName ( "study.reflect.Student" );//必须填入类的全类名
System.out.println (c1==c2);//true 拿到的是同一个对象
Student s= new Student ();
Class c3 = s.getClass ();
System.out.println (c2==c3);//true
}
}
2.获取类的构造器
import org.junit.Test;
import java.lang.reflect.Constructor;
public class Test2Constructor {
@Test
public void test1(){
//1.反射第一步必须先得到这个类的Class对象
Class c1=Cat.class;
//2.获取类的全部构造器
// Constructor[] constructors = c1.getConstructors ();//只能拿public修饰的构造器
Constructor[] constructors = c1.getDeclaredConstructors ();//获取所有声明的构造器,不管是什么修饰符的
//3.遍历数组中的每个构造器对象
for (Constructor constructor : constructors) {
System.out.println (constructor.getName ()+"--->"+constructor.getParameterCount ());//获得构造器的参数数量
}
}
@Test
public void testGetConstructor() throws Exception {
//1.反射第一步必须先得到这个类的Class对象
Class c=Cat.class;
//2.获取某个构造器:无参构造器
Constructor constructor = c.getConstructor ();//只能拿public修饰的构造器 须填入参数类型
Constructor declaredConstructor = c.getDeclaredConstructor ();//可以拿到所有权限修饰的构造器
System.out.println (constructor.getName ()+"--->"+constructor.getParameterCount ());
System.out.println (declaredConstructor.getName ()+"--->"+declaredConstructor.getParameterCount ());
//3.获取有参数的构造器
Constructor constructor1 = c.getConstructor ( String.class, int.class );
Constructor constructor2 = c.getDeclaredConstructor ( String.class, int.class );
System.out.println (constructor1.getName ()+"--->"+constructor1.getParameterCount ());
System.out.println (constructor2.getName ()+"--->"+constructor2.getParameterCount ());
}
}
3.用构造器可以通过反射初始化对象
import org.junit.Test;
import java.lang.reflect.Constructor;
public class Test2Constructor {
@Test
public void test1(){
//1.反射第一步必须先得到这个类的Class对象
Class c1=Cat.class;
//2.获取类的全部构造器
// Constructor[] constructors = c1.getConstructors ();//只能拿public修饰的构造器
Constructor[] constructors = c1.getDeclaredConstructors ();//获取所有声明的构造器,不管是什么修饰符的
//3.遍历数组中的每个构造器对象
for (Constructor constructor : constructors) {
System.out.println (constructor.getName ()+"--->"+constructor.getParameterCount ());//获得构造器的参数数量
}
}
@Test
public void testGetConstructor() throws Exception {
//1.反射第一步必须先得到这个类的Class对象
Class c=Cat.class;
//2.获取某个构造器:无参构造器
// Constructor constructor = c.getConstructor ();//只能拿public修饰的构造器 须填入参数类型
Constructor declaredConstructor = c.getDeclaredConstructor ();//可以拿到所有权限修饰的构造器
// System.out.println (constructor.getName ()+"--->"+constructor.getParameterCount ());
System.out.println (declaredConstructor.getName ()+"--->"+declaredConstructor.getParameterCount ());
//3.获取有参数的构造器
// Constructor constructor1 = c.getConstructor ( String.class, int.class );
Constructor constructor2 = c.getDeclaredConstructor ( String.class, int.class );
// System.out.println (constructor1.getName ()+"--->"+constructor1.getParameterCount ());
System.out.println (constructor2.getName ()+"--->"+constructor2.getParameterCount ());
declaredConstructor.setAccessible ( true );//禁止检查访问权限
Cat cat = (Cat) declaredConstructor.newInstance ();
System.out.println ( cat );
constructor2.setAccessible ( true );
Cat cat1 = (Cat) constructor2.newInstance ( "咪咪", 2 );
System.out.println ( cat1 );
}
}
4.获取类的成员变量
import org.junit.Test;
import java.lang.reflect.Field;
public class Test3Constructor {
@Test
public void testGetFields() throws Exception {
//1.反射第一步,必须先拿到类的Class对象
Class c1=Cat.class;
//2.获取类的全部成员变量
Field[] fields = c1.getDeclaredFields ();
//3.遍历数组
for (Field field : fields) {
System.out.println ( field.getName ()+"---->"+field.getType () );
}
//4.定位某个成员变量
Field fname = c1.getDeclaredField ( "name" );
System.out.println (fname.getName ()+"--->"+ fname.getType () );
//5.复制
Cat cat=new Cat ();
fname.setAccessible ( true );
fname.set ( cat,"加菲猫" );
System.out.println ( cat );
//6.取值
String name = (String) fname.get ( cat );
System.out.println ( name );
}
}
5.获取类的成员方法,并执行方法
import org.junit.Test;
import java.lang.reflect.Method;
public class TestMethod {
@Test
public void getMehtod() throws Exception {
//1.反射第一步:先得到class对象
Class c=Cat.class;
//2.获取类的全部成员方法
Method[] methods = c.getMethods ();//只能获取public修饰的方法
for (Method method : methods) {
System.out.println ( method.getName ()+"---->"+method.getParameterCount ()+"---->"+method.getReturnType () );
}
System.out.println ("-----------------------------------------");
Method[] declaredMethods = c.getDeclaredMethods ();//获取所有权限的方法
for (Method declaredMethod : declaredMethods) {
System.out.println ( declaredMethod.getName ()+"---->"
+declaredMethod.getParameterCount ()+"---->"+declaredMethod.getReturnType ());//返回返回值类型
}
System.out.println ("-----------------------------------------");
//3.获取某个方法对象
Method run = c.getDeclaredMethod ( "run" );
System.out.println (run.getName ()+"---->"+run.getParameterCount ()+"---->"+run.getReturnType ());//run---->0---->void
Cat cat = new Cat ();
run.setAccessible ( true );
run.invoke (cat);//必须传入触发方法的对象
}
}
三、反射的作用,应用场景
1.反射的作用
2.使用反射做一个简易版的框架
框架类
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class ObjectFrame {
//保存任意对象的字段和其数据保存带文件中
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream (new FileOutputStream ( "\\xuexiaaa\\src\\666.txt" ,true),true );
//obj 是任意对象,到底要有多少个字段要保存?
Class c = obj.getClass ();
String cName = c.getSimpleName ();
ps.println ("--------------------"+c+"----------------------");
//2.从这个类中提取它的全部成员变量
Field[] fields = c.getDeclaredFields ();
//3.遍历每个成员变量
for (Field field : fields) {
//4.拿到成员变量的名字
field.setAccessible ( true );
String name = field.getName ();
//5.拿到这个成员变量在对象中的数据
String value = field.get ( obj )+"";
ps.println (name+"="+value);
}
ps.close ();
}
}
测试类
public class TestFrame {
public static void main(String[] args) throws Exception {
Student s1 = new Student ( "吴彦祖", 18, "男" );
Teacher t1 = new Teacher ( "八八", 99.9 );
//需求把任意对象的字段名和其对应的信息
ObjectFrame.saveObject ( s1 );
ObjectFrame.saveObject ( t1 );
}
}