java 反射
反射的意义与作用
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;
这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
反射主要的作用如下:
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method,反射的实现主要依靠Class类,以下重点阐述Class类。
Class类
Class类也是类的一种,只不过是一个比较特殊的类。Class类的对象用于描述某个类的信息(构造器、字段、方法)。
得到某个类的Class对象有以下三种方法:
通过该类实例对象的getClass()
// num为Integer类的实例对象 Integer num = new Integer(3); // 通过num的getClass()方法得到Integer类的Class对象 Class<?> intClass = num.getClass();
使用“类.class”取得
// 得到Integer类的Class对象 Class<?> intClass = Integer.class;
使用Class类内部定义的一个static方法 forName(String className)
// 得到Integer类的Class对象 Class<?> intClass = Class.forName("java.lang.Integer");
Class类对象的作用
得到某个类的Class类对象,该Class对象包含了这个类的所有信息(所有的方法,所有的构造函数,所有的字段)。
通过某个类的Class类对象,可以实现以下功能:
创建该类实例(类似new)
package exercise5; public class ReflectionTest { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // 得到Computer类的Class对象 Class<?> computerClass = Class.forName("exercise5.Computer"); // 通过Computer的Class对象computerClass // 创建Computer类的实例 Computer com = (Computer) computerClass.newInstance(); } } class Computer { public Computer() { System.out.println("A constructor without arguments"); } public Computer(String name) { System.out.println("Name is " + name); } public Computer(String name, int i){ System.out.println("Name is " + name); System.out.println("Price is " + price); } private String brand; public void setBrand(String brand) {this.brand = brand;} public String getBrand() {return this.brand;} private double price; public void setPrice(double price) {this.price = price;} public double getPrice() {return this.price;} }
对于对象的实例化操作,除了使用关键字new之外又多了一个反射机制操作。
获取该类的构造器对象及使用该对象调用该类的构造器
取得一个类的指定参数构造:public Constructor<T> getConstructor(Class<?>... parameterTypes)
parameterTypes:方法参数的Class对象
public static void main(String[] args) throws Exception { // 得到Computer类的Class对象 Class<?> computerClass = Class.forName("exercise5.Computer"); // 通过Computer的Class对象computerClass获取该类的第二个构造器对象 Constructor<?> cons = computerClass.getConstructor(String.class); // 使用该构造器对象创建实例 Computer com = (Computer) cons.newInstance("Acer"); }
几种获取构造器的方法
public Constructor<?>[] getConstructors() 获得所有公共构造方法
public Constructor<?>[] getDeclaredConstructors() 获得所有构造方法(包括非public方法)
public Constructor<T> getConstructor(Class<?>... parameterTypes) 获得单个公共构造方法
public Constructor<T> getDeclaredtConstructor(Class<?>... parameterTypes) 获得单个构造方法
由上述两个例子可知,类对象computerClass.newInstance() 与 构造器对象cons.newInstance("Acer"); 都可以创建实例。
类对象创建实例,只能调用public 无参的构造函数,相当于通过公共无参构造器对象创建实例。
获取该类的方法对象及使用该对象调用该类的方法
取得指定方法:public Method getMethod(String name, Class<?>... parameterTypes)
name:方法名
parameterTypes:方法参数的Class对象
public static void main(String[] args) throws Exception { // 得到Computer类的Class对象 Class<?> computerClass = Class.forName("exercise5.Computer"); // 创建Computer类的实例 Computer com = (Computer) computerClass.newInstance(); // 获取Computer类的setBrand()方法对象 Method setMet = computerClass.getMethod("setBrand", String.class); // 通过该方法对象,调用com中的setBrand()方法 setMet.invoke(com, "lenovo"); // 获取Computer类的getBrand()方法对象 Method getMet = computerClass.getMethod("getBrand"); // 通过该方法对象,调用com中getBrand()方法 System.out.println(getMet.invoke(com)); }
获取该类的属性(字段)对象及使用该对象调用该类的属性
取得指定的成员:public Field getDeclaredField(String name)
name:成员名字
public static void main(String[] args) throws Exception { // 得到Computer类的Class对象 Class<?> computerClass = Class.forName("exercise5.Computer"); // 创建Computer类的实例 Computer com = (Computer) computerClass.newInstance(); // 获取Computer类的brand字段对象 Field brandField = computerClass.getDeclaredField("brand"); // 解除封装 brandField.setAccessible(true); // 使用brandField对象设置com中brand的值 brandField.set(com, "samsung"); System.out.println(com.getBrand()); }
从类的开发要求而言,一直都强调类之中的属性必须封装,所以现在调用之前要想办法解除封装。
解除封装:public void setAccessible(boolean flag)
getField 可以获取public字段,包括该类所定义的public字段与其所继承的public字段(父类中的public字段、父类的父类中的public字段、...,但不包括Object中的public字段)。
getDeclaredField 可以获取该类本身所定义的字段,包括private、default、protected、public,但是不包括继承来的字段。
getMethod 与 getDeclaredMethod() 相同的道理。
总结:
反射作用于程序运行阶段,主要通过Class类实现,Class可以获得某个类的Class对象,
通过Class对象可以得到该类的所有信息(属性、构造器、方法),且可以创建该类的实例,调用该类的方法、构造器、属性。
posted on 2018-07-30 19:16 Deltadeblog 阅读(146) 评论(0) 编辑 收藏 举报