1、反射:加载类,反射出类的各个组成部门 构造器 属性 方法
2、具体操作
1)准备一个类
Person
package com.gxa.pojo;
public class Person {
//私有的属性值
private Integer age = 1;
//公开的属性值
public String name = "强哥";
//公开的静态属性值
public static String address = "火星";
//无参构造方法
public Person() {
}
//私有的有参构造方法
private Person(String name) {
this.name = name;
}
//公开有参构造方法
public Person(Integer age, String name) {
this.age = age;
this.name = name;
}
//公开无参方法
public void aa() {
System.out.println("林老好");
}
//私有有参方法
private void bb(String name) {
System.out.println(name + "好");
}
//公开静态有参方法
public static void bb(String name, Integer age) {
System.out.println(name + "好," + age);
}
}
2)反射构造器
package com.gxa.reflex;
import com.gxa.pojo.Person;
import org.junit.Test;
import java.lang.reflect.Constructor;
//通过反射构造器创建对象
public class ReflexConstructor {
/**
* 通过无参构造器创建对象
*
* @throws Exception
*/
@Test
public void test1() throws Exception {
//1.加载类
Class clazz = Person.class;
//2.获取构造函数
//无参构造器 Constructor封装了构造器的相关信息
Constructor constructor = clazz.getConstructor(null);
//3.创建对象
Object obj = constructor.newInstance(null);
System.out.println(obj);//com.gxa.pojo.Person@5d6f64b1
}
/**
* 私有构造器有参
*
* @throws Exception
*/
@Test
public void test2() throws Exception {
//1.加载类
Class clazz = Person.class;
//2.获取构造函数
//使用Declared暴力获取成员,如果构造器有参数,则传递参数的字节码就行
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//因为是私有构造方法,需要开启访问权限
constructor.setAccessible(true);
//3.创建对象
Person person = (Person) constructor.newInstance("强哥2号");
System.out.println(person.name);//强哥2号
}
/**
* 有参构造器
*
* @throws Exception
*/
@Test
public void test3() throws Exception {
//1.加载类
Class clazz = Person.class;
//2.反射出构造器
Constructor constructor = clazz.getConstructor(Integer.class, String.class);
//3.创建对象
Object obj = constructor.newInstance(10, "aaa");
System.out.println(obj);//com.gxa.pojo.Person@5d6f64b1
}
/**
* 简化版的通过无参构造器创建对象
*/
@Test
public void test4() throws Exception {
// 1.加载类
Class clazz = Person.class;
//使用无参构造器
Object obj = clazz.newInstance();
System.out.println(obj);//com.gxa.pojo.Person@5d6f64b1
}
}
3)反射属性
package com.gxa.reflex;
import com.gxa.pojo.Person;
import org.junit.Test;
import java.lang.reflect.Field;
/**
* 反射属性
*/
public class ReflexField {
/**
* 获取私有属性的值
*
* @throws Exception
*/
@Test
public void test1() throws Exception {
//1.反射属性
Class clazz = Person.class;
//2.获取属性——参数为类的属性名,因为是私有属性,所以使用getDeclaredField
Field field = clazz.getDeclaredField("age");
//开启访问权限
field.setAccessible(true);
Person person = new Person();
//3.获取指定对象这个属性的值
Object value = field.get(person);
System.out.println(value);//1
}
/**
* 获取公开属性的值
*
* @throws Exception
*/
@Test
public void test2() throws Exception {
// 1.反射属性
Class clazz = Person.class;
// 2.获取属性——因为不是私有属性,所以直接getField即可
Field field = clazz.getField("name");
//声明,属性所在的类
Person person = new Person();
// 3.获取指定对象这个属性的值
Object value = field.get(person);
System.out.println(value);//强哥
//可以给该属性进行重新赋值
field.set(person, "强强哥");
value = field.get(person);
System.out.println(value);//强强哥
}
/**
* 公开的静态属性值
*/
@Test
public void test3() throws Exception {
// 1.反射属性
Class clazz = Person.class;
// 2.获取属性
Field field = clazz.getField("address");
// Field field = clazz.getDeclaredField("address");
// 3.获取指定对象这个属性的值
Object value = field.get(null);
System.out.println(value);//火星
}
}
4)反射方法
package com.gxa.reflex;
import com.gxa.pojo.Person;
import org.junit.Test;
import java.lang.reflect.Method;
/**
* 反射方法
*/
public class ReflexMethod {
/**
* 公开无参方法
*
* @throws Exception
*/
@Test
public void test1() throws Exception {
//1.加载类
Class clazz = Person.class;
//2.反射获取方法——方法没有参数,则写null即可
Method method = clazz.getMethod("aa", null);
Person person = new Person();
//3.执行方法
method.invoke(person, null);//林老好
}
/**
* 私有有参方法
*
* @throws Exception
*/
@Test
public void test2() throws Exception {
//1.加载类
Class clazz = Person.class;
//2.反射获取方法——方法有参数,写参数的class对象即可,有几个参数就写几个
Method method = clazz.getDeclaredMethod("bb", String.class);
Person person = new Person();
method.setAccessible(true);
//3.执行方法
method.invoke(person, "韩老师");//韩老师好
}
/**
* 公开静态有参方法
*/
@Test
public void test3() throws Exception {
//1.加载类
Class clazz = Person.class;
//2.反射获取方法
Method method = clazz.getMethod("bb", String.class, Integer.class);
//3.执行方法
method.invoke(null, "韩老师", 12);//韩老师好,12
}
}
3、总结
1)反射的第一步是加载类,将磁盘上的类文件通过类加载器加载到内存里的方法区(加载方法)
2)加载类后,通过反射获得类的组成部分;可以反射出构造器,获得类得对象;如果是反射私有构造器,则需要De(开头的) 获取构造器,然后开启访问权限就可以创建对象。
反射方法:getMethod;反射属性是getFiled
使用最多的是反射出无参构造器