学会了反射,你就是高手了

前言:

​ 相信不少人都知道反射能够说是Java中最强大的技术了,它能够作的事情太多太多,不少优秀的开源框架都是经过反射完成的,好比最初的不少注解框架,后来由于java反射影响性能,因此被运行时注解APT替代了,java反射有个开源框架jOOR相信不少人都用过,不过咱们仍是要学习反射的基础语法,这样才能本身写出优秀的框架,固然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的!java

概述:

JAVA反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.因此先要获取到每个字节码文件对应的Class类型的对象.数组

以上的总结就是什么是反射
反射就是把java类中的各类成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术能够对一个类进行解剖,把个个组成部分映射成一个个对象。(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
如图是类的正常加载过程:反射的原理在与class对象。
熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之建立一个Class对象。框架

学会了反射,你就是高手了

主要做用

经过反射能够使程序代码访问装载到JVM 中的类的内部信息,获取已装载类的属性信息,获取已装载类的方法,获取已装载类的构造方法信息ide

经常使用方法

(1)建立Student类性能

package cn.tedu.reflection;
//测试 反射
public class Student {
 public String name = "皮皮霞";
 public int age = 22 ;
    //提供构造方法-右键-generate...constructor...
    public Student() {
    }
    public Student(String name) {
        this.name = name;
    }
    public Student(int age) {
        this.age = age;
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
`public void show(){
        System.out.println("show()...");
    }
    public void test(String n){
        System.out.println("test()..."+n);
    }
    //为了能查看属性值,而不是地址值,提供重写的toString()
    //右键-generate...toString()-ok
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

(2)建立测试类学习

package cn.tedu.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
//测试 反射
public class Test1_Reflect {
    public static void main(String[] args) throws Exception {
        //method();//经过反射的技术,获取Class对象
//        method2();//经过反射的技术,获取类中的全部构造方法
//        method3();//经过反射的技术,获取成员方法
//        method4();//经过反射的技术,获取成员变量
        method5();//经过反射的技术,建立实例
    }
    //经过反射的技术,建立实例
    private static void method5() throws Exception {
        //1,获取Class对象
        Class<Student> clazz = Student.class;
        //2,建立实例
        //newInstance()--会触发构造方法--触发无参构造
        Student s = clazz.newInstance();
        //s = Student{name='皮皮霞', age=22}
        System.out.println("s = " + s);

        //3,需求:能够触发含参构造吗?能够-可是你得指定想要触发哪一个含参构造
        // --参数是class对象类型,和含参构造的参数类型匹配
        //public Student(String name){} -- new Student("jack");
        Constructor<Student> c = clazz.getConstructor(String.class);
        Student s2 = c.newInstance("jack");
        //s2 = Student{name='jack', age=22}
        System.out.println("s2 = " + s2);
    }
    //经过反射的技术,获取成员变量
    private static void method4() throws ClassNotFoundException {
        //1,获取Class对象
        Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
        //2,获取成员变量--!!!!只能获取public的!!!!
        Field[] fs = clazz.getFields();
        //3,遍历数组,获取每一个Field
        for (Field f : fs) {
            //获取变量名
            System.out.println( f.getName() );
            //获取变量类型
            System.out.println( f.getType().getName() );
        }
    }
    //经过反射的技术,获取成员方法
    private static void method3() {
        //1,获取Class对象
        Class clazz = Student.class;
        //2,获取成员方法们
        Method[] ms = clazz.getMethods();
        //3,遍历数组,获取每一个Method
        for (Method m : ms) {
            //获取方法名
            System.out.println(m.getName());
            //获取方法参数
            Class<?>[] cs = m.getParameterTypes();
            System.out.println( Arrays.toString(cs) );
        }
    }
    //经过反射的技术,获取类中的构造方法
    private static void method2() {
        //1,获取Class对象
        Class<Student> clazz = Student.class;
        //2,获取构造方法们
        Constructor<?>[] cs = clazz.getConstructors();
        //3,foreach循环获取每一个构造方法
        for (Constructor<?> c : cs) {
            //获取构造方法名
            System.out.println(c.getName());
            //获取构造方法的参数
            Class<?>[] cs2 = c.getParameterTypes();
            System.out.println(Arrays.toString(cs2));
        }
    }
    //经过反射的技术,获取Class对象//三种方式
    private static void method() throws ClassNotFoundException {
//        -- static Class<?> forName(String className)--参数是类的全路径
        Class<?> clazz = Class.forName("java.lang.Object");
//        -- 类名.class
        Class<String> clazz2 = String.class;
//        -- 对象.getClass()--泛型上限,最大是String类型,约束了元素的类型<=String类型
        Class<? extends String> clazz3 = new String().getClass();

        System.out.println("clazz = " + clazz);
        System.out.println("clazz2 = " + clazz2);
        System.out.println("clazz3 = " + clazz3);
    }
}

暴力反射

暴力的获取类中的私有资源顺便获取公开的。
暴力反射和普通反射的反射原理是同样的,都是拿到.class文件中的全部数据并封装成Class对象,经过各类方法来操做数据,只不过是换了一套API测试

反射机制的优缺点

优势:

反射提升了Java程序的灵活性和扩展性,下降耦合性,提升自适应能力。它容许程序建立和控制任何类的对象,无需提早硬编码目标类;反射是其它一些经常使用语言,如C、C++、Fortran 或者Pascal等都不具有的this

缺点:

  • 性能问题:使用反射基本上是一种解释操做,用于字段和方法接入时要远慢于直接代码。所以Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。编码

  • 使用反射会模糊程序内部逻辑:程序人员但愿在源代码中看到程序的逻辑,反射等绕过了源代码的技术,于是会带来维护问题。反射代码比相应的直接代码更复杂。
相关文章
相关标签/搜索