什么式反射:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
将类的各个组成部分封装为其他对象。
- 将属性封装成Field[]对象。
- 将构造方法封装成Constuctor[]对象
- 将成员方法封装成Method[]对象
获取Class对象的方式:
public class Person {
private String name="kp";
private int age;
public String a;
protected String b;
public String c;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private void eat(){
System.out.println("eat.......");
}
public void eat(String food){
System.out.println("eat"+food+"......");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
- Class.forName("全类名") 将字节码文件加载进内存。
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cls1 = Class.forName("com.kpwang.reflect.domain.Person");
System.out.println(cls1);//class com.kpwang.reflect.domain.Person
}
}
- 类名.class :通过类名的属性class获取
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
Class<Person> cls2 = Person.class;
System.out.println(cls2);//class com.kpwang.reflect.domain.Person
}
}
- 对象.getclass() :通过对象getClass方法获取
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
Person person=new Person();
Class<? extends Person> cls3 = person.getClass();
System.out.println(cls3);//class com.kpwang.reflect.domain.Person
}
}
同一个字节码文件(*.class)在一次程序运行过程中只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cls1 = Class.forName("com.kpwang.reflect.domain.Person");
System.out.println(cls1);
Class<Person> cls2 = Person.class;
System.out.println(cls2);
Person person=new Person();
Class<? extends Person> cls3 = person.getClass();
System.out.println(cls3);
System.out.println(cls1==cls2);//true
System.out.println(cls1==cls3);//true
System.out.println(cls2==cls2);//true
}
}
将属性封装成Field[]对象中
- getFields() 方法获取所有public修饰的成员变量
public class ReflectDemo2 {
public static void main(String[] args) {
//获取Person的Class对象
Class<Person> personClass = Person.class;
//获取成员变量
Field[] fields = personClass.getFields();//获取所有public修饰的成员变量
for (Field field : fields) {
System.out.println(field);
}
}
}
- getField("属性名") 方法获取指定public修饰的属性
public class ReflectDemo2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//获取Person的Class对象
Class<Person> personClass = Person.class;
Field a = personClass.getField("a");//获取指定public修饰的成员变量
System.out.println(a);
Person person=new Person();
Object value = a.get(person);
System.out.println(value);
a.set(person,"123");//给指定属性赋值
System.out.println(person);
}
}
- getDeclaredFields() 获取所有修饰符修饰的属性
public class ReflectDemo2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//获取Person的Class对象
Class<Person> personClass = Person.class;
Field[] declaredFields = personClass.getDeclaredFields();//获取所有修饰符修饰的属性
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
}
}
- getDeclaredField("属性名") 方法获取指定的属性
public class ReflectDemo2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//获取Person的Class对象
Class<Person> personClass = Person.class;
Field name = personClass.getDeclaredField("name");
Person person=new Person();
//忽略访问权限修饰符的安全检查
name.setAccessible(true);//暴露反射
Object value = name.get(person);
System.out.println(value);
}
}
将构造方法封装成Constructor[]对象
- getConstructors() 获取所有构造方法
public class ReflectDemo3 {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
}
}
- getConstructor(构造方法的参数) 获取指定的构造方法
public class ReflectDemo3 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<Person> personClass = Person.class;
Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
Person person = constructor.newInstance("kpwang", 28);
System.out.println(person);
}
}
将成员方法封装到Method[]对象
- getMethods() 获取所有public修饰的方法(包括父类的方法)
public class ReflectDemo4 {
public static void main(String[] args) {
Class<Person> personClass = Person.class;
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
System.out.println(method.getName());
}
}
}
- getMothod(方法名,参数...) 获取指定的方法
public class ReflectDemo4 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<Person> personClass = Person.class;
Method eat_method = personClass.getMethod("eat", String.class);
Person person=new Person();
eat_method.invoke(person,"西瓜");
}
}
- getDeclaredMethods() 获取所有的方法(不包括父类)
public class ReflectDemo4 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<Person> personClass = Person.class;
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
}
- getDeclaredMethod(方法名,可变参数) 获取任意指定的方法
public class ReflectDemo4 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<Person> personClass = Person.class;
Method eat_method = personClass.getDeclaredMethod("eat");
Person person=new Person();
eat_method.setAccessible(true);//private需要暴力反射
eat_method.invoke(person);
}
}
使用反射的好处:
- 可以在程序运行过程中,操作这次对象。
- 可以解耦,提高程序的可扩展性(框架就是大量用到反射)