Java 反射
前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
反射就是把java类中的各种成分映射成一个个的Java对象。
在加载类时,通过.java文件创建一个Class对象,一个类多次加载也只有一个Class对象。
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括封装数据类型)
Class
没有公共构造方法。Class
对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass
方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。
获取字节码文件对象(Class)的三种方法
- 通过 getClass(),object是一个引用变量,指向堆中对象
- 通过 类名.class
- 通过类的全限定名(即路径,包+"."+类名),调用静态方法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
创建对象的方式
- 直接创建,不用反射
- 通过反射,获取构造器,再通过构造器对象调用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