java中的反射机制

xiaoxiao2021-02-27  159

反射概念:

Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。

换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。

反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!


JAVA反射机制提供了什么功能

提供了如下功能:

在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时判段任意一个类所具有的成员变量和方法在运行时调用任一个对象的方法在运行时创建新类对象在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。

反射机制的作用:

反编译:.class–>.java通过反射机制访问java对象的属性,方法,构造方法等;

Java中JDK提供的Reflection API

Java反射相关的API在包java.lang.reflect中。

Member接口 该接口可以获取有关类成员(域或者方法)后者构造函数的信息。

AccessibleObject类 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认

Java 语言访问控制检查的能力。 Array类 该类提供动态地生成和访问JAVA数组的方法。

Constructor类 提供一个类的构造函数的信息以及访问类的构造函数的接口。 Field类 提供一个类的域的信息以及访问类的域的接口。

Method类 提供一个类的方法的信息以及访问类的方法的接口。

Modifier类 提供了 static方法和常量,对类和成员访问修饰符进行解码。

Proxy类 提供动态地生成代理类和类实例的静态方法。


动态创建代理类

代理模式:代理模式的作用=为其他对象提供一种代理以控制对这个对象的访问。

代理模式的角色:

抽象角色:声明真实对象和代理对象的共同接口代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

动态代理:

java.lang.reflect.Proxy Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类InvocationHandler 是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

动态Proxy是这样的一种类:

它是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。 在使用动态代理类时,我们必须实现InvocationHandler接口


实例练习:

import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; public class InvokeTest { /** * 利用反射机制实现调用方法 * @param obj * @param methodName * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */ public static void test(String methodName) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { InvokeTest test=new InvokeTest(); //对象类型 Class<?> cls=test.getClass(); //利用反射机制获取该类型下的方法 Method method=cls.getMethod(methodName, int.class,String.class); //执行该方法 method.invoke(test, 10,"20"); // test.method(10,20) } /** * ...代表:一组相同类型的数据(不约束个数) * 一个方法里最多只能有一个...类型 * ...类型必须出现在参数列表的最后位置 * @param a */ public static void e(int... a) { for(int i=0;i<a.length;i++) { System.out.println(a[i]); } } //反射机制 //调用方法 //不知道方法名或属性名 //通过传递参数来实现调用 public static void main(String[] args) { //...省略参数类型 e(1,2,3,4,5); //反射机制 try { test("d"); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block //没有该方法 e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void a() { System.out.println("aaaaaaaaaa"); } public void b(int b) { System.out.println("b="+b); } public void c(int a,int b) { System.out.println("sum="+(a+b)); } public void d(int a,String b) { System.out.println(a+b); } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182

具体功能的实现

反射机制获取类有三种方法,我们来获取Employee类型。

//第一种方式: Classc1 = Class.forName("Employee"); //第二种方式: //java中每个类型都有class 属性. Classc2 = Employee.class; //第三种方式: //java语言中任何一个java对象都有getClass 方法 Employeee = new Employee(); Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee) 12345678910 12345678910

创建对象:获取类以后我们来创建它的对象,利用newInstance:

Class c =Class.forName("Employee"); //创建此Class 对象所表示的类的一个新实例 Objecto = c.newInstance(); //调用了Employee的无参数构造方法. 1234 1234

获取属性:分为所有的属性和指定的属性: a,先看获取所有的属性的写法:

//获取整个类 Class c = Class.forName("java.lang.Integer"); //获取所有的属性? Field[] fs = c.getDeclaredFields(); //定义可变长的字符串,用来存储属性 StringBuffer sb = new StringBuffer(); //通过追加的方法,将每个属性拼接到此字符串中 //最外边的public定义 sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n"); //里边的每一个属性 for(Field field:fs){ sb.append("\t");//空格 sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等 sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字 sb.append(field.getName()+";\n");//属性的名字+回车 } sb.append("}"); System.out.println(sb); 123456789101112131415161718192021 123456789101112131415161718192021

b,获取特定的属性,对比着传统的方法来学习:

public static void main(String[] args) throws Exception{ <span style="white-space:pre"> </span>//以前的方式: /* User u = new User(); u.age = 12; //set System.out.println(u.age); //get */ //获取类 Class c = Class.forName("User"); //获取id属性 Field idF = c.getDeclaredField("id"); //实例化这个类赋给o Object o = c.newInstance(); //打破封装 idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。 //给o对象的id属性赋值"110" idF.set(o, "110"); //set //get System.out.println(idF.get(o)); } 12345678910111213141516171819202122 12345678910111213141516171819202122

参考博客:

博客1:

http://blog.csdn.net/liujiahan629629/article/details/18013523

博客2:

http://blog.csdn.net/yongjian1092/article/details/7364451

转载请注明原文地址: https://www.6miu.com/read-14662.html

最新回复(0)