反射-认识反射

一、什么是反射

反射-认识反射_第1张图片

二、如何使用反射

1.第一步:加载类,获取类的字节码(获取类的Class对象)

反射-认识反射_第2张图片

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.获取类的构造器

反射-认识反射_第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 ());

    }
}

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.获取类的成员变量

反射-认识反射_第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.获取类的成员方法,并执行方法

反射-认识反射_第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.反射的作用

反射-认识反射_第6张图片

2.使用反射做一个简易版的框架

反射-认识反射_第7张图片

反射-认识反射_第8张图片

框架类

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 );

    }
}

你可能感兴趣的:(java,开发语言)