Java反射

反射(Reflection)

  • 加载类,并允许以编程的方式解剖类中的各种成分

反射学什么?

1.反射第一步:加载类,获取类的字节码:Class对象
  • 获取Class对象的3种方法:
public class Test1Class {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<Student> c1 = Student.class;
        System.out.println(c1.getName()); //全类名
        System.out.println(c1.getSimpleName()); //简明:Student

        Class<?> c2 = Class.forName("thread.Student");
        System.out.println(c1 == c2);

        Student s = new Student();
        Class c3 = s.getClass();
        System.out.println(c3 == c2);
    }

}
2.获取类的构造器:Constructor对象
  • Class提供了从类中获取构造器的方法
public class Test2Constructor {
    @Test
    public void testGetConstructors(){
        //1.反射第一步:必须先得到这个类的Class对象
        Class<Cat> c = Cat.class;
        //2.获取全部构造器
//        Constructor<?>[] constructors = c.getConstructors();
        Constructor<?>[] constructors = c.getDeclaredConstructors());
        //3.遍历数组中的每个构造器对象
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName() + "--->"
            + constructor.getParameterCount());
        }
    }

    @Test
    public void testGetConstructor() throws NoSuchMethodException {
        //1.反射第一步:必须先得到这个类的Class对象
        Class<Cat> c = Cat.class;
        //2.获取某个构造器:无参构造器
//        Constructor<Cat> constructor = c.getConstructor();
        Constructor<Cat> constructor = c.getDeclaredConstructor();
        System.out.println(constructor.getName() + "--->"
                + constructor.getParameterCount());

        //3.获取有参数构造器
        Constructor<Cat> constructor2 =
                c.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor.getName() + "--->"
                + constructor.getParameterCount());
    }
}
  • 获取类构造器的作用:初始化对象返回 
//无参构造器
        constructor1.setAccessible(true); //禁止检查访问权限
        Cat cat = constructor1.newInstance();
        System.out.println(cat);


//有参构造器
        constructor2.setAccessible(true);
        Cat cat2 = constructor2.newInstance("喜洋洋", 3);
        System.out.println(cat2);

3.获取类的成员变量
public class Test3Field {
    @Test
    public void testGetFields() throws NoSuchFieldException, IllegalAccessException {
        //1.反射第一步:必须是先得到类的Class对象
        Class<Cat> c = Cat.class;
        //2.获取类的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //3.遍历这个成员变量数组
        for (Field field : fields) {
            System.out.println(field.getName() + "--->" + field.getType());
        }

        //4.定位某个成员变量
        Field fName = c.getDeclaredField("name");
        System.out.println(fName.getName() + "--->" + fName.getType());

        Field fAge = c.getDeclaredField("age");
        System.out.println(fAge.getName() + "--->" + fAge.getType());

        //赋值
        Cat cat = new Cat();
        fName.setAccessible(true);
        fName.set(cat,"加菲猫");
        System.out.println(cat);

        //取值
        String name = (String) fName.get(cat);
        System.out.println(name);

    }
}
4.获取类的成员方法:Method对象
  • public class Test3Method {
        @Test
        public void testGetMethods() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
            Class<Cat> c = Cat.class;
            //2.获取全部成员方法
            Method[] methods = c.getDeclaredMethods();
            //3.遍历
            for (Method method : methods) {
                System.out.println(method.getName() + "--->"
                        + method.getParameterCount() + "-->"
                        + method.getReturnType());
            }
            //4.获取某个方法对象
            Method run = c.getDeclaredMethod("run");
            System.out.println(run.getName() + "--->"
                    + run.getParameterCount() + "-->"
                    + run.getReturnType());
    
            Method eat = c.getDeclaredMethod("eat", String.class);
            System.out.println(eat.getName() + "--->"
                    + eat.getParameterCount() + "-->"
                    + eat.getReturnType());
    
    
            Cat cat = new Cat();
            run.setAccessible(true);
            Object rs = run.invoke(cat);//调用无参数的run方法,用cat对象触发调用的
            System.out.println(rs);
    
            eat.setAccessible(true);
            String rs2 = (String) eat.invoke(cat, "鱼儿");
            System.out.println(rs2);
        }
    }
    

反射的作用?

  • 最重要的用途是:适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能

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

需求:

  • 对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去
public class ObjectFrame {
    public static void saveObject(Object obj) throws IllegalAccessException, FileNotFoundException {
        PrintStream ps = new PrintStream(new FileOutputStream("D:\\java\\src\\date.txt", true));
        //obj是任意对象,到底有多少个字段要保存
        Class<?> c = obj.getClass();
        String cName = c.getSimpleName();
        ps.println("-----------" + cName + "-------------");
        //从这个类中提取它的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //遍历
        for (Field field : fields) {
            //拿到变量名字
            String name = field.getName();
            //拿到这个成员变量在对象中的数据
            field.setAccessible(true);
            String value = field.get(obj) + "";
            ps.println(name + "=" + value);
        }
        ps.close();
    }
}
public class Test5Frame {
    @Test
    public void save() throws FileNotFoundException, IllegalAccessException {
        Student s1 = new Student("wyf",35,'男',185,"篮球");
        Teacher t1 = new Teacher("xxx",4000);

        
        ObjectFrame.saveObject(s1);
        ObjectFrame.saveObject(t1);
    }
}

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值