java反射三种_java反射

反射

概述

反射库(reflection library) 提供了一个非常丰富且精心设计的工具集, 以便编写能够动 态操纵 Java 代码的程序。这项功能被大量地应用于 JavaBeans 中, 它是 Java组件的体系结构 (有关 JavaBeans 的详细内容在卷 II中阐述)。使用反射, Java 可以支持 Visual Basic 用户习惯 使用的工具。特别是在设计或运行中添加新类时, 能够快速地应用开发工具动态地查询新添 加类的能力。 能够分析类能力的程序称为反射(reflective)。反射机制的功能极其强大,在下面可以看 到, 反射机制可以用来:

•在运行时分析类的能力。

•在运行时查看对象, 例如, 编写一个 toString方法供所有类使用。

•实现通用的数组操作代码。

•利用 Method 对象, 这个对象很像中的函数指针。

Class类

在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。 这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。 然而, 可以通过专门的 Java 类访问这些信息。保存这些信息的类被称为 Class, 这个名 字很容易让人混淆。Object 类中的 getClass( ) 方法将会返回一个 Class 类型的实例。

public static void main(String[] args) throwsClassNotFoundException {//TODO Auto-generated method stub

Hero hero = newHero();

Integer h= new Integer(2);

String s= new String("面对疾风");

String s2= "xueren";//验证三种获取Class 对象的方式

Class class1 = Class.forName("com.yunsi.pojo.Hero");

System.out.println(class1.getName());

System.out.println(s.getClass().getName());

System.out.println(Hero.class.getName());

System.out.println();//一个类中只存在一个Class对象,封装着这个类的所有信息

System.out.println(s.getClass().hashCode());

System.out.println(s2.getClass().hashCode());

System.out.println(h.getClass().hashCode());

}

?

}

?//运行结果如下所示//com.yunsi.pojo.Hero//java.lang.String//com.yunsi.pojo.Hero

?//366712642//366712642//1829164700

获取Class类的三种方式

对象.getClass

Class.forName("String "); //String为某类的报名加类名

类.class

注意

获得 Class类对象的第三种方法非常简单。如果 T 是任意的 Java类型(或 void关键字), T.class 将代表匹配的类对象。例如: Class dl = Random,class; // if you import java.util Gass cl2 = int.class; Class cl3 = Doublet],class; 请注意,一个 Class 对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如, int 不是类,但 int.class 是一个 Class 类型的对象。

注释: Class 类实际上是一个泛型类。例如, Employee.class 的类型是 Class。 没有说明这个问题的原因是: 它将已经抽象的概念更加复杂化了。在大多数实际问题 中, 可以忽略类型参数, 而使用原始的 Class 类。

鉴于历史原 getName 方法在应用于数组类型的时候会返回一个很奇怪的名字:

Double[ ] class.getName( ) 返回“ [Ljava.lang.Double;’’

int[ ].class.getName( ) 返回“ [I”

还有一个很有用的方法 newlnstance( ),他是Object类中的方法, 可以用来动态地创建一个类的实例例如, e.getClass0.newlnstance();创建了一个与 e具有相同类类型的实例。newlnstance方法调用默认的构造器(没有参数的构 造器)初始化新创建的对象。如果这个类没有默认的构造器, 就会抛出一个异常_ 将 forName 与 newlnstance 配合起来使用, 可以根据存储在字符串中的类名创建一个对象

String s = "java.util.Random"; Object m = Class.forName(s).newlnstance();Q 注释:如果需要以这种方式向希望按名称创建的类的构造器提供参数, 就不要使用上面 那条语句, 而必须使用 Constructor 类中的 newlnstance 方法。

利用反射分析类的能力

概述:在java.lang.reflect 包中有三个类 Field、Method 和 Constructor 分别用于描述类的域、 方 法和构造器。

Field

getName() 返回项目的名称

getType(); 返回所描述域所属类型的Class对象

get(Object obj) 查看对象域

getModifiers();

static ( isPublic isPrivate isFinal)

static toString();

Method

getName(); 返回项目的名称

getGenericReturnType() 返回方法的返类型

getModifiers(); 返回整数型,用不同的位开关描述public和static这样的修饰符使用状况,当没有这两个修饰符,则返回值为0

static ( isPublic isPrivate isFinal)

static toString();

Constructor

getName() 返回项目的名称

getModifiers();

static ( isPublic isPrivate isFinal)

static toString();

getParameterTypes() 返回一个用于描述参数类型的Class对象的数组

newInstance(); 实例化构造器(Object中的方法)

Class

getFields();

getDeclaredFields()

getMethods()

getDeclaredMethods()

getConstructors()

getDeclaredConstructors()

注意: Class类中的getxxx 和getDeclaredxxx 的区别在于前者返回提供的public修饰的域,方法和构造器数组,其中包含超类的公有成员;后者返回的是全部域,方法和构造器,其中包括private修饰,但不包括超类的成员

在运行时使用反射分析对象

查看对象域的关键方法是 Field类中的 get 方法。如果 f 是一个 Field类型的对象(例如, 通过 getDeclaredFields 得到的对象),obj 是某个包含 f 域的类的对象,f.get(obj) 将返回一个 对象,其值为 obj 域的当前值。这样说起来显得有点抽象,这里看一看下面这个示例的运行。

Employee harry = new Employee("Harry Hacker", 35000, 10, 1, 1989);

?

Class cl= harry.getClass(); //the class object representing Employee

?

Field f= cl.getDeclaredField("name"): //the name field of the Employee class

?

Object v= f.get(harry); //the value of the name field of the harry object, i.e.,

?

the String object"Harry Hacker"

实际上,这段代码存在一个问题。由于 name 是一个私有域, 所以 get方法将会抛出一个 IllegalAccessException。只有利用 get 方法才能得到可访问域的值。除非拥有访问权限,否则 Java 安全机制只允许査看任意对象有哪些域, 而不允许读取它们的值。 反射机制的默认行为受限于 Java 的访问控制。然而, 如果一个 Java 程序没有受到安全管理器的控制, 就可以覆盖访问控制。 为了达到这个目的, 需要调用 Field、Method 或 Constructor 对象的 setAccessible 方法。例如, f.setAtcessible(true); // now OK to call f.get(harry); setAccessible方法是 AccessibleObject 类中的一个方法, 它是 Field、 Method 和 Constructor 类的公共超类。这个特性是为调试、持久存储和相似机制提供的;当然,可以获得就可以设置。调用 f.set(obj,value) 可以将 obj 对象的 f 域设置成新值。

调用任意方法

在 Method 类中有一个 invoke 方法, 它允许调用包装在当前 Method 对象中 的方法。invoke 方法的签名是: Object invoke(Object obj, Object... args) 第一个参数是隐式参数, 其余的对象提供了显式参数(在 Java SE 5.0 以前的版本中,必须传递一个对象数组, 如果没有显式参数就传递一个 null)。 对于静态方法,第一个参数可以被忽略, 即可以将它设置为 null。

invoke方法的参数,一个是Object类型,也就是调用该方法的对象,第二个参数是一个可变参数类型,调用者是Method的对象

原文:https://www.cnblogs.com/qianshen-bolg/p/13394199.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值