反射使用详解

反射使用详解

一、反射(主要用于框架的开发)

反射:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)

1、反射第一步:加载类,获取类的字节码:Class对象

获取Class对象的三种方式

Class c1 = 类名.class

调用Class提供方法:public static Class forName(String package);

Object提供的方法:public Class getClass(); Class c3 = 对象.getClass();

public class Test { public static void main(String[] args) throws ClassNotFoundException { Class s1 = Student.class; System.out.println(s1.getName()); //全类名 System.out.println(s1.getSimpleName()); // 简名 Class s2 = Class.forName("com.itrus.study.reflect.Student"); System.out.println(s1 == s2); Student student = new Student(); Class s3 = student.getClass(); System.out.println(s1 == s3); } }

2.获取类的构造器

public class Student { private String name; private Student() { } public Student(String name) { this.name = name; } }

1.获取public修饰的所有构造器

public class Test2 { public static void main(String[] args) { Class s = Student.class; Constructor[] constructors = s.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor.getName() + "->" + constructor.getParameterCount()); } } }

2.获取所有构造器

public class Test2 { public static void main(String[] args) { Class s = Student.class; Constructor[] constructors = s.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor.getName() + "->" + constructor.getParameterCount()); } } }

3.获取一个指定的public修饰的构造器

import java.lang.reflect.Constructor; public class Test2 { public static void main(String[] args) throws NoSuchMethodException { Class s = Student.class; Constructor constructor = s.getConstructor(String.class, int.class); System.out.println(constructor.getName() + "->" + constructor.getParameterCount()); } }

4.获取一个指定的任意构造器

public class Test2 { public static void main(String[] args) throws NoSuchMethodException { Class s = Student.class; Constructor constructor = s.getDeclaredConstructor(); System.out.println(constructor.getName() + "->" + constructor.getParameterCount()); } }

3.获取类构造器的作用

使用newInstance直接创建对象,可能会因为检查访问权限而导致创建失败,但是如果把accessible设置为true,即使是private修饰的私有构造方法也可以构造对象

public class Student { private String name; private int age; private Student() { System.out.println("初始化了一个对象"); } public Student(String name, int age) { this.name = name; this.age = age; } public Student(String name) { this.name = name; } }
public class Test2 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class s = Student.class; Constructor constructor = s.getDeclaredConstructor(); System.out.println(constructor.getName() + "->" + constructor.getParameterCount()); // cannot access a member of class com.itrus.study.reflect.Student with modifiers "private" //Student student = (Student) constructor.newInstance(); constructor.setAccessible(true); Student student = (Student) constructor.newInstance(); } }

4.获取类的成员变量

package com.itrus.study.reflect; public class Student { private static int a; public static final String str = "你好世界"; private String name; private int age; private Student() { System.out.println("初始化了一个对象"); } public Student(String name, int age) { this.name = name; this.age = age; } public Student(String name) { this.name = name; } }
public class Test3 { public static void main(String[] args) throws NoSuchFieldException { Class student = Student.class; //获取public修饰的所有属性 Field[] fields = student.getFields(); for(Field field : fields) { System.out.println(field.getName() + " ---> " + field.getType()); } System.out.println("================="); //获取所有属性 fields = student.getDeclaredFields(); for(Field field : fields) { System.out.println(field.getName() + " ---> " + field.getType()); } System.out.println("================="); //获取指定public成员变量 Field fstr = student.getField("str"); System.out.println(fstr.getName() + " ---> " + fstr.getType()); System.out.println("================="); //获取指定成员变量 Field fage = student.getDeclaredField("age"); System.out.println(fage.getName() + " ---> " + fage.getType()); System.out.println("================="); } }

5.获取类成员变量的作用

//给成员变量赋值 Student s = new Student(); fage.setAccessible(true); fage.set(s, 20); System.out.println(s); int age = (int) fage.get(s); System.out.println(age);

6.获取成员方法

getMethods会获取当前类和所有父类的public修饰的方法,而getDeclaredMethods方法是获取当前类的所有方法

package com.itrus.study.reflect; public class Student { private static int a; public static final String str = "你好世界"; private String name; private int age; public Student() { System.out.println("初始化了一个对象"); } private String eat() { return "吃饭"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Student(String name, int age) { this.name = name; this.age = age; } public Student(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
public class Test4 { public static void main(String[] args) throws NoSuchMethodException { Class c = Student.class; Method[] methods = c.getMethods(); for (Method method : methods) { System.out.println(method.getName() + " ---> " + method.getParameterCount() + " ---> " + method.getReturnType()); } System.out.println("======="); methods = c.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName() + " ---> " + method.getParameterCount() + " ---> " + method.getReturnType()); } System.out.println("======="); Method method = c.getMethod("setName", String.class); System.out.println(method.getName() + " ---> " + method.getParameterCount() + " ---> " + method.getReturnType()); System.out.println("======="); method = c.getDeclaredMethod("setName", String.class); System.out.println(method.getName() + " ---> " + method.getParameterCount() + " ---> " + method.getReturnType()); System.out.println("======="); } }

7.获取成员方法的作用

Student s = new Student(); method.setAccessible(true); method.invoke(s, "张三"); System.out.println(s.getName());