反射知识梳理

简介: 反射知识梳理

笔记


码云上的笔记


https://gitee.com/hufanglei/study/raw/master/%E5%8F%8D%E5%B0%84%E7%AC%94%E8%AE%B0/%E5%8F%8D%E5%B0%84.pdf


腾讯文档上的笔记


https://docs.qq.com/pdf/DWklmY0xUUmh2WUxu


代码:


https://gitee.com/hufanglei/study/tree/master/code/reflect-demo


反射


1.根据包名如何获取包下的类的信息并能调用类的信息?


Q: 原理根据文件夹路径获取路径下的文件。


具体操作:


将包名的.替换成/,得到文件路径


获取文件路径下的类的名称


根据名称+.class得到Class对象


根据该类的Class对象获取类的内部信息,然后调用方法,成员变量等。


2.反射有什么好处,并举例说明


Q: new Object获取对象是静态编译,反射是动态编译。反射提高了程序的扩展性。new对象调用的前提(编译需要)是必须内存有这个对象(.class字节码),反射是根据.class字节码文件生成对象,并调用。才可以调用,反射可以没有这个对象甚至没有class文件,用的时候再根据class文件名去查找class文件强制加载这个对象并调用。比较灵活。


我们封装框架的时候,如tomcat并不知道你写了多少个servlet,但是他可以吧你的servlet在程序启动的时候给调用,为啥呢?因为我们可以根据web.xml或者注解方式把文件的包名,类名等给了tomcat,tomcat启动的时候,扫描这些配置,然后加载到内存中就可以使用了。


我们只要关注注解或web.xml对应的类信息(通常是包名+类名),用反射方式获取的信息就可以了。这就是反射扩展性的一个例子。


3.获取字节码对象的三种方式


 

public static void main(String[] args) throws ClassNotFoundException {
//        test1();
//        test2();
          test3();
    }
    /**
     * 方式3
     * 包名 class
     * 只要通过给定的类的 字符串名称就可获取该类,更为扩展
     * 可是用class类中的方法完成, 该方法就是forName    
     */
    private static void test3() throws ClassNotFoundException {
        Class<?> classz = Class.forName("com.example.reflect.bean.Person");
        System.out.println(classz);
        Class<?> classz2 = Class.forName("com.example.reflect.bean.Person");
        System.out.println(classz2);
        System.out.println(classz == classz2);
    }
    /**
     * 方式2:
     * 类名.class
     * 任何数据类型都具备一个静态的属性,class类来获取其对应的class对象
     * 相对简单,但是还是要明确用到类中的静态成员
     * 还是不够扩展
     */
    private static void test2() {
        Class<?> classz = Person.class;
        System.out.println(classz);
        Class<?> classz2 = Person.class;
        System.out.println(classz2);
        System.out.println(classz==classz2);
    }
    /**
     * 方式1:
     * getClass()
     * Object类中的getClass()方法。
     * 这种方式,必须要明确具体的类并创建对象,麻烦
     */
    private static void test1() {
        Person person = new Person();
        Class<?> classz = person.getClass();
        System.out.println(classz);
        Class<?> classz2 = person.getClass();
        System.out.println(classz2);
        System.out.println(classz == classz2);
    }


4.反射获取实例对象的两种方式


早期: new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存

并创建该字节码文件对象,并接着创建该字节码文件的对应的Person对象。

现在,找寻该名称类文件,并加载进内存,并产生class对象,通过下面产生类的对象


第一种: 通过Class对象的newInstance方法,只能获取无参数的构造函数的实例


第二种:根据Class的属性Construct对象的newIntance(…)方法,获取有参数的构造函数,并实例化


/**
     * 第二种方式: 根据Construcat对象的newInstance方法获取对象
     * 当获取指定名称对应类中的
     *
     * 当获取指定名称对应类中的所体现的对象时,而改对象初始化不适用空参构造该怎么办?
     * 既然是通过指定的构造函数进行对象的初始化
     * 所以应该先获取到该构造函数,通过字节码文件对象即可完成
     * 该方法是: getConstructor(paramterTypes)
     */
    private static void createObect2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        String name = "com.example.reflect.bean.Person";
        Class<?> clazz = Class.forName(name);
        Constructor<?> constructor = clazz.getConstructor( String.class, int.class);
        Person p = (Person) constructor.newInstance("小强",18);
        p.show();
    }
    //第一种方式
    //获取无参的是实例对象
    private static void createObect1() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String name = "com.example.reflect.bean.Person";
        Class<?> clazz = Class.forName(name);
        Object o = clazz.newInstance();
        Person p = (Person) o;
       p.show();
    }


5.获取Class中的字段


Class类获取字段有4个方法:


演示一个获取可以获取私有字段的单个字段的方法:getDeclaredFiled(String name)


private static void getFieldDemo() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> clazz = Class.forName("com.example.reflect.bean.Person");
        Field field = clazz.getDeclaredField("age");
        //对私有字段的访问取消权限检查,暴力访问
        field.setAccessible(true);
        Object object = clazz.newInstance();
        //设置值
        field.set(object, 19);
        Object o = field.get(object);
        System.out.println(o);
    }


6.获取class中的方法


无参的方法的调用


private static void getMethodDemo() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> clazz = Class.forName("com.example.reflect.bean.Person");
        Method[] methods = clazz.getMethods(); //获取的都是公有的方法
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        System.out.println("-----------------------");
        //只拿本类中的包括私有的
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method.getName());
        }
        System.out.println("-----------------------");
        //获取空参数一般方法
        Method method = clazz.getMethod("show", null);
        //Object object = clazz.newInstance();
        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
        Object o = constructor.newInstance("小王", 25);
        method.invoke(o, null);
    }


有参数的方法的调用


private static void getMethodDemo1() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<?> clazz = Class.forName("com.example.reflect.bean.Person");
        //获取空参数一般方法
        Method method = clazz.getMethod("paramMethod", String.class, int.class);
        Object object = clazz.newInstance();
        method.invoke(object, "小强", 23);
    }


7.反射调用类,增强扩展性的例子


public interface PCI {
    void open();
    void close();
}


public class SoundPCI implements PCI {
    @Override
    public void open() {
        System.out.println("SoundP open");
    }
    @Override
    public void close() {
        System.out.println("SoundP close");
    }
}


public class NetCard implements PCI{
    @Override
    public void open() {
        System.out.println("NetCard open");
    }
    @Override
    public void close() {
        System.out.println("NetCard close");
    }
}


public class Mainboard {
    public void run() {
        System.out.println("main board run....");
    }
    public void userPCI(PCI p) {
        if (p != null) {
            p.open();
            p.close();
        }
    }
}


public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
        Mainboard mainboard = new Mainboard();
        mainboard.run();
        // mainboard.userPCI(new SoundPCI());
        //通过反射调用pci
        usePCI(mainboard);
    }
    private static void usePCI(Mainboard mainboard) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
//        File file = new File("pci.properties");
        Properties props = new Properties();
        InputStream in = ReflectTest.class.getClassLoader().getResourceAsStream("pci.properties");
        props.load(in);
        for (int i = 0; i < props.size(); i++) {
            String pciName = props.getProperty("pci" + (i + 1));
            Class clazz = Class.forName(pciName);
            PCI p = (PCI) clazz.newInstance();
            mainboard.userPCI(p);
        }
    }
}



相关文章
|
1月前
|
JavaScript 前端开发 Java
谈一谈Java反射
谈一谈Java反射
26 1
|
4月前
|
安全 Java
打破常规!JAVA反射技术让你“动态”编程
【7月更文挑战第1天】Java反射技术是动态编程的利器,它揭示了类的内部信息,允许运行时操作对象、调用方法和创建实例。动态加载类、调用方法和创建对象是其常见应用场景,但需注意反射带来的性能损失、安全风险和代码可读性下降。在平衡灵活性与效率时谨慎使用。
43 0
|
5月前
|
安全 Java 数据库连接
深入Java核心:反射技术如何让你“操控”一切?
【6月更文挑战第30天】Java反射让程序在运行时能检查和操作类、对象,基于`java.lang.reflect`包,它涉及类加载器和Class对象。反射常用于框架(如Spring、Hibernate)、动态代理、插件化和测试,允许动态加载、配置组件。虽然强大,但也有性能和安全考量。
34 0
|
6月前
|
Java
代码的魔法师:Java反射工厂模式详解
代码的魔法师:Java反射工厂模式详解
63 0
|
XML 安全 Java
教你精通Java语法之第十三章、反射
Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到,那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。1. 反射的意义2. 反射重要的几个类: Class类 、Field类、 Method类、 Constructor类3. 学会合理利用反射,一定要在安全环境下使用。
62 0
|
安全 Java 测试技术
带你深入学习“反射”技术
带你深入学习“反射”技术
142 0
|
缓存 安全 Java
12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路
12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路
112 0
12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路
|
Java API
内省技术
内省技术
116 0
内省技术
|
Java Android开发
Java反射技术详解
Java反射技术详解
3405 3
Java反射技术详解
C#反射与特性(二):探究反射
C#反射与特性(二):探究反射
209 0