反射(Reflection)java语言反射机制
java语言反射机制:是一种运行时机制
在运行时,通过反射机制可以(动态)的获得和该类型相关的各种信息
这里说的【类型】包括8中基本数据类型和3中引用数据类型
1.Class类型(java.lang.Class类【反射机制的入口】)
Class是对java中所有类型的抽象。即一个Class类型对象可以表示出java任意一个类型
每种类型在加载内存后,内存中都会产生一个与之对应的Class类型对象(有且只有一个)用来表示该类型
假设我们现在有一个Student类
public class Student {
private long id;
private String name;
private int age;
public Student() {}
public Student(long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
(1).表示基本数据类型
Class c = int.calss;
//isPrimitive 表示是不是基本类型
System.out.println(c.isPrimitive()) //输出true
System.out.println(c.getName()); //输出int
(2).表示类类型
Student s = new Student();
Class c1 = s.getClass();
Class c2 = Student.class;
System.out.println(c1 == c2); //true
(3).表示接口类型
Action a = new Student();
Class c1 = a.getClass(); //c1表示Student类型
Class c2 = Action.class; //c2表示Action类型
System.out.println(c1 == c2); //false
System.out.println(c2.isInterface()); //true
(4).表示数组类型
int[] a = new int[4];
Class c1 = a.getClass();
Class c2 = int[].class;
System.out.println(c1 == c2); //true
Student[] a = new Student[4];
Class c1 = a.getClass();
Class c2 = Student[].class;
System.out.println(c1 == c2);//true
2.获取一个类类型的Class对象的三种方式
(1).使用对象调用getClass方法获得
Student s = new Student();
Class c = s.getClass();
(2).使用类名获得
Class c = Student.class;
(3).使用Class类中的forName方法获得(最常用)
//这种方法很灵活,只需一个String类型参数即可
//而String类型的数据改变起来很容易
//注意该方法是会抛出异常的
Class c = Class.forName("Student类的全限定名");
3.使用Class类型对象获得类中的信息
(1).获得该类中所有包的信息
Student s = new Student();
Class c = s.getClass();
System.out.println(c.getPackage().getName());
(2).获得该类中的修饰符信息
Student s = new Student();
Class c = s.getClass();
System.out.println(c.getModifiers()); //输出int类型的值,如果有多个修饰符,则int值相加
(3).获得该类的名字
Student s = new Student();
Class c = s.getClass();
System.out.println(c.getName());
(4).获得该类的父类的Class对象
Student s = new Student();
Class c = s.getClass();
//superclass表示其父类型的Class对象
Class superclass = c.getSuperclass();
System.out.println(superclass.getName());
(5).获得该类实现的接口的Class对象
Student s = new Student();
Class c = s.getClass();
Class[] interfaces = c.getInterfaces();
for(Class clazz:interfaces){
System.out.println(clazz.getName());
}
(6).获得该类中所有的属性
Student s = new Student();
Class c = s.getClass();
Field[] declaredFields = c.getDeclaredFields();
for(Field f:declaredFields){
System.out.println(f.getModifiers());
System.out.println(f.getType().getName());
System.out.println(f.getName());
}
注意:
getDeclaredFields(): 返回类中声明的属性,包括私有的
getFields() : 只返回类中public修饰的属性,包括继承的
(7).获得该类中的所有方法
Student s = new Student();
Class c = s.getClass();
Method[] declaredMethods = c.getDeclaredMethods(); //类中自己写的方法
for(Method m:declaredMethods){
System.out.println(m.getModifiers());
System.out.println(m.getReturnType().getName());
System.out.println(m.getName());
}
注意:
getDeclaredMethods(): 返回类中声明的方法,包括私有的
getMethods(): 只返回类中public修饰的方法,包括继承的
(8).获得该类中的所有构造器(有参,无参)
Student s = new Student();
Class c = s.getClass();
Constructor[] declaredConstructors = c.getDeclaredConstructors();
for(Constructor con:declaredConstructors){
System.out.println(con.getModifiers());
System.out.println(con.getName());
}
注意:
getDeclaredConstructors(): 返回类中所有构造器
getConstructors(): 只返回类中public修饰的构造器
4.反射的常规操作
例如有Teacher这个类
public class Teacher {
private long id;
private String name;
public static int age = 22;
public Teacher() {
super();
}
public Teacher(long id, String name) {
super();
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void test(){
System.out.println("hello");
}
public String sayHello(String name){
return "Hi"+name;
}
public static void run(){
System.out.println("run...........");
}
@Override
public String toString() {
return "Teacher [id=" + id + ", name=" + name + "]";
}
}
(1).使用反射的方式调用构造器创建类的对象
默认方式:必须调用无参构造器
通用方式:获得构造器对象,并调用该构造器
例如:获得无参构造器并调用创建对象
Class c = Teacher.class;
Constructor constructor = c.getConstructor();
Teacher o = (Teacher)constructor.newInstance();
System.out.println(o);
例如:获得有参构造器并调用创建对象
Class c = Student.class;
Constructor constructor =c.getConstructor(long.class,String.class);
Teacher o = (Teacher)constructor.newInstance(2021L,"张三");
System.out.println(o);
(2).使用反射的方式访问对象中的属性
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
Class<?> c = Teacher.class;
Teacher t = new Teacher(2021L,"张三");
//类中的所有属性
Field[] declaredFields = c.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.getName());
System.out.println(field.getModifiers());//修饰符,每个修饰符对应一个int值
// System.out.println(Modifier.isPublic(field.getModifiers()));
// System.out.println(Modifier.isPrivate(field.getModifiers()));
// System.out.println(Modifier.isStatic(field.getModifiers()));
System.out.println(field.getType());
if (Modifier.isPrivate(field.getModifiers())) {
field.setAccessible(true);
}
Object vObject = field.get(t);
System.out.println("------------------");
System.out.println(vObject);
if(Modifier.isStatic(field.getModifiers())){
System.out.println(field .getName() +" = "+field .get(null));
}else{
System.out.println(field .getName() +" = "+field .get(t));
}
}
运行截图
(3).使用反射的方式调用对象中的方法
public static void main(String[] args) throws Exception{
Class<?> c = Teacher.class;
Teacher t = new Teacher();
Method method1 = c.getMethod("setName", String.class);
// method1 表示Teacher中的setName方法
t.setName("zhangsan");
//反射中的所有方法都用invoke调用 invoke(对象)
method1.invoke(t, "zhangsan");
Method method2 = c.getMethod("getName");
String name = (String)method2 .invoke(t);
System.out.println("name = "+name);
//调用无参方法
System.out.println("-----------------------------");
String methodName1 = "test";
Method method3 = c.getMethod(methodName1);
Object v = method3.invoke(t);
System.out.println(v);
//调用有参方法
System.out.println("------------------------------");
String methodName2 = "sayHello";
Class<?>[] argsClass = {String.class};
Object[] argsObj = {"zhangsan"};
Method method4 = c.getMethod(methodName2,argsClass);
Object rv = method4.invoke(t, argsObj);
System.out.println(rv);
//调用静态方法 不需要对象
System.out.println("------------------------------");
Method method5 = c.getMethod("run");
method5 .invoke(null);
}
输出截图
注意:
常用的方法
Student 是类类型,输出全是false,
Student s = new Student();
System.out.println(s.isprimitive()); //是不是基本类型
System.out.println(s.isInterface()); //是不是接口
System.out.println(s.Array()); //是不是数组类型
System.out.println(s.isAnnotatopn()); //是不是注解 @..
System.out.println(s.isEnum()); //是不是枚举类型