概述
JAVA反射机制
- 1、什么是反射
- 1.1 获取字节码文件的方式
- 2、Class 类
- 2.1、newInstance()
- 3、利用反射分析类的能力
- 3.1、Field
- 3.2、Method
- 4、反射方法的其他使用--通过反射越过泛型检查
1、什么是反射
能够分析类能力的程序称为反射(reflective )。 反射机制可以用来:
(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))
- 在运行时分析类的能力。
- 在运行时查看对象, 例如, 编写一个 toString 方法供所有类使用。
- 实现通用的数组操作代码。
- 利用 Method 对象, 这个对象很像中C++中的函数指针
1.1 获取字节码文件的方式
-
方式一:object类中的getClass方法,
想要用这种方式,必须要明确具体的类,并创建对象。很麻烦 -
方式二:任何数据类型都具备应该静态属性 .class来获取对应的class文件
相对简单,但还是要明确用到类中的静态成员,还是不够扩展 -
方式三: 只要通过给定的字符串名称就能获取该类,更为拓展。用class类中的forName方法完成
2、Class 类
在程序运行期间,Java 运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。 虚拟机利用运行时类型信息选择相应的方法执行。
然而,可以通过专门的 Java 类访问这些信息。保存这些信息的类被称为 Class, 这个名字很容易让人混淆。Object 类中的 getClass( ) 方法将会返回一个 Class 类型的实例。
Employee e;
Class cl = e.getClassO;
如同用一个 Employee 对象表示一个特定的雇员属性一样, 一个 Class 对象将表示一个特
定类的属性。最常用的 Class 方法是 getName。 这个方法将返回类的名字。例如,下面这条语句:
System.out.println(e.getClass().getName() + " " + e.getNameO);
如果 e 是一个雇员,则会打印输出:
Employee Harry Hacker
如果 e 是经理, 则会打印输出:
Manager Harry Hacker
我们还能通过调用静态方法forName来获取类名对应得class对象
这个方法只有在className是类名或者接口名得时候才能执行,否则forName方法将抛出一个checked_exception(已检查异常)。
2.1、newInstance()
我们可以使用newInstance(),动态创建一个类得实例
通过反射创建新的类示例,有两种方式:
一 、Class.newInstance()
String s = "java.util .Random";
Object m = Cl ass.forName (s) .newlnstance();
或者
String s = "java.util .Random";
s.class.newInstance();
1.只能够调用无参的构造函数,即默认的构造函数;
2.要求被调用的构造函数是可见的,也即必须是public类型的;
3.抛出所有由被调用构造函数抛出的异常
二 、Constructor.newInstance()
String s = "java.util .Random";
s.class.getConstructor().newInstance();
1.可以根据传入的参数,调用任意构造构造函数。
2.在特定的情况下,可以调用私有的构造函数。
3、利用反射分析类的能力
在 java.lang.reflect 包中有三个类 Field、 Method 和 Constructor 分别用于描述类的字段(域)、 方法和构造器。 这三个类都有一个叫做 getName 的方法, 用来返回项目的名称。
- Field 类有一个 getType 方法, 用来返回描述域所属类型的 Class 对象。
- Method 和 Constructor 类有能够报告参数类型的方法
- Method 类还有一个可以报告返回类型的方法。这 三个类还有一个叫
做 getModifiers 的方法, 它将返回一个整型数值,用不同的位开关描述 public 和 static 这样的修饰符使用状况 - 还可以利用java.lang.reflect包中的 Modifiei类的静态方法分析
getModifiers 返回的整型数值。例如, 可以使用 Modifier 类中的 isPublic、 isPrivate 或 isFinal判断方法或构造器是否是 public、 private 或 final。 我们需要做的全部工作就是调用 Modifier类的相应方法,并对返回的整型数值进行分析,还可以利用 Modifier.toString方法将修饰符打印出来
3.1、Field
字段属性被对象调用,所有在设置对象属性的时候需要new 对象,
这里用反射的方式去new对象,然后再给字段赋值
Calss clazz= Class.forName("cn.itcats.bean.Person");
Field field = null
//只能获取共有的
field = clazz.getField ("age")
//只获取本类,但包含私有的
field = clazz.getDeclaredField ("age")
// 对私有字段的访问取消权限检查,暴力访问
field.setAccessible(true);
Object obj = clazz.newInstance();
//给age赋值
field.set(obj ,18);
//获取age的值
Object o = field.get(obj);
System.out.println(o) //89
3.2、Method
获取方法:
Calss clazz= Class.forName("cn.itcats.bean.Person");
//获取的都是共有的方法,用数组接收
Method[] methods = clazz.getMethods();
//获取本类中的所有方法,包含私有的
methods = clazz.getDeclaredMethods();
// 遍历数组
for (Method method : methods ){
System.out.println(method );
}
运行方法:
Calss clazz= Class.forName("cn.itcats.bean.Person");
//show = 方法名 ,null 代表是空参数
Method method = clazz.getMethods(“show”, null);
//show = 方法名 ,后面 代表是有参数
Method method = clazz.getMethods(“show”, String.class ,int.class );
Constructor c = clazz.getConstructor(String.Class,int.Class);
Object obj = c.newInstance("小莫",37);
//既需要实体对象,又需要实例参数
method.invoke(obj, null)
4、反射方法的其他使用–通过反射越过泛型检查
泛型用在编译期,编译过后泛型擦除(消失掉),所以是可以通过反射越过泛型检查的
import java.lang.reflect.Method;
import java.util.ArrayList;
/*
* 通过反射越过泛型检查
* 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?
*/
public class Demo {
public static void main(String[] args) throws Exception{
ArrayList<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");
// strList.add(100);
//获取ArrayList的Class对象,反向的调用add()方法,添加数据
Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
//获取add()方法
Method m = listClass.getMethod("add", Object.class);
//调用add()方法
m.invoke(strList, 100);
//遍历集合
for(Object obj : strList){
System.out.println(obj);
}
}
}
控制台输出:
aaa
bbb
100
最后
以上就是风中马里奥为你收集整理的JAVA反射机制1、什么是反射2、Class 类3、利用反射分析类的能力4、反射方法的其他使用–通过反射越过泛型检查的全部内容,希望文章能够帮你解决JAVA反射机制1、什么是反射2、Class 类3、利用反射分析类的能力4、反射方法的其他使用–通过反射越过泛型检查所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复