java基础知识(十一)java反射机制(下)
1、什么是反射机制?
java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制。
也就是说,java程序可以加载一个运行时才得知名称的class,获悉该类的完整构造(但不包括methods定义),并生成其对象实体,或对其fields设值,或唤起其methods。总之,就是JVM可以在运行时加载、探知、使用编译期完全未知的classes。
2、jdk提供的反射api
Java反射相关的API在包java.lang.reflect中
Member接口 | 该接口可以获取有关类成员(域或者方法)后者构造函数的信息。 |
AccessibleObject类 | 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。 |
Array类 | 该类提供动态地生成和访问JAVA数组的方法。 |
Constructor类 | 提供一个类的构造函数的信息以及访问类的构造函数的接口。 |
Field类 | 提供一个类的域的信息以及访问类的域的接口。 |
Method类 | 提供一个类的方法的信息以及访问类的方法的接口。 |
Modifier类 | 提供了 static 方法和常量,对类和成员访问修饰符进行解码。 |
Proxy类 |
提供动态地生成代理类和类实例的静态方法。 |
3、反射机制的作用
在运行时获取任意一个类的成员变量和方法
在运行时构造任意一个类的对象
在运行时判断任意一个对象所属的类
在运行时调用任意一个对象的方法
生成动态代理
4、哪里用到了反射机制
在我们刚学jdbc时首先会用到这样一行代码Class.forName('com.MySQL.jdbc.Driver.class').newInstance();当时只是感性认识用来实例化驱动对象。其时我们开发中用到的许多框架都用到了反射,如spring、hibernate等在web.xml中的配置;还有我们开发中用到的工具的提示等。
5、代码实现
3.1获取Class对象
public class ClassCreate { public static void main(String[] args) { try { Class c1 = Class.forName("java.lang.String"); String s = new String("string"); Class c2 = s.getClass(); Class c3 = String.class; System.out.println(c1 + " | " + c2 + " | " + c3); System.out.println(c1 == c2); System.out.println(c1 == c3); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
由上面可以看出有3中获取Class对象的方法,并且同一个类在内存中拥有唯一的class对象(前提使用统一类加载器)。
3.2、获取类的构造
Class<T>类提供了几个方法获取类的构造器
public Constructor<T> getConstructor(Class<?>... parameterTypes) |
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法 |
public Constructor<?>[] getConstructors() |
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法 |
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) |
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法 |
public Constructor<?>[] getDeclaredConstructors() |
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法 |
public class ObtainConstructor { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.classTest.classload.OC"); Constructor[] ct = clazz.getConstructors(); for(Constructor c : ct) System.out.println(c.getName() + " | " + c.getParameterTypes().length); } } class OC { private String name; public OC() { } public OC(String name) { this.name = name; } }
3.3、获取类的方法
Class<T>类提供了几个方法获取类的方法。
public MethodgetMethod(String name,Class<?>... parameterTypes) |
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 |
public Method[] getMethods() |
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 |
public MethodgetDeclaredMethod(Stringname,Class<?>... parameterTypes) |
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法 |
public Method[] getDeclaredMethods() |
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法 |
public class ObtainMethod { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.classTest.classload.OM"); Method[] mt = clazz.getMethods(); for (Method m : mt) System.out.println(m.getName() + " | " + m.getReturnType() + " | " + m.getParameterTypes().length); } } class OM { public void getList() { } public void getList(String keyword) { } }
3.4、获取类的成员变量
JAVA 的Class<T>类提供了几个方法获取类的属性。
public FieldgetField(String name) | 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段 |
public Field[] getFields() | 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段 |
public FieldgetDeclaredField(Stringname) | 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段 |
public Field[] getDeclaredFields() |
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段 |
public class ObtainField { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.classTest.classload.OF"); Field[] fd = clazz.getFields(); for (Field f : fd) System.out.println(f.getName() + " | " + f.getType()); } } class OF { public String name; public int age; private String address; }
6、反射机制的优缺点
反射机制的优点是可以实现动态编译和创建对象。比如某软件的更新,采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
反射机制的缺点是反射基本是一种解释操作,对性能有影响。