反射:是发生在程序运行期间的行为
java的一个动态机制
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
Properties pro=new Properties();
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
Person p=(Person) Class.forName(pro.getProperty("name")).newInstance();
p.work();
}
}
class Teacher extends Person{
@Override
public void work() {
System.out.println("讲javase");
}
}
- 创建对象的时候,拿到的都是当前类型Class对象的一个镜像|赋值体
- 在类加载的时候,会在内存中创建当前类型的一个Class对象,一个类的Class对象中存储这个类的所有信息(属性,方法,构造器...)
- 只要我们能够获取这个类型的Class对象,就可以对这个类做一切操作
- Class 类的实例表示正在运行的 Java 应用程序中的类和接口
对象.getClass()
类名.class
Class.forName("类的权限命名:包名+类名")
public class ReflectDemo02 {
public static void main(String[] args) throws ClassNotFoundException{
//1.对象.getClass()
Class cls1="哈哈".getClass();
Class cls2="呵呵".getClass();
System.out.println(cls1==cls2);
//2.类名.class
Class cls3=String.class;
System.out.println(cls1==cls3);
System.out.println(cls3);
//3.Class.forName("类的权限命名:包名+类名") 推荐
Class cls4=Class.forName("java.lang.String");
System.out.println(cls3==cls4);
//4.根据子类的Class对象获取父类的Class对象
Class cls5=cls4.getSuperclass();
System.out.println(cls5);
//5.获取基本数据类型的Class对象
Class base1=int.class;
System.out.println(base1);
Class cls6=Integer.class;
System.out.println(base1==cls6);
Class base2=Integer.TYPE; //得到对应的基本数据类型的class对象
System.out.println(base1==base2);
//常用的方法
//1.getName() 包名+类名
System.out.println(cls5.getName());
//2. Class[] getInterfaces()
Class[] arr=cls4.getInterfaces();
System.out.println(Arrays.toString(arr));
//3.String getSimpleName()
System.out.println(cls4.getSimpleName());
//4.boolean isInterface() isPrimitive()
System.out.println(Integer.class.isPrimitive());
System.out.println(Integer.TYPE.isPrimitive());
}
}
第一步:通过反射获取到类中的构造器
第二步:
方法一:根据构造器创建对象,构造器Constructor对象.newInstance(实参)方法
方法二:直接通过class类的newIntance()方法创建对象,方法没有参数 调用空构造
public class ReflectDemo03 {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//1.先获取类的Class
Class cls=Person.class;
//2.通过Class类中的方法,获取到Person类中的构造器
/*
* Constructor getConstructor(Class... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
*/
Constructor con1=cls.getConstructor(int.class,String.class,int.class);
Person p=(Person) con1.newInstance(01,"卢妹妹",18);
System.out.println(p);
Person p1=(Person)cls.newInstance();
System.out.println(p1);
/*
* Constructor getDeclaredConstructor(Class... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Constructor[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
*/
Constructor[] cons=cls.getDeclaredConstructors();
System.out.println(Arrays.toString(cons));
//私有的构造器
//放开权限
cons[1].setAccessible(true); //权限方法
Person p3=cons[1].newInstance(02,"卢双双");
cons[1].setAccessible(false);
System.out.println(p3);
}
}
public class ReflectDemo04 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
// testField(Person.class);
testMethod(Person.class);
}
操作方法 调用方法,能给方法传递实参
Method getDeclaredMethod(String name, Class... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Method[] getDeclaredMethods()返回
Method
对象的一个数组,这些对象反映此Class
对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method getMethod(String name, Class... parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共成员方法。
public static void testMethod(Class cls) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
Method[] arr=cls.getMethods();
Person p=(Person) cls.newInstance();
// Method me=cls.getDeclaredMethod("setAge", int.class);
Method me=cls.getDeclaredMethod("toString");
System.out.println(me.invoke(p));;
System.out.println(p.getAge());
// System.out.println(Arrays.toString(arr));
//静态方法执行的时候,invoke第一个参数可以为null
cls.getMethod("haha").invoke(null);
}
反射操作类中的字段 能设置值 能获取值
Field getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields()
返回Field
对象的一个数组,这些对象反映此Class
对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
Field getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields()返回一个包含某些
Field
对象的数组,这些对象反映此Class
对象所表示的类或接口的所有可访问公共字段
public static void testField(Class cls) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
Field name=cls.getDeclaredField("name");
//Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。
name.setAccessible(true);
//void set(Object obj, Object value)
Person p=new Person(05,"大力",18);
name.set(p, "大力水手");
System.out.println(name.get(p));
System.out.println(name.getName());
System.out.println(Modifier.toString(name.getModifiers()));
}
}