反射机制
什么是反射呢?我大概的理解就是让对象认识到自身的结构。
也就是可以在运行期间可以获得对象的类型、方法、属性等。
获取对象类型
1.Object.getClass()//返回对象的关键字、包名、类名
2.Class.forName(“包名.类名”)//返回对象的关键字、包名、类名
3.类名.class//返回对象的关键字、包名、类名
下面以Student类为例:
package org.xupt.blogs;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出结果;
package org.xupt.blogs;
public class Test {
public static void main(String[] args) {
//1.Object.getClass()//返回对象的关键字、包名、类名
System.out.println(new Student().getClass());
//2.Class.forName("包名.类名")//返回对象的关键字、包名、类名
try {
System.out.println(Class.forName("org.xupt.blogs.Student"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//3.类名.class//返回对象的关键字、包名、类名
System.out.println(Student.class);
}
}
这些类型信息在Java虚拟机中仍然表现为一个对象,而且只存在一份
类对象的功能
1.用反射方式创建对象
一般方式: new 类名();
反射方式:类对象.newInstance();//创建一个新的实例
要求:
1.对象必须拥有无参构造器
否则会出现异常。
2.构造方法不能私有
同样的以Student为例
package org.xupt.blogs;
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.toString());
Student student1 = null;
try {
student1 = Student.class.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println(student1.toString());
}
}
2.获取方法信息
1.类对象.getMethods();//获取所有public方法,包括继承返回一个Method数组
2.类对象.getDeclareMethods();//获取本类中的所有方法,但不包括继承的方法
3.类对象.getMethod(“方法名”)//找公共方法,包括继承
4.类对象.getDeclareMethod(“方法名”)//找本类方法不包括继承
package org.xupt.blogs;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
//1.类对象.getMethods();//获取所有public方法,包括继承返回一个Method数组
Method[] methods = Student.class.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("********************");
//2.类对象.getDeclareMethods();//获取本类中的所有方法,但不包括继承的方法
Method[] declaredMethods = Student.class.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println("********************");
//3.类对象.getMethod("方法名")//找公共方法,包括继承
Method equals = Student.class.getMethod("equals", Object.class);
System.out.println(equals);
System.out.println("********************");
//4.类对象.getDeclareMethod("方法名")//找本类方法不包括继承
Method setName = Student.class.getDeclaredMethod("setName", String.class);
System.out.println(setName);
}
}
3.获取属性信息
1.getFields();//获取公共属性,和继承的属性
2.getDeclaredFields();//获取所有属性
3.getField(“属性名”);//获取指定的公共属性和继承属性
4.getDeclaredField(“属性名”);//获取指定属性
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException {
Constructor<?>[] constructors = Student.class.getConstructors();
System.out.println(constructors);
Constructor<?>[] declaredConstructors = Student.class.getDeclaredConstructors();
System.out.println(declaredConstructors);
}
}
反射调用方法
1.正常方式:对象.方法(参数)
2.反射方式:方法.invoke(对象,参数)
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Student student = new Student();
Method getName = student.getClass().getMethod("getName");
System.out.println(getName.invoke(student));
}
}
缺点:
1.编程复杂度高
2.效率低
优点:
1.可以调用私有的方法,突破正常方法限制
2.经常在开源框架中使用