反射(概述,Class对象和信息,使用反射生产并操作对象,数组,反射与框架)
2015-07-23 15:03
239 查看
1.反射的概述
Java程序中有很多对象都会在运行时出现两种类型:编译时类型和运行时类型,例如代码Person() p = new Student(); 那么他编译时就是Person类,运行的时候就是Student类,我们可以instanceof来判断,但是对于一些不知道类型的类来说,我们就只能依靠该对象的类信息来判断了,这就叫反射。
2.获得Class对象和信息
获取类的对象,有三种方式:
示例:
从Class中获取信息
示例:
运行结果:
3. 使用反射生产并操作对象
Class对象里面获得该类的方法(Method0), 构造器(Construtor)和成员变量(Field),程序可以通过对应的类来进行相应的操作。
1)使用反射创建对象
第一种:使用Class类的newInstance()方法来创建该类的实例。
第二种:通过Construtor对象的newInstance()方法来创建。
示例:
运行结果:
2)使用反射调用方法
调用Method中包含的一个invoke(Object obj, Object ... args):该方法中的obj执行方法的主调,后面的args是执行该方法时传入的实参。
如果是private方法,可以将Method对象的accessible设置为true。 setAccessible()方法是Method的父类AccessibleObject.
示例:
运行结果:
3)使用反射访问成员变量
首先反射的类应该符合JavaBean的原则,里面有set()和get()方法。
利用Field提供的getXxx(Obj obj)和setXxx(Obj obj, Xxx val)来获取obj的成员变量的值和设定成员变量的值
示例:
运行结果
运行结果:
4.反射与框架
正如老师所说,框架就好像房屋的结构,他提供了门窗的接口,至于怎么样去装修就会对于不同的人有不同的风格。反射正是解决这样的问题,不同的人有不同的风格,当时安装的规则还是一样的,只是内容换了。
示例:
运行结果:
Java程序中有很多对象都会在运行时出现两种类型:编译时类型和运行时类型,例如代码Person() p = new Student(); 那么他编译时就是Person类,运行的时候就是Student类,我们可以instanceof来判断,但是对于一些不知道类型的类来说,我们就只能依靠该对象的类信息来判断了,这就叫反射。
2.获得Class对象和信息
获取类的对象,有三种方式:
示例:
public class Demo01 { public static void main(String[] args) throws ClassNotFoundException { // 第一种方法使用Class.forName()方法 Class<?> name = Class.forName("Demo1"); // 第二种方法 类名.class Class className = Demo01.class; // 第三种方法调用某个对象的 getClass()方法。 Demo01 d = new Demo01(); Class className1 = d.getClass(); } }
从Class中获取信息
示例:
public class Demo02 { public static void main(String[] args) throws NoSuchMethodException, SecurityException { Class fruit = Fruit.class; // 获取构造器 Constructor[] constructors = fruit.getConstructors(); for (Constructor c : constructors) { System.out.println("构造器:" + c.getName() + "--参数个数:" + c.getParameterCount()); } Constructor c = fruit.getConstructor(String.class, String.class, String.class); System.out.println("2个参数的构造器是" + c.getName() + "修饰符:" + c.getModifiers()); // 获取方法:c.getParameterCount()表示的一般声明按声明顺序来声明的类型变量的数量 Method[] methods = fruit.getMethods(); for (Method m : methods) { System.out.println("方法名是:" + m.getName() + "--参数个数是:" + c.getParameterCount()); } Method[] declaredMethods = fruit.getDeclaredMethods(); for (Method m : declaredMethods) { System.out.println("与访问权限无关的方法名是:" + m.getName() + "--参数个数是:" + c.getParameterCount()); } Method method = fruit.getMethod("setShape", String.class); System.out.println(method.getName() + " -- " + method.getModifiers()); // 获取成员变量 Field[] fields = fruit.getFields(); for (Field f : fields) { System.out.println(f.getName() + " --" + f.getModifiers()); } Field[] fields2 = fruit.getDeclaredFields(); for (Field f : fields2) { System.out.println("与符号无关的字段:" + f.getName() + " --" + f.getModifiers()); } } } class Fruit { private String shape; private String color; public String length; @Override public String toString() { return "Fruit [shape=" + shape + ", color=" + color + "]"; } public String getShape() { return shape; } public void setShape(String shape) { this.shape = shape; } private String getColor() { return color; } public void setColor(String color) { this.color = color; } /* * public String getLength() { return length; } public void setLength(String * length) { this.length = length; } */ public Fruit(String shape, String color, String length) { super(); this.shape = shape; this.color = color; this.length = length; } public Fruit() { super(); } }
运行结果:
3. 使用反射生产并操作对象
Class对象里面获得该类的方法(Method0), 构造器(Construtor)和成员变量(Field),程序可以通过对应的类来进行相应的操作。
1)使用反射创建对象
第一种:使用Class类的newInstance()方法来创建该类的实例。
第二种:通过Construtor对象的newInstance()方法来创建。
示例:
public class Demo03 { /** * @param args * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { //第一种使用Class类的newInstance()方法来创建该类的实例。 Fruit f1 = Fruit.class.newInstance(); f1.setColor("黄色"); f1.setShape("椭圆形"); f1.setLength("长"); System.out.println(f1); //第二种通过Construtor对象的newInstance()方法来创建。 Class f = Fruit.class; Constructor c = f.getConstructor(String.class, String.class, String.class); Fruit obj = (Fruit) c.newInstance("圆形", "红色", "短"); System.out.println(obj); } } class Fruit { private String shape; private String color; public String length; @Override public String toString() { return "Fruit [shape=" + shape + ", color=" + color + ",length=" + length + "]"; } public String getShape() { return shape; } public void setShape(String shape) { this.shape = shape; } private String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getLength() { return length; } public void setLength(String length) { this.length = length; } public Fruit(String shape, String color, String length) { super(); this.shape = shape; this.color = color; this.length = length; } public Fruit() { super(); } }
运行结果:
2)使用反射调用方法
调用Method中包含的一个invoke(Object obj, Object ... args):该方法中的obj执行方法的主调,后面的args是执行该方法时传入的实参。
如果是private方法,可以将Method对象的accessible设置为true。 setAccessible()方法是Method的父类AccessibleObject.
示例:
public class Demo03 { /** * @param args * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class f = Fruit.class; Constructor c = f.getConstructor(String.class, String.class, String.class); Fruit obj = (Fruit) c.newInstance("圆形", "红色", "短"); System.out.println(obj); // 获取Method对象 Method m = f.getMethod("setShape", String.class); // 操作方法 m.invoke(obj, "五角形"); System.out.println(obj); // 获取Method对象 Method m2 = f.getDeclaredMethod("setLength", String.class); m2.setAccessible(true);// 方法的访问控制符是private,需将Method对象的accessible设置为true m2.invoke(obj, "长"); System.out.println(obj); } } class Fruit { private String shape; private String color; public String length; @Override public String toString() { return "Fruit [shape=" + shape + ", color=" + color + ",length=" + length + "]"; } public String getShape() { return shape; } public void setShape(String shape) { this.shape = shape; } private String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getLength() { return length; } private void setLength(String length) { this.length = length; } public Fruit(String shape, String color, String length) { super(); this.shape = shape; this.color = color; this.length = length; } public Fruit() { super(); } }
运行结果:
3)使用反射访问成员变量
首先反射的类应该符合JavaBean的原则,里面有set()和get()方法。
利用Field提供的getXxx(Obj obj)和setXxx(Obj obj, Xxx val)来获取obj的成员变量的值和设定成员变量的值
示例:
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { Class f = Fruit.class; Constructor c = f.getConstructor(String.class, String.class, String.class); Fruit obj = (Fruit) c.newInstance("圆形", "红色", "短"); System.out.println(obj); //获取成员变量:由于shape和color属性值都是私有的,需要设置accessible() Field field = f.getDeclaredField("shape"); field.setAccessible(true); String shape = (String) field.get(obj); Field field2 = f.getDeclaredField("color"); field2.setAccessible(true); String color = (String) field2.get(obj); System.out.println(shape +"--" + color); } } class Fruit { private String shape; private String color; public String length; @Override public String toString() { return "Fruit [shape=" + shape + ", color=" + color + ",length=" + length + "]"; } public String getShape() { return shape; } public void setShape(String shape) { this.shape = shape; } private String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getLength() { return length; } private void setLength(String length) { this.length = length; } public Fruit(String shape, String color, String length) { super(); this.shape = shape; this.color = color; this.length = length; } public Fruit() { super(); } }
运行结果
</pre><p><span style="font-size:18px;">4)使用反射操作数组</span></p><p><span style="font-size:18px;">在java.lang.reflect包中的Array类,Array对象可以包含所有的数组。程序可以通过他来动态地创建数组,和操作数组元素。</span></p><p><span style="font-size:18px;">示例:</span></p><p><span style="font-size:18px;"></span></p><pre name="code" class="java">public class Demo04 { /** * @param args * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws InstantiationException, IllegalAccessException { Object obj = "abc"; print(obj); int[] a = new int[] { 12, 4, 12, 44, 5, 4 }; print(a); } private static void print(Object obj) throws InstantiationException, IllegalAccessException { // 得到Class对象 Class<? extends Object> className = obj.getClass(); // 判断Class对象是否是数组 if (className.isArray()) { int len = Array.getLength(obj); for (int i = 0; i < len; i++) { System.out.println(Array.getInt(obj, i)); } } else { System.out.println(obj); } } }
运行结果:
4.反射与框架
正如老师所说,框架就好像房屋的结构,他提供了门窗的接口,至于怎么样去装修就会对于不同的人有不同的风格。反射正是解决这样的问题,不同的人有不同的风格,当时安装的规则还是一样的,只是内容换了。
示例:
public class Demo05 { /** * @param args * @throws IOException * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { InputStream is = new FileInputStream("E:/app2/Test/src/init.properties"); // 加载配置文件 Properties p = new Properties(); p.load(is); String name = p.getProperty("name"); is.close(); // 反射再进行相关操作 Class<?> clazz = Class.forName(name); ArrayList c = (ArrayList) clazz.newInstance(); c.add(1); c.add(3); c.add(5); c.add(2); for (int i = 0; i < c.size(); i++) { System.out.print(c.get(i) + " "); } } }
运行结果:
相关文章推荐
- TCP和UDP协议有什么不同?
- hadoop distcp拷贝数据问题
- JS点击复制
- 江城感怀---诗一首
- Android真机调试的时候logcat中无法输出调试信息的解决办法
- FreeMaker学习笔记
- LVS_NAT
- lamp编译安装
- eclipse或IDEA连接魅蓝
- linux网络设置命令
- android 实现地图定位功能
- GROUP函数-GROUP_ID,GROUPING,GROUPING_ID
- 移动端rem布局
- CentOS 7.1 (6.6)PXE网络自动化安装
- 使用C语言计算utf-8字符串长度
- Android活动的启动模式
- 图像分割(Image Segmentation)
- [ASP.NET MVC 小牛之路]18 - Web API
- 银行业双活数据中心-F5在双活数据中心中的应用
- delphi使用细节