Java反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射(背景):
什么是反射?有什么用?
先了解一些基本的概念:运行时,编译时,编译型,解释型,类加载器,动态加载类
什么是编译?
将原程序翻译成计算机语言,就是二进制代码,在java中是将.java文件也就是源程序翻译成.class的字节码
什么是编译时?
将原程序翻译成计算机语言的过程中,将.java翻译为.class文件的过程
什么是运行时?
就是在启动这个程序的时候,在java中是,类加载器加载.class文件,并交给jvm处理
什么是编译型语言?
将原程序一次性全部转换为二进制代码,然后执行程序
什么是解释型语言?
转换一句,执行一句,java是既编译又解释的语言
编译型语言和解释型语言的区别:编译型语言效率高,依赖于编译器,但是跨平台差,解释型的效率低,依赖于解释器,但跨平台强
什么是类加载器?
类加载器就是JVM中的类装载器,作用就是将编译好的.class字节码运到检查器进行安全检查的,检查通过后开始解释执行
什么是运行时动态加载类?
反射就是可以将一个程序(类)在运行的时候获得该程序(类)的信息的机制,也就是获得在编译期不可能获得的类的信息,因为这些信息是保存在Class对象中的,而这个Class对象是在程序运行时动态加载的
它就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成对象。类在运行的时候,可以得到该类的信息,并且 可以动态的修改这些信息,自己能看到自己,跟照镜子一样,class对象是在运行的时候产生的,通过class对象操作类的信息是在运行时进行的,当运行 程序的时候,类加载器会加载真正需要的类,什么是真正需要的呢?就是该类真正起作用,如:有该类的对象实例,或该类调用了静态方法属性等
反射的作用第一,远程方法调用,第二,通过容器得到组件的对象
理解Class类
1.在面向对象的世界里,万事万物皆对象。
java语言中,静态的成员、普通数据类型类是不是对象呢?
类是不是对象呢?类如果是对象又是谁的对象?
类是对象,类是java.lang.Class类的实例对象。
2.这个对象如何表示?
得到Class对象有三种方法如下:
如何实现反射呢?
得到Class对象
三种方式得到Class对象:
1.调用对象的getClass方法,返回该对象的Class对象; Class c=Object.getClass(); 2.Class.forName(“类的名字”); Class c=Class.forName (“…”); 3.Class c=类名.class; Class c=String.class;
java.lang.reflect包下的类
Method类:提供一个类的方法的信息以及访问类的方法的接口。
Constructor类:提供一个类的构造函数的信息以及访问类的构造函数的接口。
Field类:提供一个类的域的信息以及访问类的域的接口。
使用Class创建对象
Class c= Class.forName("类的全名"); Object o=c.newInstance(); Test1 t = Test1.class.newInstance();
找出class属于那个包
Class c=Test1.class; Package p; p=c.getPackage();
调用方法
Class c = Class.forName(“类的全名”);//获得访问类的对象 Object obj=c.newInstance();//获得被访问类的实例对象 Class[] cs=new Class[]{String.class};//设置参数类型 Method ff=c.getMethod(“setName”,cs);//得到参数匹配的方法 Object[] values=new Object[]{“你好”};//设置需要传递的值 ff.invoke(obj,values);//映射 ff=c.getMethod("getName"); Object uuu= ff.invoke(obj);
动态调用有参数静态方法
Class c = Class.forName("类的全名"); Class[] cs=new Class[]{String.class}; Method m=c.getMethod("setName",cs); Object[] o=new Object[]{"aaa"}; m.invoke(c,o);
得到属性和构造器及函数
Field[] ff = c.getDeclaredFields(); //无论静态还实体还私有皆可得到属性 Constructor[] ccc= c.getDeclaredConstructors(); //得到构造 Method[] mm=c.getDeclaredMethods();//无论静态还实体还私有皆可得到函数
调用构造器
Class c = Class.forName(“类的全名"); Class[] cs=new Class[]{String.class}; Constructor cc= c.getConstructor(cs); Object[] o=new Object[]{"ssssssssssssss"}; cc.newInstance(o);
Method[] methods = classObj1.getMethods(); //获取所有成员方法包含 父类成员方法 Method[] methods = calze.getDeclaredMethods(); //获取类里所有成员方法 Field[] fields = claze.getDeclaredFields();//得到所有属性 Constructor[] constructors = claze.getConstructors();//得到所有构造方法
反射优缺点
优点:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类;
缺点: (1)性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。 (2)使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。 反射代码比相应的直接代码更复杂。
java中利用反射实现工厂模式
package com.scxh.java.factory; interface Fruit { //水果接口 public void eat() //吃水果 } class Apple implements Fruit{ //定义苹果 public void eat() { System.out.println("**吃苹果。"); } } class Orange implements Fruit{ public void eat() { System.out.println("**吃橘子。"); } } class Factory{ public static Fruit getInstance(String className){ Fruit fruit = null try{ fruit = (Fruit) Class.forName(className).newInstance() }catch(Exception e ){ e.printStackTrace() } return fruit } } public class FactoryDemo{ public static void main(String args[]){ //通过工厂类取得接口实例,传入完整的包.类名称 Fruit f = Factory.getInstance("com.scxh.java.factorydemo.Apple") if(f!=null){ //判断是否取得接口实例 f.eat() } } }
反射工具类获取指定类的属性、方法,构造方法
/** * 反射机制实现: 打印指定类的属性、方法,构造方法 * * * @author zhou.sir * */ public class ReflectUtil { /** 输出结果: String name int age int id String sex Student() Student(String int int String ) String toString() void playeGame() void makeFriend() void learn() */ public static void main(String[] args) throws ClassNotFoundException { showDeclaredParameter(getClaze()); showConstruction(getClaze()); showDeclaredMethods(getClaze()); } /** * 获取类对象 * @throws ClassNotFoundException */ public static Class<?> getClaze() throws ClassNotFoundException{ Class<?> classObj1 = Student.class; // Class classObj2 = new Dog().getClass(); // Class classObj3 = Class.forName("com.scxh.java1601.object.ex01.test.Student"); // Log.d(classObj1.getName()); return classObj1; } /** * 显示成员方法头 * @param calze */ public static void showDeclaredMethods(Class calze){ // Method[] methods = classObj1.getMethods(); //获取所有成员方法包含 父类成员方法 Method[] methods = calze.getDeclaredMethods(); //获取类里所有成员方法 for (int i = 0, n = methods.length; i < n; i++) { String methodName = methods[i].getName(); Class returnType = methods[i].getReturnType(); Class[] parameterType = methods[i].getParameterTypes(); Log.v(subString(returnType.getName()) + " " + methodName + "("); for (Class p : parameterType) { Log.v(subString(p.getName()) + " "); } Log.d(")"); } } public static void showDeclaredParameter(Class claze){ Field[] fields = claze.getDeclaredFields();//得到所有属性 for(Field f : fields){ String fieldName = f.getName(); Class parameterType = f.getType(); String ptName = subString(parameterType.getName()); Log.d(ptName+ "\t"+fieldName); } } public static void showConstruction(Class claze){ Constructor[] constructors = claze.getConstructors();//得到所有构造方法 for(Constructor c : constructors){ String constructorName = c.getName(); Class[] parameterType = c.getParameterTypes(); Log.v(subString(constructorName) + "("); for (Class p : parameterType) { Log.v(subString(p.getName()) + " "); } Log.d(")"); } } public static String subString(String str){ String ptName = str; if(ptName.contains(".")){ int lastIndex = ptName.lastIndexOf("."); ptName = ptName.substring(lastIndex+1); } return ptName; } }
转载请注明来源:Java反射机制