反射的原理,反射创建实例的三种方式是什么方法反射实例
反射的原理:java类的执行需要经历以下的过程
编译:java文件编译后生成.class字节码文件
加载:类加载器负责根据一个类的全限定名俩读取此类的二进制字节流到jvm内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
连接:细分三步
验证:格式(class文件规范)语义(final类是否有子类)操作
准备:静态变量赋初值和内存空间,final修饰的内存空间直接赋原值,此处不是用户指定的初值。
解析:符号引用转化为直接引用,分配地址
初始化:有父类先初始化父类,然后初始化自己;将stati修饰代码执行一遍如果是静态变量,则用用户指定的值覆盖原有的初值;如果是代码块,则执行一遍操作。
java的反射就是利用上面第二步加载到jvm中的.class文件来进行操作的。.class文件中包含java类中的所有信息,当你知道某个类具体信息时,可以使用反射获取class。然后进行各种操作。
java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。总结说:反射就是把java类中的各种成分映射为一个个的java对象,并且可以进行操作。
获取class的三种方式
1.对象调用getClass()方法来获取
2.类名.class的方法获取,该方法最为安全可靠,程序性能更高
3.通过class对象的forName()静态方法来获取,用的最多
// 但可能抛出 ClassNotFoundException 异常
Class c3 = Class.forName(“reflex.Person”);
Class具有的部分方法:
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
Class能实现的功能
1.判断对象属于哪个类
Person person = new Person();
Class class2= person.getClass();
System.out.println("class2:"+class2);
输出:class2:class reflect.Person
2.获取类信息
Class class1 = Person.class;
Method[] methods = class1.getMethods();
Method[] declaredMethods = class1.getDeclaredMethods();
Field[] declaredFields = class1.getDeclaredFields();
3.构建对象
Person person = new Person();
Class class2= person.getClass();
Object o = class2.newInstance();
//强转前先用instanceof判断
if(o instanceof Person){
((Person) o).work();
}
4.动态执行方法
Class class1 = Person.class;
Method work = class1.getDeclaredMethod("work");
Person person = new Person();
work.invoke(person);
5.动态操作属性
Class class1 = Person.class;
Person person = new Person();
Field field = class1.getDeclaredField("age");
//age默认值是18
field.set(person,22);
System.out.println(person.age);
6.动态代理
反射中forName和ClassLoader区别
java中Class.forName和classLoader都可以用来对类进行加载
class.forName(“className”)
其实这种方法调运的是:Class.forName(className,true,ClassLoader.getCallerClassLoader())方法
参数1:classNmae,需要加载类的名称
参数2:true,是否对class进行初始化(需要序列化initialize)
参数3:classLoader,对应的类加载器
ClassLoader.laodClass(“className”)
其实这种方法调用的是:ClassLoader.loadClass(name,false)方法
参数1:name,需要加载的类的名称
参数2: false,这个类加载以后是否需要去连接(不需要linking)
可见Class.forName除了将类的.class文件架子啊到jvm中之外,还会对类进行解释,执行类中的static快、
而ClassLoader只干了一件事情,就是讲.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行stataic