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

posted @ 2019-10-16 22:57  守林鸟  阅读(280)  评论(0编辑  收藏  举报