反射

反射:
反射就是Reflection,java的反射式是指程序在运行期可以拿到一个对象的所有信息。
解决在运行期间,对某个实例一无所知的情况狂下,如何调用其方法
通过Class实例获取的class信息的方法—反射

通过一个class的静态变量获取
Class cls = String.class;

通过实例变量提供的getClass()方法获取
String s = “Hello”;
Class cls = s.getClass();

通过静态方法Class.forName()获取完整类名的方法
Class cls = Class.forName(“java.lang.String”);

instanceof 和 == 的区别:
用instanceof 不但可以匹配当前类型,还可以匹配当前类型的子类。而 == 判断class实例可以精确的判断数据类型,但不能做子类型比较。
通常情况下,我们面向抽象编程的时候,不关心具体的子类型,所以可以使用instanceof 判断数据类型。只有在需要判断一个类型是不是某个class的时候,才使用 == 判断实例。

Integer n = new Integer(123);
boolean b3 = n instanceof Integer; // true
boolean b4 = n instanceof Number; // true
boolean b1 = n.getClass() == Integer.class; // true
boolean b2 = n.getClass() == Number.class; // false

反射的目的是为了获得某个实例的信息。
反射中可以通过Class.newInstance() 创建类实例,但是只能调用public的无参构造方法。带参数的构造方法或者非public的构造方法都无法通过class.newInstance()被调用。

动态加载:
jvm在执行java程序时,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载。
JVM为每个加载的class及interface创建了对应的class实例来保存class和interface的所有信息。

//Class类提供了一下几个方法来访问字段:
Field getField(name):根据字段名获取某个public的field(包括父类)
Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
Field[] getFields():获取所有public的field(包括父类)
Field[] getDeclaredFields():获取当前类的所有field(不包括父类)


//一个Filed对象包含了一个字段的所有信息:
getName():返回字段名称,例如,"name";
getType():返回字段类型,也是一个Class实例,例如,String.class;
getModifiers():返回字段的修饰符,它是一个int,不同的bit表示不同的含义。

通过Filed实例可以读取或设置某个对象的字段,如果存在访问限制,可以首先调用setAccessible(true)来访问非public字段。反射对鞋字段是一种非常规的方法,会破坏对象的封装。
setAccessible(true) 可能会失败,如果JVM运行期存在SecurityManager,那么他有可能被阻止。

//Class实例获取所有Method信息
Method getMethod(name, Class...):获取某个public的Method(包括父类)
Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
Method[] getMethods():获取所有public的Method(包括父类)
Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)


//一个Method对象包含一个方法的所有信息:
getName():返回方法名称,例如:"getScore";
getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。

对Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在那个实例上调用该方法,后面的可变参数就要与方法参数一致,否则将报错。
Method m = String.class.getMethod(“substring”, int.class) ;
String r = (String) m.invoke(s , 6);
如果获得的Method表示一个静态方法,调用静态方法 时,无需指定实例对象,所以invoke方法传入的第一个参数永远为null。
Integer n = (Integer) m.invoke(null, “123456”);

调用构造方法
通过反射来创建新的实例,可以调用Class提供的newInstance() 方法
Person p = Person.class.newInstance() ;
只能调用该类的public无参构造方法,如果构造方法带有参数,或者是非public,则无法直接通过Class.newInstance()来调用
为了调用任意的构造方法,java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。

// 获取构造方法Integer(int):
Constructor cons1 = Integer.class.getConstructor(int.class);
// 调用构造方法:
Integer n1 = (Integer) cons1.newInstance(123);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值