java的反射机制
来源:互联网 发布:arp static ip mac 编辑:程序博客网 时间:2024/05/29 15:24
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
来点代码展现反射形态:
Object obj = new Person("xxc",99); //获得Class的实例的三种方式 //1.通过对象的getClass()方法获得 Class clazz1 = obj.getClass(); //2.通过表示类名的字符串来获得,注意:这里的字符串必须是完整路径,否则找不到这个类 String className = "com.xxc.reflet.Person"; Class clazz2 = Class.forName(className); //3.用类名.class的方式获取 Class clazz3 = Person.class; System.out.println(clazz3); System.out.println(clazz1 == clazz3);//true System.out.println(clazz1 == clazz2);//true System.out.println(clazz3 == clazz2);//true //获取基本数据类型的Class对象,void也是一种类型。 Class intClazz = int.class; System.out.println(intClazz);//打印int Class voidClazz = void.class; System.out.println(voidClazz);//打印void
/* * 获得类中定义的所有属性 * getField(String name)返回一个属性,是这个类或接口当中的公共成员字段 返回类型 Field * getFields()返回这个类或接口中所有公共成员字段 返回类型 Field[] * * getDeclaredField(String name)返回一个已声明的属性,可以是这个类或接口中任意权限的字段 返回类型 Field * getDeclaredFields() 返回这个类或借口中所有已声明的成员字段,任意权限 返回类型 Field[] */ Class clazz = Person.class; Field[] fields = clazz.getDeclaredFields(); for(Field f: fields){ System.out.println("属性名 "+f.getName()); System.out.println("类型: "+f.getType()); } /* * 用反射获取类中的成员字段: * 1.先根据这个属性的名字,拿到这个属性 * 2.设置反射的对象在使用时应该取消 Java 语言访问检查,说白了就是不受权限的限制,可以访问private * 3.返回指定对象上此 Field 表示的字段的值。 get(obj)参数的obj表示一个对象。返回obj对象里的字段。 */ Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); Object value = nameField.get(obj); System.out.println(value); /* * 利用反射来改某个对象里的属性,第一个参数表示要修改哪个对象,第二个表示被修改属性的值。 * 至于修改哪个属性,并不是在参数里指定的,调用set方法的那个类就表示哪个属性 */ nameField.set(obj, "xxm"); System.out.println(obj);
/* * 获得类中定义的所有方法 * getMethod(String name, Class<?>... parameterTypes) 返回这个类或接口中公共的方法 返回类型Method 第一个参数表示哪个对象,第二个参数表示参数类型 int.class * 因为光是指定函数名没用,重载的话就不能明确指出是哪一个方法。 * getMethods() 返回这个类或接口中所有公共的方法 返回类型是Method[] * * getDeclaredMethod(String name, Class<?>... parameterTypes) 返回这个类或接口中任意权限的方法 返回类型是Method * * getDeclaredMethods() 返回这个类或接口中任意权限的所有方法 返回类型是Method[] */ Object obj = new Person("xxc",99); Class clazz = obj.getClass(); Method[] methods = clazz.getDeclaredMethods(); for(Method m : methods){ System.out.println(m.getName());//返回方法名 System.out.println(m.getReturnType().getName());//返回方法的返回类型,如果直接是m.getReturnType()则会在返回类型前加class java.lang.String Class[] parameterTypes = m.getParameterTypes();//获取方法中的参数类型,并封装在一个数组中 for(Class parameterType : parameterTypes){//遍历参数类型数组 System.out.print("参数类型 "+parameterType.getName());//获取参数类型名称 } } Method method = clazz.getDeclaredMethod("run",String.class,int.class,String.class);//获取需要调用的方法对象 第一个参数是方法名字,第二个参数是参数类型 method.invoke(obj, "xxc",20,"男");//调用方法,第一个参数是具体对象,第二个参数是方法的实参
/*通过反射获取构造函数,以及其中的参数类型,构造函数名称,用构造函数创建对象。 *getConstructors() 获取某一个类中所有的公共权限构造函数 *getConstructor(Class<?>... parameterTypes) 获取某一个类中指定参数类型的公共权限构造函数 * *getDeclaredConstructors() 获取某一个类中所有的任意权限的构造函数 *getDeclaredConstructor(Class<?>... parameterTypes) 获取某一个类中指定参数类型的任意权限的构造函数 */ Object obj = new Person("xxc",99); Class clazz = obj.getClass(); Constructor[] constructors = clazz.getDeclaredConstructors(); for(Constructor constructor : constructors){ System.out.println("构造函数名字"+constructor.getName()); System.out.println("构造函数的参数类型:"); Class[] parametersTypes = constructor.getParameterTypes(); for(Class parametersType : parametersTypes){ System.out.print(parametersType.getName()); System.out.println(); } } //调用有参构造函数,创建对象 /* * 下面这句话的第二个参数能写数组的原因是因为在1.5前,这里的第二个参数就是数组类型。 * 它和可变参数最主要的区别就是,当调用的函数是没有参数的,那么可变参数的可以不用写,而用数组类型表示的需要写null */ Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class); //Constructor constructor = clazz.getDeclaredConstructor(new Class[]{String.class,int.class});JDK1.5之前用的 Person person = (Person)constructor.newInstance("xxx",99);//使用反射获取的有参构造函数创建对象 System.out.println(person);persion类
public class Person { private String name; private int age; Person(String name,int age){ this.name = name; this.age = age; } public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public void run(String str,int age,String sex){ System.out.println(str+" "+age+" "+sex); } }
获取类或方法前的修饰:
Package pack = clazz.getPackage();//获取某个类的包名 System.out.println("包名--->"+pack.getName()); int num = clazz.getModifiers();//可以获取类的修饰内容 /* * 以下这个方法这样用有局限性,因为一个类既有public修饰,又有abstract修饰 * Modifier.PUBLIC=1 * Modifier.abstract=1024 * 那么此时有两个修饰就是1025,所以再用Modifier.PUBLIC就不能正确判断了。 * 这时可以用Modifier.isPublic(num)来进行判断。 */ if(num == Modifier.PUBLIC){ System.out.println("这个类的修饰符是PUBLIC"); } if(Modifier.isPublic(num)){ System.out.println("这个类的修饰符是PUBLIC"); } Method run = clazz.getDeclaredMethod("run",String.class,int.class,String.class); if(Modifier.isPublic(run.getModifiers())){//函数中也有获取修饰符类型的方法 System.out.println("Run方法是PUBLIC修饰的");
练习:通过反射,做一个面向接口的,能计算任何形状面积的方法。
创建接口(此接口中有计算面积的抽象方法):
package com.xxc.reflet.test; public interface InterfaceTest { double getArea(); }
实现接口的类(圆)
package com.xxc.reflet.test; public class ChangFangXing implements InterfaceTest{ private double height; private double width; public double getArea() { return height*width; } }
实现接口的类(长方形)
package com.xxc.reflet.test; public class ChangFangXing implements InterfaceTest{ private double height; private double width; public double getArea() { return height*width; } }
测试:
package com.xxc.reflet.test; import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Field; public class RefletTest { public static void main(String[] args) throws Exception { System.out.println("请输入要计算的图形名称"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String name = br.readLine(); Class clazz; try { clazz = Class.forName("com.xxc.reflet.test."+name); } catch (Exception e) { System.out.println("不存在这样的图形"); return; } InterfaceTest ift = (InterfaceTest)clazz.newInstance(); Field[] parameterType = clazz.getDeclaredFields();//获得所有的数据域 for(Field f : parameterType){ System.out.println("请输入:"+f.getName()); double num = Double.parseDouble(br.readLine()); f.setAccessible(true);//将所有的域设置为可访问的。 f.setDouble(ift, num); } double area = ift.getArea(); System.out.println("图形面积是:"+area); } }
0 0
- java的反射机制
- Java的反射机制
- Java的反射机制
- Java 的反射机制
- JAVA的反射机制
- Java 的反射机制
- java的反射机制
- Java的反射机制
- Java 的反射机制
- JAVA的反射机制
- Java 的反射机制
- java的反射机制
- java的反射机制
- java的反射机制
- Java的反射机制
- Java的反射机制
- Java的反射机制
- Java的反射机制
- Open MP计算π的值
- 在CSDN开通博客专栏后如何发布文章及改进建议(图文)
- 【微机原理】-MCS-51单片机的功能模块原理
- Android里ListView的onItemClickListener点击失效
- 谨献给为了知识执着的嵌入式初学者
- java的反射机制
- Tweenlite防止内存溢出的写法
- The connection to adb is down, and a severe error has occured.问题解决
- 基于Android系统的智能家居控制终端研究与实现
- 基于Wi-Fi的室内定位在美团总部的实践和应用(上)
- Servlet中listener(监听器)和filter的总结
- JavaFX 概括
- Linux CentOS下BIND搭建智能DNS寻线
- ruby编译安装