java学习笔记--反射

1.反射介绍

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

        在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。 在执行程序(java.exe)时候,将字节码文件读入JVM中--->这个过程叫做类的加载。然后在内存中对应创建一个java.lang.Class对象-->这个对象会被放入字节码信息中,这个Class对象,就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口。 所以:我们可以通过这个对象看到类的结构,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称之为反射。

        这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

        说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。 如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。

        使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)。 反射就是把java类中的各种成分映射成一个个的Java对象。 简而言之:使用Class类将原来的类中的内容(属性、方法、构造器等)转换成各种对象,使用的时候调用Class类中的对象,简洁高效。

动态语言vs静态语言

1、动态语言 是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运 行时代码可以根据某些条件改变自身结构。 主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang
2、静态语言 与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、 C++。
所以Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动 态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。 Java的动态性让编程的时候更加灵活!

2.Class类

        通过Class类,可以得到具体的Class类的对象,,然后获得对象内容,如属性,方法,构造器等。

3.获取字节码信息的4种方式

        方式1:通过getClass()方法获取        Person p = new Person();        Class c1 = p.getClass();

        方式2:通过内置class属性:        Class c2 = Person.class; //c1和c2是一样的,只要加载一次内容都是一样的。

        注意:方式1和方式2  不常用。因为得到字节码信息就是为了得到类中的东西,既然已经有person类了,再通过Class类有点多此一举了。

        方式3:--》用的最多:调用Class类提供的静态方法forName    Class c3 = Class.forName("com.zhaoss.test02.Person");

        方式4:利用类的加载器(了解技能点)      ClassLoader loader = Test.class.getClassLoader();

4.可作为Class类的实例的种类

(1)类:外部类,内部类:Class c1 = Person.class;//Person是一个具体类

(2)接口:Class c2 = Comparable.class;//Comparable是一个接口

(3)注解:Class c3 = Override.class;//@ Override是一个注解

(4)数组:int[] arr1 = {1,2,3};   Class c4 = arr1.getClass();

(5)基本数据类型:Class c6 = int.class;

(6)void:Class c7 = void.class;

5.获取运行时类的完整结构

获取构造器和创建对象

1.getConstructors只能获取当前运行时类的被public修饰的构造器 2.getDeclaredConstructors:获取运行时类的全部修饰符的构造器
3.getConstructor(),获取指定的构造器,空构造器或有参构造器
4.Object o1 = con1.newInstance();有了构造器以后我就可以创建对象

获取属性和对属性进行赋值

1.getFields:获取运行时类和父类中被public修饰的属性
2.getDeclaredFields:获取运行时类中的所有属性
3.获取指定的属性:        Field score = cls.getField("score"); Field sno = cls.getDeclaredField("sno")
4.属性的具体结构:获取修饰符getModifiers()
5.获取属性的名字:getName()
6.给属性赋值:(给属性设置值,必须要有对象) Field sco = cls.getField("score");        Object obj = cls.newInstance();        sco.set(obj,98);//给obj这个对象的score属性设置具体的值,这个值为98

获取方法和调用方法

1.getMethods:获取运行时类的方法还有所有父类中的方法(被public修饰) 2.getDeclaredMethods:获取运行时类中的所有方法: 3.获取指定的方法:getMethod(),  getDeclaredMethod() 4.获取方法的具体结构:修饰符 返回值类型  方法名(参数列表) throws XXXXX{} 5.获取注解:getAnnotations() 6.获取异常:getExceptionTypes() 7.调用方法:invoke()

获取类的接口,所在包、注解

1.获取运行时类的接口:getInterfaces()
2.得到父类的接口:
先得到父类的字节码信息: Class superclass = cls.getSuperclass();
得到接口:    Class[] interfaces1 = superclass.getInterfaces();
3.获取运行时类所在的包:getPackage()
4.获取运行类的注解:getAnnotations()

反射的优缺点

优点:
1.增加程序的灵活性,避免将程序写死到代码里;
2.代码简洁,提高代码的复用率,外部调用方便;
3.对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法。
缺点:
1.性能问题 性能开销:反射涉及动态解析类型,因此无法执行某些Java虚拟机的优化,应该避免在性能敏感功能中使用反射。
2.使用反射会模糊程序内部逻辑。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。
3.安全限制:反射需要在安全管理器下运行时可能不存在的运行时权限。对于必须在受限安全上下文中运行的代码(例如在 Applet 中),这是一个重要的考虑因素。
4.内部暴露:反射允许代码执行在非反射代码中非法的操作,例如访问private字段和方法,因此使用反射可能会导致意想不到的副作用,这可能会导致代码功能失调并可能破坏可移植性。反射代码打破了抽象,因此可能会随着平台的升级而改变行为。

6.关于反射的面试问题

问题1:创建Person的对象,以后用new Person()创建,还是用反射创建?

答:通常情况下new的效率更高,在需要动态生成实例会用到反射。反射在某些场景下是非常有用的,特别是在需要动态地加载类、调用未知类的方法或访问未知类的字段时。但是由于额外的开销,应该谨慎使用反射,避免不必要的性能损失。 反射的部分使用场景  1.Spring通过反射来帮我们实例化对象,并放入到Ioc容器中  2.使用JDBC链接数据库时加载数据库驱动Class.forName()  3.逆向代码 例如反编译  4.利用反射,在泛型为Integer的arryaList集合中存放一个String类型的对象 new 对象和反射的区别 1.new的对象无法访问其中的私有属性,反射出来的可以通过设置setAccessible()方法来省略访问权限符。 2.new必须要知道类名,而反射创建对象不需要知道类型也可以创建

问题2:反射是否破坏了面向对象的封装性?

答:两者之间不矛盾。反射 告诉我们可以调 但是不建议调私有的方法,因为可能公共的方法更好 ,加了一些逻辑 。 封装性解决的问题是, 建议 调那个的问题 ,公共的调就可以了, 私有的不要掉了,就私有的属性不建议你直接修改 ,建议你通过get set方法修改。 反射解决的是能不能调的问题。 所以两者不矛盾。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值