Java -- 浅入Java反射机制
1,Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。
Java 反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:代表一个类。
Field 类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor 类:代表类的构造方法。
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
2,通过Class对象获取成员变量、成员方法、接口、超类、构造方法等。
API中给我们提供了一下方法
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
下面就先从是用来说起吧
- 通过对象获取完整的包名和类名
public class TestReflect{
public static void main(String[] args){
TestReflect testReflect = new TestReflect();
System.out.println(testReflect.getClass().getName());
}
}
- 实例化class类对象
package com.qianmo.flowlayout.reflection; import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; /**
* Created by wangjitao on 2017/3/28 0028.
* E-Mail:543441727@qq.com
* Java反射机制的简单实现
*/ public class TestReflect{ /**
* @param args
*/
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException { Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null; class1 = Class.forName("com.qianmo.flowlayout.reflection.TestReflect");
class2 = new TestReflect().getClass();
class3 =TestReflect.class;
System.out.println("类名称:"+class1.getName());
System.out.println("类名称:"+class2.getName());
System.out.println("类名称:"+class3.getName()); }
}
- 获取对象父类和实现的接口
package com.qianmo.flowlayout.reflection; import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; /**
* Created by wangjitao on 2017/3/28 0028.
* E-Mail:543441727@qq.com
* Java反射机制的简单实现
*/ public class TestReflect{ /**
* @param args
*/
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
Class<?> clazz = Class.forName("com.qianmo.flowlayout.reflection.TestReflect");
//获取父类
Class<?> superClazz = clazz.getSuperclass();
System.out.println("父类名称:"+superClazz.getName());
//获取所有接口
Class<?> intes[] = clazz.getInterfaces();
for (int i = 0; i < intes.length; i++) {
System.out.println("实现的接口有:"+intes[i].getName());
}
}
}
- 通过反射得到一个类中的全部构造函数
先创建User类
package com.qianmo.flowlayout.reflection; /**
* Created by wangjitao on 2017/3/29 0029.
* E-Mail:543441727@qq.com
*/ public class User {
private int age;
private String name; public User() {
super(); } public User(int age) {
super();
this.age = age;
} public User(String name) {
super();
this.name = name;
} public User(int age, String name) {
super();
this.age = age;
this.name = name; } public int getAge() {
System.out.println("Java 反射机制 - 调用某个类的方法1.");
return age;
} public void setAge(int age) {
this.age = age;
System.out.println("Java 反射机制 - 调用某个类的方法2.");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "User [age=" + age + ",name:" + name + "]";
}
}
在main方法中调用
package com.qianmo.flowlayout.reflection; import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; /**
* Created by wangjitao on 2017/3/28 0028.
* E-Mail:543441727@qq.com
* Java反射机制的简单实现
*/ public class TestReflect{ /**
* @param args
*/
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
Class<?> class1 = null;
class1 = Class.forName("com.qianmo.flowlayout.reflection.User");
//第一种方法使用默认的构造方法
User user_one = (User) class1.newInstance();
user_one.setAge(20);
user_one.setName("wangjitao");
System.out.println(user_one); //第二种获取所有构造方法,使用构造函数赋值
Constructor<?> cons[] = class1.getConstructors();
//查看每一个构造方法中所需要的参数
for (int i = 0; i < cons.length; i++) {
System.out.print("cons[" + i + "] (");
Class<?> clazzs[] = cons[i].getParameterTypes();
for (int j = 0; j <clazzs.length ; j++) {
System.out.print(clazzs[j].getName()+",");
}
System.out.println(")");
} //通过获取到的构造函数创建对象
user_one = (User) cons[0].newInstance(24,"wangjitao04");
System.out.println(user_one);
user_one = (User) cons[1].newInstance("wangjitao04");
System.out.println(user_one);
}
}
- 获取类中全部属性
Class<?> clazz = Class.forName("com.qianmo.flowlayout.reflection.User");
//获取本类中的全部属性
Field[] field = clazz.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
//权限修饰符
String priv = Modifier.toString(field[i].getModifiers());
//属性类型
Class<?> type = field[i].getType();
System.out.println("修饰符:" + priv + ",属性类型:" + type.getName()); }
//获取实现的接口或者父类的属性
Field[] fild1 = clazz.getFields();
for (int i = 0; i <fild1.length ; i++) {
int mo = fild1[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = fild1[i].getType();
System.out.println(priv + " " + type.getName() + " " + fild1[i].getName() + ";");
}
- 获取类中的全部方法
Class<?> clazz = Class.forName("com.qianmo.flowlayout.reflection.User");
Method method[] = clazz.getMethods();
for (int i = 0; i < method.length; i++) {
Class<?> returnType = method[i].getReturnType();
Class<?> para[] = method[i].getParameterTypes();
int temp = method[i].getModifiers();
System.out.println(method[i].getName() + "," + returnType.getName() + "," + Modifier.toString(temp));
for (int j = 0; j < para.length; j++) {
System.out.print(para[j].getName());
}
}
- 通过反射调用类中的方法
Class<?> clazz = Class.forName("com.qianmo.flowlayout.reflection.User");
Method method = clazz.getMethod("getAge");
method.invoke(clazz.newInstance()); method = clazz.getMethod("setAge", int.class);
method.invoke(clazz.newInstance(), 20);
- 通过反射操作类中的属性(包括私有属性)
Class<?> clazz = Class.forName("com.qianmo.flowlayout.reflection.User");
User user = (User) clazz.newInstance();
Field field = clazz.getDeclaredField("age");
field.setAccessible(true);
field.set(user, 50);
System.out.print(field.get(user));
通过以上的这些我们基本上可以在运行时候拿到一个类中成员变量、成员方法、接口、超类、构造方法等信息。
3,深入了解反射机制
一般来说Java中使用Class.fromName()函数来生成Class对象,那我们来看看源码(这里只展示了主要的部分)
.......省略........
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName(className, true, VMStack.getCallingClassLoader());
} .......省略........... @CallerSensitive
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
if (loader == null) {
loader = BootClassLoader.getInstance();
}
Class<?> result;
try {
result = classForName(name, initialize, loader);
} catch (ClassNotFoundException e) {
Throwable cause = e.getCause();
if (cause instanceof LinkageError) {
throw (LinkageError) cause;
}
throw e;
}
return result;
} /** Called after security checks have been made. */
static native Class<?> classForName(String className, boolean shouldInitialize,
ClassLoader classLoader) throws ClassNotFoundException;
Class.forName(classname)方法,实际上是调用了Class类中的 Class.forName(classname, true, currentLoader)方法。参数:name - 所需类的完全限定名;initialize - 是否必须初始化类;loader - 用于加载类的类加载器。currentLoader则是通过调用ClassLoader.getCallerClassLoader()获取当前类加载器的。类要想使用,必须用类加载器加载,所以需要加载器。反射机制,不是每次都去重新反射,而是提供了cache,每次都会需要类加载器去自己的cache中查找,如果可以查到,则直接返回该类。
而java的类加载器也很有意思,分为一下四类
BootStrap Class Loader(引导类加载器);
Extensions Class Loader (扩展类加载器);
App ClassLoader(或System Class Loader);
Custom ClassLoader(用户自定义类加载器)
类在加载的过程中,首先判断类是否被加载过,检测过程自底向上,首先从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。这里如果没有检测到则调用BootStrap ClassLoader加载器
这幅图简单的说明了类加载器的类加载过程。先检查自己是否已经加载过该类,如果加载过,则直接返回该类,若没有则调用父类的loadClass方法,如果父类中没有,则执行findClass方法去尝试加载此类,也就是我们通常所理解的片面的"反射"了。这个过程主要通过ClassLoader.defineClass方法来完成。defineClass 方法将一个字节数组转换为 Class 类的实例(任何类的对象都是Class类的对象)。这种新定义的类的实例需要使用 Class.newInstance 来创建,而不能使用new来实例化。
Java -- 浅入Java反射机制的更多相关文章
- Java 核心类库之反射机制
1:什么是反射机制? 2:反射机制它可以做什么呢? 3:反射机制对应的API又是什么? 1):通过反射机制来获取一个对象的全限定名称(完整包名),和类名: 2):实例化Class对象 3):获取对象的 ...
- java的泛型与反射机制
什么是泛型? 泛型,即“参数化类型”.顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参) ...
- Java动态代理和反射机制
反射机制 Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法.属性和构造方法等. 动态代理:分为JDK动态代理.cglib动态代理(spring中的动态代理). ...
- java.lang.Class<T> -- 反射机制
1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- 在JAVA中,关于反射机制的讨论
一.什么是反射机制 简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制 ...
- java工厂类与反射机制
java 简单工厂类 2012-04-22 15:44:07| 分类: java | 标签:java工厂类 简单工厂类 |举报|字号 订阅 简单工厂模式需要由以下角色组成: 接口 ...
- Java SE之初探反射机制
[Keywords]:Java,Hibernate,虚拟机,框架,SQL [Abstract]: 反射的概念:所谓的反射就是java语言在运行时拥有一项自观的能力,反射使您的程序代码能够得到装载到 ...
- JAVA(五)反射机制/Annotation
成鹏致远 | lcw.cnblog.com |2014-02-04 反射机制 1.认识Class类 在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在 java中也允许通过一个对象来找 ...
随机推荐
- 每天一个linux命令(43)--netstat命令
netstat 命令用于显示与 IP TCP UDP 和 ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况.netstat 是在内核中访问网络及相关信息的程序,它能提供TCP连接,T ...
- 【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则
作者:Williammao, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/290.h ...
- mybatis系列笔记(4)---输入输出映射
输入输出映射 通过parameterType制定输入参数类型 类型可以是简单类型(int String)也可以是POJO本身 或者包装类 1输入映射 关于输入简单类型和pojo本身的我就不写了,因为比 ...
- 4063: [Cerc2012]Darts
4063: [Cerc2012]Darts Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 85 Solved: 53[Submit][Status] ...
- iPhone 上显示桌面版页面
在用智能电话的浏览器打开页面时,很多网站会根据浏览器的屏幕大小自动调整显示布局,或跳转到移动设备使用的专用面上来优化显示.一些情况下,这种优化可能不是用户希望的,比如优化后的页面缺少桌面版的功能. 这 ...
- Nginx uWSGI web.py 站点搭建
一.安装nginx 在安装nginx前,需要先装nginx的依赖包. 1.如果没有yum则先安装yum 删除原有的yum rpm -aq|grep yum|xargs rpm -e --node ...
- final 、finally 和 finalize()的区别
1. final 是一个关键字.可以修饰数据.方法.类. 1)final 数据:final 用来修饰一个永不改变的编译时常量,或者运行时初始化但是不希望被改变的常量.一个既是 static又是 fin ...
- 深入浅出数据结构C语言版(1)——什么是数据结构及算法
在很多数据结构相关的书籍,尤其是中文书籍中,常常把数据结构与算法"混合"起来讲,导致很多人初学时对于"数据结构"这个词的意思把握不准,从而降低了学习兴趣和学习信 ...
- cuda编程学习2——add
cudaMalloc()分配的指针有使用限制,设备指针的使用限制总结如下: 1.可以将其传递给在设备上执行的函数 2.可以在设备代码中使用其进行内存的读写操作 3.可以将其传递给在主机上执行的函数 4 ...
- Spring中一个类的注入和引用是不一样的
1.在Spring管理下的bean需要以下面这种方式引入(一种注入方式): private MgrService mgrService; public MgrService getMgrService ...