反射
反射
什么是反射?
我的理解是:正常加载一个类的时候,可以去new这个类,从而得到一个对象,在这些对象里面可以去获得这个类里面的所有公开的方法、字段、构造器等。但是反射就是在加载类的时候会通过Class这个类将对象进行反射,获取到这个对象的全类名,进而去操作这个类里面的所有方法、字段、构造器等。
Class对象
- 一个类在内存中只有一个Class对象
- 一个类被加载后,类的所有结构都被封装到一个Class对象当中
获取Class类的方式
//测试获取Class类的方式
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是:" + person.name);
//方式一:通过对象获取
Class c1 = person.getClass();
//方式二:通过类来获取
Class c2 = Student.class;
//方式三:通过全路径名来获取
Class c3 = Class.forName("com.kaung.reflection.Student");
System.out.println(c1 == c2);
System.out.println(c1 == c3);
System.out.println(c2 == c3);
//方式四:基本内置类型都有一个TYPE,也可以获取Class
Class c4 = Integer.TYPE;
System.out.println(c4.hashCode());
//获取父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
通过反射获得类的信息
User类
//实体类,也可以叫做 pojo或entity
public class User{
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
获取信息类
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//获得类的信息
public class Test04 {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
User user = new User();
Class c1 = user.getClass();
//获取类的名字
System.out.println(c1.getName()); //包名 + 类名
System.out.println(c1.getSimpleName()); //类名
System.out.println("==============");
//获得类的属性
Field[] fields = c1.getFields(); //只能找到public的属性
for (Field field : fields) {
System.out.println(field);
}
System.out.println("==============");
fields = c1.getDeclaredFields(); //可以找到所有的属性
for (Field field : fields) {
System.out.println(field);
}
System.out.println("==============");
//查找指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
System.out.println("==============");
//获得类的方法
Method[] methods = c1.getMethods(); //获得本类以及父类的所有public方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==============");
methods = c1.getDeclaredMethods(); //获得本类的所有方法,并没有获得父类的方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==============");
//获得指定方法
//这边为什么需要指定参数?因为方法可能重载,所以需要传入的参数类型来判断需要调用哪个方法
Method getName = c1.getDeclaredMethod("getName", null);
System.out.println(getName);
Method setName = c1.getDeclaredMethod("setName", String.class);
System.out.println(setName);
System.out.println("==============");
//获得构造器
Constructor[] constructors = c1.getConstructors(); //获得所有的public构造器
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors(); //获得所有的构造器
for (Constructor constructor : constructors) {
System.out.println("$" + constructor);
}
//获得指定构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("指定的" + declaredConstructor);
}
}
通过反射操作属性、方法等
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
//动态的创建对象,通过反射
public class Test05 {
public static void main(String[] args) throws Exception {
//获得class对象
Class c1 = Class.forName("com.kaung.reflection.User");
//通过class对象构造一个user对象
User user = (User) c1.newInstance(); //本质是调用了无参构造器 User user = new User();
System.out.println(user);
//通过构造器创建一个对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) constructor.newInstance("咯咯", 007, 18);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
//1.通过反射获取方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//2.调用invoke方法激活setName,传入的参数为(对象,参数),也就是给对象的setName方法传入参数
setName.invoke(user3,"哒哒");
System.out.println(user3);
//通过反射操作属性
User user4 = (User) c1.newInstance();
//1.获取指定要操作的属性
Field name = c1.getDeclaredField("name");
//2.调用set方法设值,也就是给user4这个对象的name赋值为憨憨
//但是因为name是私有属性,不能直接操作,需要关闭安全检测,使用属性或者方法的 setAccessible(true)
name.setAccessible(true);
name.set(user4,"憨憨");
System.out.println(user4.getName());
}
}
通过反射操作注解
import java.lang.annotation.*;
import java.lang.reflect.Field;
//练习反射操作注解
public class Test07 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.kaung.reflection.Student2");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value值
TableName tableName = (TableName) c1.getAnnotation(TableName.class);
String value = tableName.value();
System.out.println(value);
//获得类指定的注解
Field name = c1.getDeclaredField("name");
FieldName fieldName = name.getAnnotation(FieldName.class);
String s = fieldName.columnName();
System.out.println(s);
}
}
@TableName("db_student")
class Student2{
@FieldName(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldName(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldName(columnName = "db_name",type = "varchar",length = 3)
private String name;
public Student2() {
}
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldName{
String columnName();
String type();
int length();
}

浙公网安备 33010602011771号