详解Java反射各种应用
|
Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息。通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容:
本文也将从上面几个方面来介绍Java反射。本文涉及的所有代码均在反射代码 首先放出一个Java类作为反射的研究对象,类的内容如下:
public abstract class FatherObject implements Runnable{
public void doSomething(){
System.out.println("做事情......");
}
}
public class ExampleObject extends FatherObject{
public int age = 30;
public String name = "byhieg";
private Integer score = 60;
public void printName(){
System.out.println(name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public ExampleObject(){
}
public ExampleObject(String name){
}
public ExampleObject(int age,Integer score){
}
@Override
public void doSomething() {
super.doSomething();
}
@Override
public void run() {
System.out.println("run......");
}
}
Class对象 我们应用会用到反射这个知识点,肯定是想要在运行时得到类的信息,根据类的那些信息去做一些特定的操作。那么,首先无疑就是得到类的信息,在JDK中提供了Class对象来保存类的信息。所以,反射的第一步就是得到Class对象。在JDK中提供了两种方式得到Class对象。 第一种,如果编写代码的时候,就知道Class的名字,可以直接用如下方式得到Class对象:
第二种,如果在编写代码的时候,不知道类的名字,但是在运行时的时候,可以得到一个类名的字符串,可以用如下的方式获取Class对象:
注意,此方法需要有2个条件,第一,forName中的字符串必须是全限定名,第二,这个Class类必须在classpath的路径下面,因为该方法会抛出ClassNotFoundException的异常。 获取到这个Class对象之后,就可以得到类的各种信息,开头已经提及了一些信息,下面,说几个没提到的类的信息。 得到类的名字 类的名字有两种方式得到,一种是getName(),一种是getSimpleName()。第一种得到的是全限定名,第二种得到的是这个类的名字,不带包名。看下面的例子:Class对象,已经通过上面的代码得到了。 String fullClassName = exampleObjectClass.getName(); String simpleClassName = exampleObjectClass.getSimpleName(); System.out.println(fullClassName); System.out.println(simpleClassName); 结果如下: cn.byhieg.reflectiontutorial.ExampleObject ExampleObject 得到类的包名、父类和实现的接口 类的包名和父类,可以通过如下代码得到。 //得到包信息 Package aPackage = exampleObjectClass.getPackage(); System.out.println(aPackage); //得到父类 Class superClass = exampleObjectClass.getSuperclass(); System.out.println(superClass.getSimpleName()); 结果如下: package cn.byhieg.reflectiontutorial FatherObject 很显然,得到父类的返回值也是一个Class对象,那么可以利用这个对象得到父类的一些信息,比如判断父类是不是抽象类
getModifiers可以得到类的修饰符,从而得到类的修饰符,当然,这个getModifiers不仅仅Class对象可以调用,Method对象可以调用。 可以使用java.lang.reflect.Modifier类中的方法来检查修饰符的类型: Modifier.isAbstract(int modifiers); Modifier.isFinal(int modifiers); Modifier.isInterface(int modifiers); Modifier.isNative(int modifiers); Modifier.isPrivate(int modifiers); Modifier.isProtected(int modifiers); Modifier.isPublic(int modifiers); Modifier.isStatic(int modifiers); Modifier.isStrict(int modifiers); Modifier.isSynchronized(int modifiers); Modifier.isTransient(int modifiers); Modifier.isVolatile(int modifiers); 此外,我们还可以得到父类实现的接口
//得到接口
Class[] classes = superClass.getInterfaces();
System.out.println("父类的接口" + classes[0]);
因为Java类可以实现很多接口,所以用的数组,但在实际使用的时候,需要先判断数组的长度。 下面,重点讲解上述列出来的内容。 构造器 利用Java反射可以得到一个类的构造器,并根据构造器,在运行时动态的创建一个对象。首先,Java通过以下方式获取构造器的实例:
//构造器
Constructor[] constructors = exampleObjectClass.getConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor.toString());
}
结果如下: public cn.byhieg.reflectiontutorial.ExampleObject(int,java.lang.Integer) public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String) public cn.byhieg.reflectiontutorial.ExampleObject() 如果,事先知道要访问的构造方法的参数类型,可以利用如下方法获取指定的构造方法,例子如下: Constructor constructor = exampleObjectClass.getConstructor(String.class); System.out.println(constructor.toString()); 结果显然是:
还可以用如下方式得到另一个构造器 Constructor constructor = exampleObjectClass.getConstructor(int.class,Integer.class); System.out.println(constructor.toString()); 此外,如果我们不知道构造器的参数,只能得到所有的构造器对象,那么可以用如下方式得到每一个构造器对想的参数:
Constructor[] constructors = exampleObjectClass.getConstructors();
for (Constructor constructor : constructors){
Class[] parameterTypes = constructor.getParameterTypes();
System.out.println("构造器参数如下========================");
for (Class clz : parameterTypes){
System.out.println("参数类型 " + clz.toString());
}
}
结果如下: 构造器参数如下======================== 参数类型 class java.lang.String 构造器参数如下======================== 参数类型 int 参数类型 class java.lang.Integer 这里,可以看出无参构造方法,是不打印出结果的。基本类型的Class对象和引用类型的Class对象toString()方法是不一样的。 现在,可以根据构造器的各种信息,动态创建一个对象。 Object object = constructor.newInstance(1,100); System.out.println(object.toString()); 这个创建对象的方式有2个条件,第一是通过有参构造器创建的,第二,构造器对象必须通过传入参数信息的getConstructor得到。 第一个条件,对于无参构造方法就可以创建的对象,不需要得到构造器对象,直接Class对象调用newInstance()方法就直接创建对象。 第二个条件,构造器对象必须通过exampleObjectClass.getConstructor(String.class);这种形式得到。如果通过getConstructors得到构造器数组,然后调用指定的构造器对象去创建对象在JDK1.8是会错的。但是JDK1.6是正常的。 变量 利用Java反射可以在运行时得到一个类的变量信息,并且可以根据上面讲的方式,创建一个对象,设置他的变量值。首先,通过如下方法,得到所有public的变量:
Field[] fields = exampleObjectClass.getFields();
for (Field field : fields){
System.out.println("变量为: " + field.toString());
}
结果如下: 变量为: public int cn.byhieg.reflectiontutorial.ExampleObject.age 变量为: public java.lang.String cn.byhieg.reflectiontutorial.ExampleObject.name 很显然,得到的都是public的变量,上述的private的变量score,并没有得到。 和构造器一样的得到方式一样,我们可以指定一个参数名,然后得到指定的变量:
Field field = exampleObjectClass.getField("age");
System.out.println("变量为:" + field.toString());
上述的变量的toString方法得到的名字太长,Java对Field类提供了getName的方法,返回类中写的变量名字,上面的代码就可以改成field.getName()。 反射不仅提供了得到变量的方法,还提供了设置变量值的方式。通过如下方法可以对一个动态生成的类,改变其变量值:
ExampleObject object = ((ExampleObject) constructor1.newInstance("byhieg"));
System.out.println("原先的age是 " + object.age);
field.set(object,10);
System.out.println("更改之后的age是" + object.age);
结果如下: 原先的age是 30 更改之后的age是10 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java时间日期使用与查询代码详解
- java.lang.NumberFormatException:对于输入字符串:“2011
- java – JMS主题与队列 – 意图
- java – hibernate OneToMany标准返回重复项
- 如何判断一个局部变量是否来自Java字节码的“最终”? (与B
- Spring MVC实现的登录拦截器代码分享
- 仅在Java Filter中更改ContentType或CharacterEncoding如果
- 通过JDK源码学习InputStream详解
- java – 有人可以解释Spring Security BasePermission.Crea
- Lisp是像JVM一样的虚拟机吗?
