public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Properties properties=new Properties(); properties.load(new FileInputStream("src/main/resources/res.properties")); String classfullpath = properties.getProperty("classfullpath").toString(); String methodName = properties.getProperty("method").toString(); System.out.println(classfullpath); System.out.println(methodName); //1、加载类 Class cls=Class.forName(classfullpath); //2、得到类的对象实例 Object o = cls.newInstance(); //3、获取方法对象 Method method = cls.getMethod(methodName); //4、方法执行 method.invoke(o); //获取所有public字段 Field[] fields = cls.getFields(); for (Field field:fields){ System.out.println("字段名称:"+field.getName()); System.out.println("字段值:"+field.get(o)); } //获取所有public方法 Method[] methods = cls.getMethods(); for (Method method1:methods){ System.out.println("方法名称:"+method1.getName()); } //构造器 Constructor constructor = cls.getConstructor(); System.out.println(constructor); }
Class也是类,因此也继承Object类
Class类对象不是new出来的,而是系统创建的
对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
每个类的实例都会记得自己是由哪个Class 实例所生成
通过Class可以完整地得到一个类的完整结构,通过一系列API
Class对象是存放在堆的
类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法代码
变量名,方法名,访问权限等等)https://www.zhihu.com/question/384969073
方法名称 | 功能说明 |
---|---|
static Class forName(String name) | 返回指定类名name的Class 对象 |
Object newlnstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类、基本类型等)名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class []getlnterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Field[] getDeclaredFields() | 返回Field对象的一个数组(私有和公有字段) |
Field[] getFields() | 返回Field对象的一个数组(公有字段) |
Method getMethod | 返回一个Method对象,此对象的形参类型为paramType |
Method getMethod(String name,Class … paramTypes) | 返回一个Method对象,此对象的形参类型为paramType |
前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException,实例:
Class cls1 =Class.forName( "java.lang.Cat”)
前提:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高实例: Class cls2 = Cat.class;
应用场景:多用于参数传递,比如通过反射得到对应构造器对象.
前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象,实例:Class clazz =对象.getClass();
应用场景:通过创建好的对象,获取Class对象.
其他方式
ClassLoader cl =对象.getClass(0).getClassLoaderO); Class clazz4 = cl.loadClass(“类的全类名”);
基本数据(int, char,boolean,float,double,byte,long, short)按如下方式得到Class类
Class cls =基本数据类型.class
基本数据类型对应的包装类,可以通过.type得到Class类对象
Class cls =包装类.TYPE Class<Integer> type = Integer.TYPE;
1.外部类,成员内部类,静态内部类,局部内部类,匿名内部类
interface:接口
数组
enum:枚举
annotation:注解
基本数据类型
void
java.lang.reflect.Field
为我们提供了获取当前对象的成员变量的类型,和重新设值的方法。
类中的变量分为两种类型:基本类型和引用类型:
java.lang.reflect.Field
提供了两个方法获去变量的类型:
Field.getType()
Class<?> getType() //返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。 Type getGenericType() //返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
1.***静态加载:***编译时加载相关的类,如果没有则报错,依赖性太强
1.当创建对象时(new) (静态加载)
2.当子类被加载时,父类也被加载 (静态加载)
3.调用类中的静态成员时(静态加载)
4.通过反射(动态加载)
Class.forName("com.test.Cat");
JVM在该阶段的主要目的是将字节码从不同的数据源(可能是 class文件、也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class 对象
1.目的是为了确保Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
2.包括:文件格式验证(是否以魔数oxcafebabe开头)、元数据验证、字节码验证和符号引用验证
3.可以考虑使用**-Xverify:none** 参数来关闭大部分的类验证措施,缩短虚拟机类加载
JVM 会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0、0L、null、false 等)。这些变量所使用的内存都将在方法区中进行分配。
class A{ //1、n1是实例属性,不是静态变量,因为在准备阶段是不会分配内存的 //2、n2是静态变量,在链接初始化阶段,分配内存n2默认初始化是0 //3、n3是final static常量(一旦赋值不会改变),在链接初始化阶段,分配内存n3默认初始化是30 public int n1=10; public static int n2=20; public final static int n3=30; }
虚拟机将常量池内的符号引用替换为直接引用(内存地址)的过程
1.到初始化阶段,才真正开始执行类中定义的 Java程序代码,此阶段是执行()方法的过程。
package org.example.reflection; import java.lang.reflect.Constructor; /** * @author joy * @create 2021-09-16 10:02 * @description */ public class ReflectionObjectDemo { public static void main(String[] args) throws Exception { //1、获取到User类的Class对象 Class classUser=Class.forName("org.example.reflection.User"); //2、通过public的无参构造函数获取对象 Object o = classUser.newInstance(); System.out.println(o); //3、通过public的有参构造函数获取对象 Constructor constructorUser = classUser.getConstructor(String.class); Object user1 = constructorUser.newInstance("yyc"); System.out.println(user1); //4、通过非public的有参构造函数获取对象 Constructor declaredConstructor = classUser.getDeclaredConstructor(int.class, String.class); //值true表示反射对象在使用时应禁止Java语言访问检查。值false表示反射对象应强制执行Java语言访问检查 //爆破,访问私有属性、构造器、方法等 declaredConstructor.setAccessible(true); Object user2 = declaredConstructor.newInstance(12, "yyc"); System.out.println(user2); } } class User{ public int age=1; public String name="xiaoma"; public User(){ } public User(String name){ this.name=name; } private User(int age,String name){ this.age=age; this.name=name; } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
package org.example.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; /** * @author joy * @create 2021-09-16 10:02 * @description */ public class ReflectionObjectDemo { public static void main(String[] args) throws Exception { //1、获取到User类的Class对象 Class classUser = Class.forName("org.example.reflection.User"); //获取对象 Object o = classUser.newInstance(); //获取字段 Field name = classUser.getField("name"); //设置字段值 name.set(o, "xiaozhang"); //获取属性值 Object nameObj = name.get(o); System.out.println(nameObj); System.out.println(o); Field address = classUser.getDeclaredField("address"); address.setAccessible(true); address.set(o,"usa"); } } class User { public int age = 1; public String name = "yyc"; private String address="china"; public User() { } public User(String name) { this.name = name; } private User(int age, String name) { this.age = age; this.name = name; } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + ", address='" + address + '\'' + '}'; } }
1.根据方法名和参数列表获取Method方法对象: Method m =clazz.getDeclaredMethod(方法名,XX.class);//得到本类的所有方法·
2.获取对象:Object o=clazz.newlnstance();
package org.example.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * @author joy * @create 2021-09-16 10:02 * @description */ public class ReflectionObjectDemo { public static void main(String[] args) throws Exception { //1、获取到User类的Class对象 Class classUser = Class.forName("org.example.reflection.User"); //获取对象 Object o = classUser.newInstance(); Method getAddress = classUser.getMethod("getAddress"); Object invokeResult = getAddress.invoke(o); System.out.println(invokeResult); } } class User { public int age = 1; public String name = "yyc"; private String address="china"; public User() { } public User(String name) { this.name = name; } private User(int age, String name) { this.age = age; this.name = name; } public String getAddress(){ return address; } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + ", address='" + address + '\'' + '}'; } }