没有合适的资源?快使用搜索试试~ 我知道了~
未经允许禁止转载,转载请联系作者。 目录 一 反射(Reflect)初识 二 反射的基本使用和常用API 2.1 基本使用 2.2 反射获取一个对象的步骤 2.3 反射常用API 2.3.1 获取反射中的Class对象 2.3.2 通过反射创建类对象 2.3.3 通过反射获取类属性、方法、构造器(初步) 三 反射小结 3.1 小结 3.2 反射中类加载器、构造器、Method、Field的进阶操作 3.2.1 对类加载器的操作: 3.2.2 对构造器的操作: 3.2.3 对Method、Field的操作: 3.2.4 对Field的操作: 四 反射进阶之深入剖析 4.1 Java反射机制的起源
资源详情
资源评论
资源推荐
Java反射总结:入门进阶到使用反射总结:入门进阶到使用
未经允许禁止转载,转载请联系作者。
目录目录
一 反射(Reflect)初识
二 反射的基本使用和常用API
2.1 基本使用
2.2 反射获取一个对象的步骤
2.3 反射常用API
2.3.1 获取反射中的Class对象
2.3.2 通过反射创建类对象
2.3.3 通过反射获取类属性、方法、构造器(初步)
三 反射小结
3.1 小结
3.2 反射中类加载器、构造器、Method、Field的进阶操作
3.2.1 对类加载器的操作:
3.2.2 对构造器的操作:
3.2.3 对Method、Field的操作:
3.2.4 对Field的操作:
四 反射进阶之深入剖析
4.1 Java反射机制的起源和入口:Class类
4.1.1 Class类简介
4.1.2 Java中类的加载过程
4.2 反射源码解析
五 反射方法的使用
5.1 通过反射运行配置文件内容
5.2 反射方法的其它使用之—通过反射越过泛型检查
一一 反射(反射(Reflect)初识)初识
反射之中包含了一个「反」字,所以了解反射我们先从「正」开始。一般情况下,我们使用某个类时必定知道它是具体的什么类,然后再直接对这个类进行实例化后操作。
Apple apple = new Apple(); //直接初始化,「正射」
apple.setPrice(3);
反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。这时候,我们使用 JDK 提供的反射 API 进行反射调用。
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
Class clz = Class.forName("com.test.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 3);
上面两段代码的执行结果一样,但思路完全不一样:
第一段代码在未运行时就已经确定了要运行的类:Apple;
第二段代码则是在运行时通过字符串值才得知要运行的类:com.test.reflect.Apple。
这就是反射。
二二 反射的基本使用和常用反射的基本使用和常用API
2.1 基本使用基本使用
public class Apple {
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public static void main(String[] args) throws Exception{
//正常的调用
Apple apple = new Apple();
apple.setPrice(3);
System.out.println("Apple Price:" + apple.getPrice());
//使用反射调用
Class clz = Class.forName("com.test.api.Apple");
Method setPriceMethod = clz.getMethod("setPrice", int.class);
Constructor appleConstructor = clz.getConstructor();
Object appleObj = appleConstructor.newInstance();
setPriceMethod.invoke(appleObj, 3);
Method getPriceMethod = clz.getMethod("getPrice");
System.out.println("Apple Price:" + getPriceMethod.invoke(appleObj));
}
}
从代码中可以看到我们使用反射调用了 setPrice 方法,并传递了 14 的值。之后使用反射调用了 getPrice 方法,输出其价格。上面的代码整个的输出结果是:
Apple Price:3
Apple Price:3
2.2 反射获取一个对象的步骤反射获取一个对象的步骤
通过上面这个简单的例子可以看出,一般情况下我们使用反射获取一个对象的步骤:
1:获取类的 Class 对象实例
Class clz = Class.forName("com.zhenai.api.Apple");
2:根据 Class 对象实例获取 Constructor 对象
Constructor appleConstructor = clz.getConstructor();
3:使用 Constructor 对象的 newInstance 方法获取反射类对象
Object appleObj = appleConstructor.newInstance();
4:而如果要调用某一个方法,则需要经过下面的步骤:
获取方法的 Method 对象:
Method setPriceMethod = clz.getMethod("setPrice", int.class);
利用 invoke 方法调用方法:
setPriceMethod.invoke(appleObj, 14);
2.3 反射常用反射常用API
2.3.1 获取反射中的获取反射中的Class对象对象
在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。
在 Java API 中,获取 Class 类对象有三种方法:
第一种,使用第一种,使用 Class.forName 静态方法。静态方法。当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。
Class clz = Class.forName("java.lang.String");
第二种,使用第二种,使用 .class 方法。方法。
这种方法只适合在编译前就知道操作的 Class。
Class clz = String.class;
第三种,使用类对象的第三种,使用类对象的 getClass() 方法。方法。
String str = new String("Hello");
Class clz = str.getClass();
2.3.2 通过反射创建类对象通过反射创建类对象
通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。
第一种:通过 Class 对象的 newInstance() 方法。
Class clz = Apple.class;
Apple apple = (Apple)clz.newInstance();
第二种:通过 Constructor 对象的 newInstance() 方法
Class clz = Apple.class;
Constructor constructor = clz.getConstructor();
Apple apple = (Apple)constructor.newInstance();
通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始
化。
Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("红富士", 15);
2.3.3 通过反射获取类属性、方法、构造器(初步)通过反射获取类属性、方法、构造器(初步)
我们通过 Class 对象的 getFields() 方法可以获取 Class 类的属性,但无法获取私有属性。
Class clz = Apple.class;
Field[] fields = clz.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
输出结果是:
price
而如果使用 Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性:
Class clz = Apple.class;
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
输出结果是:
name
price
与获取类属性一样,当我们去获取类方法、类构造器时,如果要获取私有方法或私有构造器,则必须使用有 declared 关键字的方法。
三三 反射小结反射小结
3.1 小结小结
反射是什么:反射是什么:
通过上面例子,我们可以大致总结到:反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。通过上面例子,我们可以大致总结到:反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
反射提供了什么功能:反射提供了什么功能:
在运行时构造任意一个类的对象
在运行时获取任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法/属性
反射为什么慢:反射为什么慢:
其实反射的效率并不慢,在某些情况下可能达到和直接调用基本相同的效率,但是在首次执行或者没有缓存的情况下还是会有性能上的开销,主要在以下方面
Class.forName()会调用本地方法,我们用到的method和field都会在此时加载进来,虽然会进行缓存,但是本地方法免不了有JAVA到C++在到JAVA得转换开销(详情可见4.2:
MethodAccessor的native版本和java版本)。
class.getMethod(),会遍历该class所有的公用方法,如果没匹配到还会遍历父类的所有方法,并且getMethods()方法会返回结果的一份拷贝,所以该操作不仅消耗CPU还消耗堆内
存,在代码中应该尽量避免,或者进行缓存。
invoke参数是一个object数组,而object数组不支持java基础类型,而自动装箱也是很耗时的。
3.2 反射中类加载器、构造器、反射中类加载器、构造器、Method、、Field的进阶操作的进阶操作
下面举个例子进一步介绍反射中对类加载器、构造器、Method、Field的操作。
首先定义一个自定义对象Person:
public class Person {
String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("this is setName()!");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
System.out.println("this is setAge()!");
}
//包含一个带参的构造器和一个不带参的构造器
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
//私有方法
private void privateMethod(){
System.out.println("this is private method!");
}
}
3.2.1 对类加载器的操作:对类加载器的操作:
public class TestClassLoader {
/*类加载器相关*/
public static void testClassLoader() throws ClassNotFoundException,
FileNotFoundException {
//1. 获取一个系统的类加载器(系统类加载器)(可以获取,当前这个类PeflectTest就是它加载的)
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//2. 获取系统类加载器的父类加载器(扩展类加载器,可以获取).
classLoader = classLoader.getParent();
System.out.println(classLoader);
//3. 获取扩展类加载器的父类加载器(引导类加载器,不可获取).
classLoader = classLoader.getParent();
System.out.println(classLoader);
//4. 测试当前类由哪个类加载器进行加载(系统类加载器):
classLoader = Class.forName("cn.enjoyedu.refle.more.ReflectionTest")
.getClassLoader();
System.out.println(classLoader);
//5. 测试 JDK 提供的 Object 类由哪个类加载器负责加载(引导类)
classLoader = Class.forName("java.lang.Object")
.getClassLoader();
剩余10页未读,继续阅读
weixin_38552239
- 粉丝: 13
- 资源: 955
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0