Java 反射
Class
Java 程序汇总的各个 Java 类属于同一类事物,描述这类事物的 Java 类名就是 Class。Class 表示在内存中存储的字节码。
(1)获取字节码的三种方式:
1 、类名.class。 例如:System.class;
2 、对象.getClass()。例如:new Date().getClass();
3、Class.forName("类名")。例如:Class.forName("java.util.Date");
(2)九个预定义 Class 实例对象:
boolean、byte、char、short、int、long、float、double、void
反射
反射就是把 Java 类中的各种成分映射成相应的 Java 类。例如,一个 Java 类中用一个 Class 类的对象来表示,一个类中的组成部分:成员变量、方法、构造方法、包等等信息也用一个个 Java 类来表示。表示 Java 类的 Class 类显然要提供一系列的方法,来过的其中的变量、方法、构造方法、修饰符、包等信息,这些信息就是用相应类的实例对象来表示,它们是 Field、Method、Constructor、Package 等等。一个类中的每个成员都可以用相应的反射 API 类的一个实例对象来表示,通过调用 Class 类的方法可以得到这些实例对象。
Constructor 类
一个 Constroctor 类代表一个字节码中的一个构造方法。
(1)得到一个类中的所有构造方法。例如:Constroctor[] constroctors = Class.forName("java.lang.String").getConstroctors();
(2)得到一个类中的某一个构造方法。例如:Constroctor constroctor = Class.forName("java.lang.String").getConstroctor(StringBuffer.class);
编程实例:用反射的方式创建一个类的实例对象
- public class A {
- public static void main(String[] args) throws Exception {
- // 1
- Constructor constructor = String.class
- .getConstructor(StringBuffer.class);
- String string = (String) constructor.newInstance(new StringBuffer(
- "DriverKing_斌"));
- System.out.println(string);
- // 2 这种方法是用字节码直接创建一个对象,用的是无参的构造函数
- String s = String.class.newInstance();
- }
- }
Field 类
Field 类代表某个类中的一个成员变量。因为 Field 是对应到对象上面的成员变量,所以 Field 代表的成员变量是具体的,不是抽象的,一个类的字节码对应着一个类的成员变量。
编程实例: 用反射的方式获取一个类中的成员变量,并修改变量的值
- public class A {
- public static void main(String[] args) throws Exception {
- B b = new B("DriverKing", "男", 23);
- Field fName = b.getClass().getDeclaredField("name"); // 通过B类的字节码根据字段名来获取字段对象,如果字段是对外公开的就用getField("");
- fName.setAccessible(true); // 因为 name字段是私有的,则必须设置setAccessible(true),才能进行修改,俗称暴力反射,哈哈,犀利
- String oldName = (String) fName.get(b); // 通过字段的对象来获取B的实例对象的字段值
- System.out.println("原名:" + oldName);
- fName.set(b, "DriverKing_斌");
- String newName = (String) fName.get(b);
- System.out.println("改后:" +newName);
- }
- }
- class B {
- public B(String name, String sex, int age) {
- this.setName(name);
- this.setSex(sex);
- this.setAge(age);
- }
- private String name;
- private String sex;
- private int age;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
运行结果:
原名:DriverKing
改后:DriverKing_斌
编程实例:将任意一个对象中的所有 String 类型的成员变量所对应的字符串内容中的 “b” 改为 “a”
- public class A {
- public static void main(String[] args) throws Exception {
- B b = new B("black", "hubei", "basketball", 23);
- System.out.println(b);
- Field[] fields = b.getClass().getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- if (fields[i].getType() == String.class) {
- fields[i].setAccessible(true);
- String oldString = (String) fields[i].get(b);
- String newString = oldString.replace('b', 'a');
- fields[i].set(b, newString);
- }
- }
- System.out.println(b);
- }
- }
- class B {
- private String name;
- private String address;
- private String hobby;
- private int age;
- public B(String name, String address, String hobby, int age) {
- super();
- this.name = name;
- this.address = address;
- this.hobby = hobby;
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- public String getHobby() {
- return hobby;
- }
- public void setHobby(String hobby) {
- this.hobby = hobby;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String toString() {
- return name + "," + address + "," + hobby + "," + age;
- }
- }
运行结果:
black,hubei,basketball,23
alack,huaei,aasketaall,23
Method 类
Method 类代表某个类中的一个成员方法。
(1)得到类中的某一个方法。例如:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
(2)调用方法。例:System.out.println(charAt.invoke(str,2)); // 普通方式调用: System.out.println(str.charAt(2));
编程实例:用反射的方式调用某个类的方法
- public class A {
- public static void main(String[] args) throws Exception {
- Method method = String.class.getMethod("charAt", int.class);
- System.out.println(method.invoke(new String("abc"), 2));
- }
- }
(3)用反射的方式执行某个类的 main 方法
- public class A {
- public static void main(String[] args) throws Exception {
- Method method = Class.forName(args[0]).getMethod("main", String[].class);// 获取 main方法
- // jdk1.4没有可变参,它会将字符串数组拆开作为参数来用,而拆开后,又不是字符串数组了,
- // 而是字符串了,所以jdk1.5为了兼容jdk1.4必须将字符串数组看为一个单独的对象,告诉编译器
- method.invoke(null, (Object) new String[] { "a", "b" });
- }
- }
- class B {
- public static void main(String[] args) {
- System.out.println(args[1]);
- }
- }
(4)对数组的反射
具有相同维数和元素类型的数组属于同一个类型,即代表有相同的 Class 实例对象。相同的维数,例如:二维数组就是数组的数组,也就是说数组里面存放的是引用类型的对象,它的字节码就不相同。所以 具有相同维数和元素类型的数组才是属于同一个类型。如果想获得一个数组的类型用:Class 实例对象的 getSuperClass()
编程实例:用反射的方法打印数组
- public class A {
- public static void main(String[] args) throws Exception {
- int[] array = {1,123,45,4,34,67};
- printObject(array);
- }
- private static void printObject(Object obj) {
- Class objClass = obj.getClass();
- if (objClass.isArray()) {
- int len = Array.getLength(obj);
- for (int i = 0; i < len; i++) {
- System.out.println(Array.get(obj, i));
- }
- } else
- System.out.println(obj);
- }
- }
(5)对集合的反射
编程实例:利用配置文件指定集合的类型,然后再用反射创建集合并打印集合
- public class A {
- public static void main(String[] args) throws Exception {
- InputStream in = new FileInputStream("config.properties");
- Properties properties = new Properties();
- properties.load(in);
- String className = properties.getProperty("className");
- Collection c = (Collection) Class.forName(className).newInstance();
- c.add("a");
- c.add("b");
- c.add("c");
- printObject(c);
- }
- private static void printObject(Object obj) {
- Class objClass = obj.getClass();
- if (objClass.isArray()) {
- int len = Array.getLength(obj);
- for (int i = 0; i < len; i++) {
- System.out.println(Array.get(obj, i));
- }
- } else
- System.out.println(obj);
- }
- }
(6)用类加载器加载配置文件
- public class A {
- public static void main(String[] args) throws Exception {
- // InputStream in = new FileInputStream("config.properties");
- //InputStream in = A.class.getClassLoader().getResourceAsStream("config.properties");
- InputStream in = A.class.getResourceAsStream("config.properties");
- Properties properties = new Properties();
- properties.load(in);
- String className = properties.getProperty("className");
- Collection c = (Collection) Class.forName(className).newInstance();
- c.add("a");
- c.add("b");
- c.add("c");
- printObject(c);
- }
- private static void printObject(Object obj) {
- Class objClass = obj.getClass();
- if (objClass.isArray()) {
- int len = Array.getLength(obj);
- for (int i = 0; i < len; i++) {
- System.out.println(Array.get(obj, i));
- }
- } else
- System.out.println(obj);
- }
- }