反射是什么?-reflection

1、反射是什么

Annotaion:

----一个.java文件中只能存在一个public----

反射机制reflection:

  • java是静态语言,正是因为有反射的存在,java可以被视为为动态语言
  • javaScript就是一个动态语言:eg:var x =“var a=3;var b=5,alert(a+b)”;这个x现在就是一个字符串,但是我们可以通过eval(x),让字符串的值“var a=3;var b=5,alert(a+b)”,具体的动起来,执行alert(a+b)这个方法,通俗了说,就是在运行的时候代码可以根据某些条件改变自身结构
  • java的微动态是指如何动起来呢?
    • 游戏运行期间,注入一个外挂进去,就可以通过反射实现,创建运行时类的对象
  • 反射机制允许程序在执行期间借助reflection API取得任何类的内部信息,并能操作任意对象的属性及方法
  • 当一个类被加载之后,在堆内存的方法区中就产生了一个Class类型的对象,这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像一面镜子,透过镜子看到类的结构,所以,我们形象的称之为:反射
  • 不仅 通过反射可以看到某对象所属的类,某个类的成员方法和变量,还可以通过反射,构造任意一个类的对象,获取泛型信息,直接调用任意对象的成员方法和变量,处理注解,生成动态代理等~

2、反射的Api有哪些?

java.lang.Class:代表一个类【重点】

java.lang.reflect.Method:代表类的方法

java.lang.reflect.Field:代表类的成员方法、

java.lang.reflect.Constructor:代表类的构造器

3、如何获取Class对象

获取Class对象的方式有四种,现在有一个对象:Person person = new Person();

  • person.getClass( );
  • person.Class;
  • Class.forName("com.yang.Person")【全限命名】
  • Integer.Type;【如果是基本封装类型,可以直接通过这种方式】

4、哪些类有Class对象

  • class基本对象
  • interface接口
  • 数组 [ ]
  • 枚举类【enum】
  • 基本数据类型
  • annotation注解(自定义注解是通过@interface)
  • void也是一个类型,所以它也可以获得class对象

只要元素类型于维度相同(都是一/二维数组),那么他的Class对象都是一样的

可以使用int a [ ]= new int [10]; int b [ ] = new int [100];然后sout.(a.getclass.hashcode)验证

!!:Class对象,我们只能去获取,不能去创建

当java程序被编译之后,生成class文件字节码,运行的时候会将这个class文件字节码加载到内存中,并且讲这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象

5、类的初始化

类什么时候被初始化?

主动引用:

  • new一个新的对象
  • 调用类的静态成员,静态方法(除了final常量)
  • 使用java.lang.reflect包的方法对类进行反射调用
  • 当new一个子类,如果父类没有被初始化,那么就会优先初始化父类

细节的知识点!

  • 静态方法只会执行一次,也就是在初始化的时候!!!
  • 程序运行过程中,先加载main方法的static块,在加载类中对象的static块

类的被动引用(不会触发类的初始化):

  • 当触发静态域的时候,只有真正声明这个域的类才会被初始化
    • eg:当通过子类访问父类的静态变量,不会导致子类初始化
    • sout(Son.b):这个b是父类的静态变量,会发现,子类的static没有被触发
  • 访问常量池中的常量,不会被初始化
    • eg:子类中:static final int M = 1;sout( Son.M);发现子类合服了都不会被初始化;

双亲委派机制:防止你自定义的类和系统默认名冲突,如果冲突了,你自己的类就跑不起来,默认使用系统默认类

6、通过反射可以获得什么

c.getClass( )//获得包名,类名

c.getSimpleName( )//获得简单的类名

c.getFields()//获得类的字段,公共字段 ----- public

c.getDeclareFields( )//获得类的字段,所有字段-----包括private

c.getDeclareField("name")//获取指定获取类的字段

c.getMethods()//获取类的方法-----公共的

c.getDeclaredMethod()//获取类的方法,所有的-----包括private

c.getMethod("getName",null)//第二个参数即为方法的属性,没有参数则为null

c.getMethod("setName",String.class)//有参数,则为参数的类型

总结:反射可以获取正在运行程序的任意类的内部信息

7、通过反射操作类

01:创建示例

可以创建一个实例(创建一个对象,就和new一个对象一样)

Class c1 = Clas.forName(“com.yang.User”);
User uesr = (User)c1.newInstance();//这个user对象默认调用了User对象中的无参构造器

如果对象没有无参构造上面代码会报错,因为你自己自定义的构造器可能是有参数的,在java中,有参数的构造器会覆盖掉无参数的,如果希望两者同时存在,必须在定义有参构造器之后,在显式的定义一次无参构造

也可以通过反射得到构造器,然后通过构造器创建一个实例

Constructor constructor = c.getDeclaredConstructor(String.Class,int.class,int.class);
User user = (User)constructor.newlnstance("yzh" , 001,18)

02:获取并且调用类方法

通过反射获取方法,那么如何调用这个方法?

User user = (User)c.newInstance;
Method setName = c.getDeclaredMethod("setName",String.class);//通过反射获取到方法
setName.invoke(user,"yzh");//通过invoke给调用set方法,invok是激活的意思
sout.(user.getName);//打印结果

03:获取并且操作类属性

通过反射操作属性的方法和调用方法的操作相同

User user = (User)c.newInstance;
Method setName = c.getDeclaredFiled("name");//通过反射获取到属性
name.setAccessible(true);//由于name属性是私有的不能直接在外部给它赋值的,但是在反射中,
//我们可以手动关闭程序的安全检测,也就是通过setAccessible(true);方法,默认为false
setName.invoke(user,"yzh");//通过invoke给调用set方法,invoke是激活的意思
sout.(user.getName);//打印结果

04:setAccessible安全检测

使用setAccessible可以提高代码效率

证明:

循环调用user.getName()方法,十亿次,判断程序执行时间

执行时间通过:long startTime = System.currentTimeMillis();

运行结果:

所以说,如果实在不可避免,需要使用反射执行方法,并且需要大量重复使用,建议关闭程序安全测试

05:获取泛型信息

使用反射获取泛型信息:

获取参数类型集合使用:method.getGenericParameterType();

获取返回值类型泛型信息:method.getGenericReturnType();

06:获取注解信息

利用反射获取注解的参数:

准备工作:创建一个注解:@Tablekuang(value())

  • 获得Class对象中的所有注解
    • Annotation[] annotation = c.getAnnotation();
  • 获得注解中的value的值
    • Tablekuang tablekuang = (Tablekuang) c.getAnnotation(Tablekuang.class);
    • String value = tablekuang.value();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值