------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一,什么是反射机制
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,
那么就可以通过反射机制来获得类的所有信息。
二,哪里用到反射机制
有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码,
Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成
驱动对象实例,并不知道它的具体含义。听了反射机制这节课后,才知道,原来这就是反射,现在很多开
框架都用到反射机制,hibernate、struts都是用反射机制实现的。
三,反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多
态的应用,有以降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中
它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编
译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如
这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能
的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功
能。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它
满足我们的要求。这类操作总是慢于只直接执行相同的操作。
四,获取某个类的Class对象的三种方式:
方式一:调用对象的getClass()方法。它是Object类中的方法。
此方法是普通方法,不是静态的,要通过类的对象的引用去调用。
Student stu = new Studetn();
Class stuClass = stu.getClass();
方式二:任何的"数据类型"都有一个"静态的属性"--class属性,这个属性可以
获取这个类的Class对象
方式三:调用Class类中的静态方法forName()可以获取某个类的Class对象;
public static Class forName(String className)
1,获取并调用这个类的所有的构造方法:
批量获取
1.public Constructor[] getConstructors():获取所有公共构造方法
2.public Constructor[] getDeclaredConstructors():获取所有构造方法。包括公有,受保护,默认,私有
获取单个的构造方法:
1.public Constructor getConstructor(Class... parameterTypes):获取类中的指定的"公有构造方法"。
参数:parameterTypes:构造方法形参的类型的Class
2.public Constructor getDeclaredConstructor(Class...parameterTypes):获取类中的任何的构造方法,包括私有的
调用构造方法:通过Constructor去调用。使用方法:public T newInstance(Object... initargs)
2,通过Class对象获取成员属性,并调用:
批量获取:
1.Field[] getFields() :所用"公有"的成员属性
2.Field[] getDeclaredFields() :所有的成员属性,包括私有的:
获取单个的属性
1.Field getField(String fieldName):获取单个的,公有的成员属性
2.Field getDeclaredField(String fieldName):获取单个的成员属性,可以是任何的访问级别
怎样设置和获取属性的值?
Field:
set(Object obj,Object value):设置值。注意:设置前,一定要先实例化一个此类的对象。
get(Object obj)
3,通过Class对象获取某个类的成员方法并调用:
批量获取:
1.Method[] getMethods() :获取所有的"公有"方法;
2.Method[] getDeclaredMethods() :获取所有方法,包括私有的。
获取单个的:
1.Method getMethod(String name, Class<?>... parameterTypes) :获取某个公有的方法。
形参:name:方法名;
parameterTypes:形参的类型列表;
2.Method getDeclaredMethod(String name, Class<?>... parameterTypes):获取某个方法。可以是私有的。
调用方法:
Method:public Object invoke(Object obj,Object... args):调用此方法;
注意:调用方法前,一定要先实例化一个此类对象。
参数:
obj : 方法所属的对象;
args: 调用方法需要的实参
五, 一个小例子:
1.定义一个具有Integer类型泛型的集合对象,问:怎么可以向这个集合中添加一个字符串;
1.例子:
1).Student类中有一个coding()方法,写程序;
2).测试类中如果需要coding()方法,需要直接实例化一个Student,并调用方法;
如果想在coding()方法的前面或者后面添加一些其他功能,可以不用修改Student类,而为Student类添加
一个"代理类",代理类会调用Student类中的方法。
3).增加了代理类后,测试类不需要直接面对Student,转而使用代理类。代理类中为coding方法添加了新的功能。
动态代理:
1.之前的例子实现有些麻烦,要为每个需要代理的类单独提供一个"代理类";
2.Java类中提供了"动态代理",使我们不需要为每个类都提供"代理类",它在内部会动态的生成代理类:
3.使用动态代理的步骤:
1).自定义一个类,实现InvocationHandler接口,重写内部的invoke()方法;
2).在需要代理类的时候,使用Proxy的newProxyInstance()方法获取代理类的对象
七,一些简单代码:
一,什么是反射机制
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,
那么就可以通过反射机制来获得类的所有信息。
二,哪里用到反射机制
有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码,
Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成
驱动对象实例,并不知道它的具体含义。听了反射机制这节课后,才知道,原来这就是反射,现在很多开
框架都用到反射机制,hibernate、struts都是用反射机制实现的。
三,反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多
态的应用,有以降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中
它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编
译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如
这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能
的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功
能。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它
满足我们的要求。这类操作总是慢于只直接执行相同的操作。
四,获取某个类的Class对象的三种方式:
方式一:调用对象的getClass()方法。它是Object类中的方法。
此方法是普通方法,不是静态的,要通过类的对象的引用去调用。
Student stu = new Studetn();
Class stuClass = stu.getClass();
方式二:任何的"数据类型"都有一个"静态的属性"--class属性,这个属性可以
获取这个类的Class对象
方式三:调用Class类中的静态方法forName()可以获取某个类的Class对象;
public static Class forName(String className)
常用:方式三
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
Student stu = new Student();
//方式一:
Class stuClass1 = stu.getClass();
//方式二:
Class stuClass2 = Student.class;
//方式三:
// Class stuClass3 = Class.forName("Student");//运行时异常。这里需要的是:全名限定的类名(带包的类名)
Class stuClass3 = Class.forName("cn.itcast.demo01_获取Class对象的三种方式.Student");
//对于Student的Class对象,三种方式获取的都是同一个Class对象。这个Class对象,在内存中只产生一个。
System.out.println("stuClass1 == stuClass2 :" + (stuClass1 == stuClass2));
System.out.println("stuClass1 == stuClass3 : " + (stuClass1 == stuClass3));;
}
}
通过这个Class对象,我们可以:
1,获取并调用这个类的所有的构造方法:
批量获取
1.public Constructor[] getConstructors():获取所有公共构造方法
2.public Constructor[] getDeclaredConstructors():获取所有构造方法。包括公有,受保护,默认,私有
获取单个的构造方法:
1.public Constructor getConstructor(Class... parameterTypes):获取类中的指定的"公有构造方法"。
参数:parameterTypes:构造方法形参的类型的Class
2.public Constructor getDeclaredConstructor(Class...parameterTypes):获取类中的任何的构造方法,包括私有的
调用构造方法:通过Constructor去调用。使用方法:public T newInstance(Object... initargs)
2,通过Class对象获取成员属性,并调用:
批量获取:
1.Field[] getFields() :所用"公有"的成员属性
2.Field[] getDeclaredFields() :所有的成员属性,包括私有的:
获取单个的属性
1.Field getField(String fieldName):获取单个的,公有的成员属性
2.Field getDeclaredField(String fieldName):获取单个的成员属性,可以是任何的访问级别
怎样设置和获取属性的值?
Field:
set(Object obj,Object value):设置值。注意:设置前,一定要先实例化一个此类的对象。
get(Object obj)
3,通过Class对象获取某个类的成员方法并调用:
批量获取:
1.Method[] getMethods() :获取所有的"公有"方法;
2.Method[] getDeclaredMethods() :获取所有方法,包括私有的。
获取单个的:
1.Method getMethod(String name, Class<?>... parameterTypes) :获取某个公有的方法。
形参:name:方法名;
parameterTypes:形参的类型列表;
2.Method getDeclaredMethod(String name, Class<?>... parameterTypes):获取某个方法。可以是私有的。
调用方法:
Method:public Object invoke(Object obj,Object... args):调用此方法;
注意:调用方法前,一定要先实例化一个此类对象。
参数:
obj : 方法所属的对象;
args: 调用方法需要的实参
五, 一个小例子:
1.定义一个具有Integer类型泛型的集合对象,问:怎么可以向这个集合中添加一个字符串;
public class Demo {
public static void main(String[] args) throws Exception{
ArrayList<Integer> intList = new ArrayList<>();
intList.add(10);
// intList.add("abc");
//通过反射,直接去加载ArrayList的Class,然后调用它的add方法
Class listClass = ArrayList.class;
//获取add方法
Method addMethod = listClass.getMethod("add", Object.class);
//调用add方法
addMethod.invoke(intList, "abc");
//遍历集合
System.out.println("遍历集合:");
for(Object o : intList){
System.out.println(o);
}
}
}
六,代理模式:
1.例子:
1).Student类中有一个coding()方法,写程序;
2).测试类中如果需要coding()方法,需要直接实例化一个Student,并调用方法;
如果想在coding()方法的前面或者后面添加一些其他功能,可以不用修改Student类,而为Student类添加
一个"代理类",代理类会调用Student类中的方法。
3).增加了代理类后,测试类不需要直接面对Student,转而使用代理类。代理类中为coding方法添加了新的功能。
动态代理:
1.之前的例子实现有些麻烦,要为每个需要代理的类单独提供一个"代理类";
2.Java类中提供了"动态代理",使我们不需要为每个类都提供"代理类",它在内部会动态的生成代理类:
3.使用动态代理的步骤:
1).自定义一个类,实现InvocationHandler接口,重写内部的invoke()方法;
2).在需要代理类的时候,使用Proxy的newProxyInstance()方法获取代理类的对象
七,一些简单代码:
实例一:获得完整的类名
//获得完整的类名
public class GetClassName {
public String getNameByClass() {
String name = "";
System.out.println("通过类本身获得对象");
Class UserClass = this.getClass();
System.out.println("获得对象成功!\n");
System.out.println("通过类对象获得类名");
name = UserClass.getName();
System.out.println("获得类名成功!");
return name;
}
public static void main(String[] args) {
GetClassName gcn = new GetClassName();
System.out.println("类名为:"+gcn.getNameByClass());
}
}
运行结果:
通过类本身获得对象
获得对象成功!
通过类对象获得类名
获得类名成功!
类名为:reflection.getclassname.GetClass Name
实例二:获得类的属性
//获得类的属性
public class GetFields {
public static void getFieldNames(String className) {
try {
//获得类名
Class c = Class.forName(className);
//获得所有属性
Field[] fds = c.getFields();
for (int i=0; i<fds.length; i++)
{
String fn = fds[i].getName();
Class tc = fds[i].getType();
String ft = tc.getName();
System.out.println("该属性的名字为:"+fn+",该属性的类型为:"+ft);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
GetFields.getFieldNames("reflection.getfields.FieldInfo");
}
}
运行结果:
该属性的名字为:id,该属性的类型为:java.lang.String
该属性的名字为:username,该属性的类型为:java.lang.String
实例三:获得类实现的接口
//获得类实现的接口
public class GetInterfaces {
public static void getInterfaces(String className) {
try {
//取得类
Class cl = Class.forName(className);
Class[] ifs = cl.getInterfaces();
for (int i = 0; i<ifs.length;i++)
{
String IName = ifs[i].getName();
System.out.println("该类实现的接口名字为:"+IName);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
GetInterfaces.getInterfaces("reflection.getinterfaces.Student");
}
}
运行结果:
该类实现的接口名字为:reflection.getinterfaces.Person
实例四:获得类及其属性的修饰符
//获得类及其属性的修饰符
public class GetModifiers {
private String username = "liu shui jing";
float f = Float.parseFloat("1.000");
public static final int i = 37;
//获得类的修饰符
public static String useModifiers(UserInfo ui) {
Class uiClass = ui.getClass();
int m = uiClass.getModifiers();
return Modifier.toString(m);
}
//获得本类属性的修饰符
public void checkThisClassModifiers() {
Class tc = this.getClass();
Field fl[] = tc.getDeclaredFields();
for(int i=0;i<fl.length;i++)
{
System.out.println("第"+(i+1)+"个属性的修饰符为:"+Modifier.toString(fl[i].getModifiers()));
}
}
public static void main(String[] args) {
//获得类的修饰符
UserInfo ui =new UserInfo();
System.out.println("获得这个类的修饰符:"+GetModifiers.useModifiers(ui)+"\n");
//获得本类属性的修饰符
GetModifiers gm = new GetModifiers();
gm.checkThisClassModifiers();
}
}
运行结果:
获得这个类的修饰符:public
第1个属性的修饰符为:private
第2个属性的修饰符为:
第3个属性的修饰符为:public static final
实例五:获得类的构造函数
//获得类的构造函数
public class GetConstructor {
//构造函数一
GetConstructor(int a) {
}
//构造函数二
GetConstructor(int a, String b) {
}
public static void getConstructorInfo(String className) {
try {
//获得类的对象
Class cl =Class.forName(className);
System.out.println("获得类"+className+"所有的构造函数");
Constructor ctorlist[] = cl.getDeclaredConstructors();
System.out.println("遍历构造函数\n");
for(int i =0 ; i<ctorlist.length; i++)
{
Constructor con = ctorlist[i];
System.out.println("这个构造函数的名字为:"+con.getName());
System.out.println("通过构造函数获得这个类的名字为:"+con.getDeclaringClass());
Class cp[] = con.getParameterTypes();
for (int j=0; j<cp.length; j++)
{
System.out.println("参数 "+j+" 为 "+cp[j]+"\n");
}
}
}catch (Exception e) {
System.err.println(e);
}
}
public static void main(String[] args) {
GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");
}
}
运行结果:
获得类reflection.getconstructor.GetConstructor所有的构造函数
遍历构造函数
这个构造函数的名字为:reflection.getconstructor.GetConstructor
通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor
参数 0 为 int
这个构造函数的名字为:reflection.getconstructor.GetConstructor
通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor
参数 0 为 int
参数 1 为 class java.lang.String