• Java 反射


    前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)


    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

    反射就是把java类中的各种成分映射成一个个的Java对象。

    在加载类时,通过.java文件创建一个Class对象,一个类多次加载也只有一个Class对象。


    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括封装数据类型)

    Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

    获取字节码文件对象(Class)的三种方法

    1. 通过 getClass(),object是一个引用变量,指向堆中对象
    2. 通过 类名.class
    3. 通过类的全限定名(即路径,包+"."+类名),调用静态方法Class.forName(String 路径)。需要抛出ClassNotFoundException异常
     1 import javax.security.auth.callback.LanguageCallback;
     2 
     3 public class TestFC {//测试反射机制
     4     public static void main(String[] args) throws ClassNotFoundException {
     5         Object object=new String("1234");//Object是所有类的父类,多态
     6         Class c1=object.getClass();
     7         System.out.println(c1);
     8         object=new Student(520,1314);
     9         c1=object.getClass();
    10         System.out.println(c1);
    11         System.out.println("----------1.通过getClass(),object是一个引用变量,指向堆中对象");
    12         
    13         Class c2=String.class;
    14         System.out.println(c2);
    15         c2=Student.class;
    16         System.out.println(c2);
    17         System.out.println("----------2.通过类名.class");
    18         
    19         Class c3=Class.forName("java.lang.String");//调用静态方法forName()
    20         System.out.println(c3);
    21         c3=Class.forName("my_test.Student");
    22         System.out.println(c3);
    23         System.out.println("----------3.通过类的全限定名。需要抛出ClassNotFoundException异常");
    24         if(c1==c2 && c2==c3 && c1==c3)
    25             System.out.println("Yes");//对象一样,证明获取的是同一个对象
    26     }
    27 }
    28 class Student{
    29     int id;
    30     int age;
    31     public Student(int id,int age) {
    32         this.id=id;
    33         this.age=age;
    34     }
    35     public void say() {
    36         System.out.println("我是学生类的say方法");
    37     }
    38 }

    输出:

    class java.lang.String
    class my_test.Student
    ----------1.通过getClass(),object是一个引用变量,指向堆中对象
    class java.lang.String
    class my_test.Student
    ----------2.通过类名.class
    class java.lang.String
    class my_test.Student
    ----------3.通过类的全限定名。需要抛出ClassNotFoundException异常
    Yes

    创建对象的方式

    1. 直接创建,不用反射
    2. 通过反射,获取构造器,再通过构造器对象调用newInstance()方法创建对象
            Object stu1=new Student(33, 44);//不通过反射直接new出对象
            //通过反射:Class对象的getConstructor方法拿到构造器。
            Constructor constructor=c3.getConstructor(Integer.class,int.class);
            //通过构造器的newInstance方法实例化并初始化变量
            Object stu2=constructor.newInstance(96,85);
            System.out.println(stu1);
            System.out.println(stu2);//要抛出一大堆异常

    输出:

    my_test.Student@15db9742
    my_test.Student@6d06d69c

    通过此方法要抛出一大堆异常还有导入新的类包。添加如下:

    package my_test;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import javax.security.auth.callback.LanguageCallback;
    
    public class TestFC {//测试反射机制
        
        public static void main(String[] args) throws ClassNotFoundException, 
        NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            Object object=new String("1234");//Object是所有类的父类,多态
            Class c1=object.getClass();
            System.out.println(c1);
            object=new Student(520,1314);
            c1=object.getClass();
            System.out.println(c1);
            System.out.println("----------1.通过getClass(),object是一个引用变量,指向堆中对象");
            
            Class c2=String.class;
            System.out.println(c2);
            c2=Student.class;
            System.out.println(c2);
            System.out.println("----------2.通过类名.class");
            
            Class c3=Class.forName("java.lang.String");//调用静态方法forName()
            System.out.println(c3);
            c3=Class.forName("my_test.Student");
            System.out.println(c3);
            System.out.println("----------3.通过类的全限定名。需要抛出ClassNotFoundException异常");
            if(c1==c2 && c2==c3 && c1==c3)
                System.out.println("Yes");//对象一样,证明获取的是同一个对象
            
            Object stu1=new Student(33, 44);//不通过反射直接new出对象
            //通过反射:Class对象的getConstructor方法拿到构造器。
            Constructor constructor=c3.getConstructor(Integer.class,int.class);
            //通过构造器的newInstance方法实例化并初始化变量
            Object stu2=constructor.newInstance(96,85);
            System.out.println(stu1);
            System.out.println(stu2);//要抛出一大堆异常
        }
    }
    class Student{
        Integer id;
        int age;
        public Student(Integer id,int age) {
            this.id=id;
            this.age=age;
        }
        public void say() {
            System.out.println("我是学生类的say方法");
        }
    }
    获取字节码文件对象+实例化

    Class常用方法

    获取公共构造器 getConstructors()
    获取所有构造器 getDeclaredConstructors()
    获取该类对象 newInstance()
    获取类名包含包路径 getName()
    获取类名不包含包路径 getSimpleName()
    获取类公共类型的所有属性 getFields()
    获取类的所有属性 getDeclaredFields()
    获取类公共类型的指定属性 getField(String name)
    获取类全部类型的指定属性 getDeclaredField(String name)
    获取类公共类型的方法 getMethods()
    获取类的所有方法 getDeclaredMethods()
    获得类的特定公共类型方法: getMethod(String name, Class[] parameterTypes)
    获取内部类 getDeclaredClasses()
    获取外部类 getDeclaringClass()
    获取修饰符 getModifiers()
    获取所在包 getPackage()
    获取所实现的接口 getInterfaces()

    参考:

    https://blog.csdn.net/qq_36226453/article/details/82790375

    https://blog.csdn.net/qq_44614710/article/details/86741226

  • 相关阅读:
    解决谷歌高版本没有设置字符编码的选项的问题
    System.nanoTime与System.currentTimeMillis的区别
    jQuery学习笔记(一)
    linux问题
    阿里资源学习
    PHP-Gealman
    php-fpm
    GIT使用
    设置导出的excel数据
    CI框架, 参数验证
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/11688040.html
Copyright © 2020-2023  润新知