Java 基础 - 反射
文章目录
- Java 基础 - 反射
- 1 什么是类对象
- 2 获取类对象的方法
- 3 反射通用操作【`重点`】
- 3.1 常见方法
- 3.2 通用操作
- 4 内省
1 什么是类对象
类的对象:基于某个类 new 出来的对象,也称为实例对象。
类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法、包) ,每个类只有一个类对象。
反射:把Java类中的各种成分映射成单独的Java对象进行操作。
如图:
注意:每个类加载到内存都会生成一个唯一的类对象。
2 获取类对象的方法
通过类的对象,获取类对象。
Student s = new Student();
Class c = s.getClass();
通过类名获取类对象。
Class c = 类名.class;
通过静态方法获取类对象。
Class c=Class.forName(“包名.类名”);
代码演示:
Student:
package StageOne.day24.demo1;import java.io.Serializable;/*** @author 胡昊龙* @version 1.0* @description: TODO* @date 2024/1/19 10:13*/
public class Student implements Serializable{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;}//普通方法public void show() {System.out.println("学生信息: 姓名 "+this.name+" 年龄 "+this.age);}public void show(String address) {System.out.println("学生地址: "+address);}public String getInfo() {return this.name+"..."+this.age;}public static void method1() {System.out.println("静态方法");}private void method2() {System.out.println("私有方法");}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
TestReflect:
package StageOne.day24.demo1;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** @author 胡昊龙* @version 1.0* @description: TODO* @date 2024/1/19 10:20*/
public class TestReflect {public static void main(String[] args) throws Exception{reflect1();}//反射操作1: 获取类对象public static void reflect1() throws Exception {//方式1 通过类的实例获取Student student = new Student();Class<?> aClass = student.getClass();System.out.println(aClass.hashCode());//方式2 通过class获取Class<?> class2 = Student.class;System.out.println(class2.hashCode());//方式3 通过Class.forName(类的全名称)获取(耦合性低,灵活性高)Class<?> class3 = Class.forName("StageOne.day24.demo1.Student");System.out.println(class3.hashCode());}
}
3 反射通用操作【重点
】
3.1 常见方法
方法名 | 描述 |
---|---|
public String getName() | 获取类的完全名称 |
public Package getPackage() | 获取包信息 |
public Class<? super T> getSuperclass() | 获取父类 |
public Class<?>[] getInterfaces() | 获取实现父接口 |
public Field[] getFields() | 获取字段信息 |
public Method[] getMethods() | 获取方法信息 |
public Constructor<?>[] getConstructors() | 获取构造方法 |
public T newInstance() | 反射创建对象 |
3.2 通用操作
反射通用操作:使用反射机制获取类对象,并使用Class对象的方法获取表示类成员的各种对象(比如Constructor、Method、Field等),实现反射各种应用。
案例演示:反射操作。
Person类:
public class Person implements Serializable,Cloneable{//姓名private String name;//年龄private int age;public Person() {System.out.println("无参构造执行了...");}public Person(String name, int age) {super();this.name = name;this.age = age;System.out.println("带参构造方法执行了...");}//吃public void eat() {System.out.println(name+"正在吃东西......");}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}//带参的方法public void eat(String food) {System.out.println(name+"开始吃...."+food);}//私有的方法private void privateMethod() {System.out.println("这是一个私有方法");}//静态方法public static void staticMethod() {System.out.println("这是一个静态方法");}
}
TestPerson类:
public class TestPerson {public static void main(String[] args) throws Exception {//调用测试以下方法//代码略}//获取类对象的三种方式public static void getClazz() throws Exception {//1使用对象获取类对象Person zhangsan=new Person();Class<?> class1=zhangsan.getClass();System.out.println(class1.hashCode());//2使用类名.class属性Class<?> class2=Person.class;System.out.println(class2.hashCode());//3使用Class的静态方法[推荐使用]Class<?> class3=Class.forName("com.qf.chap17_1.Person");System.out.println(class3.hashCode());}//1 使用反射获取类的名字、包名、父类、接口public static void reflectOpe1() throws Exception {//(1)获取类对象 PersonClass<?> class1=Class.forName("com.qf.chap17_1.Person");//getName();System.out.println(class1.getName());//getPackage();System.out.println(class1.getPackage().getName());//getSuperClass();System.out.println(class1.getSuperclass().getName());//getInterfaces();Class<?>[] classes=class1.getInterfaces();System.out.println(Arrays.toString(classes));System.out.println(class1.getSimpleName());System.out.println(class1.getTypeName());}//2使用反射获取类的构造方法,创建对象public static void reflectOpe2() throws Exception{//(1)获取类的类对象Class<?> class1=Class.forName("com.qf.chap17_1.Person");//(2)获取类的构造方法 ConstructorConstructor<?>[] cons=class1.getConstructors();for (Constructor<?> con : cons) {System.out.println(con.toString());}//(3)获取类中无参构造Constructor<?> con=class1.getConstructor();Person zhangsan=(Person)con.newInstance();Person lisi=(Person)con.newInstance();System.out.println(zhangsan.toString());System.out.println(lisi.toString());//简便方法:类对象.newInstance();Person wangwu=(Person)class1.newInstance();System.out.println(wangwu.toString());//(4)获取类中带参构造方法Constructor<?> con2=class1.getConstructor(String.class,int.class);Person xiaoli=(Person)con2.newInstance("晓丽",20);System.out.println(xiaoli.toString());}//3使用反射获取类中的方法,并调用方法public static void reflectOpe3() throws Exception{//(1)获取类对象Class<?> class1=Class.forName("com.qf.chap17_1.Person");//(2)获取方法 Method对象//2.1getMethods() 获取公开的方法,包括从父类继承的方法//Method[] methods=class1.getMethods();//2.2getDeclaredMethods() 获取类中的所有方法,包括私有、默认、保护的 、不包含继承的方法Method[] methods=class1.getDeclaredMethods();for (Method method : methods) {System.out.println(method.toString());}//(3)获取单个方法//3.1eatMethod eatMethod=class1.getMethod("eat");//调用方法//正常调用方法 Person zhangsan=new Person(); zhangsan.eat();Person zhangsan=(Person)class1.newInstance();eatMethod.invoke(zhangsan);//zhangsan.eat();System.out.println("------------------");//3.2toStringMethod toStringMethod=class1.getMethod("toString");Object result=toStringMethod.invoke(zhangsan);System.out.println(result);System.out.println("-------------------");//3.3带参的eat Method eatMethod2=class1.getMethod("eat", String.class);eatMethod2.invoke(zhangsan, "鸡腿");//3.4获取私有方法Method privateMethod=class1.getDeclaredMethod("privateMethod");//设置访问权限无效privateMethod.setAccessible(true);privateMethod.invoke(zhangsan);//3.4获取静态方法Method staticMethod=class1.getMethod("staticMethod");//正常调用 Person.staticMethodstaticMethod.invoke(null);}//4使用反射实现一个可以调用任何对象方法的通用方法public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception {//1获取类对象Class<?> class1=obj.getClass();//2获取方法Method method=class1.getMethod(methodName, types);//3调用return method.invoke(obj, args);}//5使用反射获取类中的属性public static void reflectOpe4() throws Exception{//(1)获取类对象Class<?> class1=Class.forName("com.qf.chap17_1.Person");//(2)获取属性(字段) 公开的字段,父类继承的字段//Field[] fields=class1.getFields(); //getDeclaredFields()获取所有的属性,包括私有,默认 ,包含,Field[] fields=class1.getDeclaredFields();System.out.println(fields.length);for (Field field : fields) {System.out.println(field.toString());}//(3)获取name属性Field namefield=class1.getDeclaredField("name");namefield.setAccessible(true);//(4)赋值 正常调用 Person zhangsan=new Person(); zhangsan.name="张三";Person zhangsan=(Person)class1.newInstance();namefield.set(zhangsan, "张三"); //zhangsan.name="张三";//(5) 获取值System.out.println(namefield.get(zhangsan));// zhangsan.name}
}
4 内省
内省:采用反射实现对属性进行操作的一种机制。
- PropertyDescriptor:属性描述符 ,代表一个属性
- BeanInfo:实体类信息 ,包含类的信息
- Introspector:工具类
代码演示:
Dog:
package StageOne.day24.demo2;/*** @author 胡昊龙* @version 1.0* @description: TODO* @date 2024/1/19 15:57*/
public class Dog {private String breed;private int age;public Dog() {}public Dog(String breed, int age) {this.breed = breed;this.age = age;}public String getBreed() {return breed;}public void setBreed(String breed) {this.breed = breed;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Dog{" +"breed='" + breed + '\'' +", age=" + age +'}';}
}
Test:
package StageOne.day24.demo2;import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;/*** @author 胡昊龙* @version 1.0* @description: TODO* @date 2024/1/19 15:57*/
public class Test {public static void main(String[] args) throws Exception {Class<?> aClass = Class.forName("StageOne.day24.demo2.Dog");Dog dog = (Dog) aClass.newInstance();PropertyDescriptor breed = new PropertyDescriptor("breed", aClass);Method setBreed = breed.getWriteMethod();Method getBreed = breed.getReadMethod();PropertyDescriptor age = new PropertyDescriptor("age", aClass);Method setAge = age.getWriteMethod();setBreed.invoke(dog,"二哈");setAge.invoke(dog,1);System.out.println(dog);//BeanInfo类信息: 封装了 类的所有属性/*内省内容中的属性含义:如果类中有getXxx(); 或 setXxx(); 或 isXxxv(); 方法则认为类中包含Xxx属性*/BeanInfo beanInfo = Introspector.getBeanInfo(aClass);PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();for (PropertyDescriptor pd : pds) {System.out.println(pd.getName());}}
}