8.1.4反射动态机制
-
反射是JAVA有着一个非常突出的动态相关机制:Reflection。
-
必须发生在程序运行期间->(动态语言的特点)
-
Java反射机制,可以实现以下功能: ①在运行时判断任意一个对象所属的类; ②在运行时构造任意一个类的对象; ③在运行时判断任意一个类所具有的成员变量和方法; ④在运行时调用任意一个对象的方法; ⑤生成动态代理;
public class Class001_Reflect { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException { //在jdk11中允许通过var声明一个局部变量,类型由初始值的类型决定 var i = ""; //构建一个Properties对象 Properties pro = new Properties(); //从流中加载 pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("classname.properties")); //通过反射创建对象 Person p = (Person) Class.forName((pro.getProperty("classname"))).newInstance(); p.sleep(); } } class Person{ void sleep(){ System.out.println("逼着眼睛睡觉"); } } class Student extends Person{ void sleep(){ System.out.println("边上课边睡觉"); } } class Teacher extends Person{ void sleep(){ System.out.println("边讲课边睡觉"); } }
8.1.5反射的源头
-
反射的源头: Class : 类实例表示正在运行的Java应用程序中的类和接口。 一个类在加载到内存之后就会存在一个该类的Class对象,不是通过程序员城建就已经存在,独一份不变的 使用的时候不能创建只能获取 可以理解为Class对象中包含类中的所有内容,只要获取Class对象就能操作这个类型
-
获取Class对象的方式: 类名.class 对象.getClass() Class.forName(包名.类名) 权限定名:包名.类名 --> 推荐
public class Class002_Reflect { public static void main(String[] args) throws Exception{ Class<String> cls1 = String.class; System.out.println(cls1.toString()); Class cls2 = "abc".getClass(); System.out.println(cls1==cls2); Class cls3 = Class.forName("java.lang.String"); System.out.println(cls1==cls3); //获取父类的Class对象 System.out.println(Object.class==cls1.getSuperclass());; //获取基本数据类型的Class对象 System.out.println(int.class); System.out.println(Integer.class); System.out.println(Integer.TYPE); System.out.println(int.class==Integer.class); System.out.println(int.class==Integer.TYPE); } }
8.1.6CLass常用方法
public class Class003_Reflect { public static void main(String[] args){ Class<String> cls = String.class; //类<?>[] getInterfaces() 返回由此对象表示的类或接口直接实现的接口。 System.out.println(Arrays.toString(cls.getInterfaces())); //int getModifiers() 返回此类或接口的Java语言修饰符,以整数编码。 System.out.println(cls.getModifiers()); //static String toString(int mod) 返回描述指定修饰符中的访问修饰符标志的字符串。 System.out.println(Modifier.toString(cls.getModifiers())); //String getName() 返回此 类对象表示的实体名称(类,接口,数组类,基本类型或void),作为 String 。 System.out.println(cls.getName()); //String getSimpleName() 返回源代码中给出的基础类的简单名称。 System.out.println(cls.getSimpleName()); //boolean isPrimitive() 确定指定的 类对象是否表示基本类型。 System.out.println(int.class.isPrimitive()); System.out.println(Integer.class.isPrimitive()); } }
8.1.7反射创建对象
-
反射创建对象 基于反射的源头-->获取某一个类型的Class对象 1) Class--> T newInstance() --> 默认调用空构造 2) Constructor --> T newInstance(Object... initargs) a. 获取指定的构造器 构造器<T> getConstructor(类<?>... parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类的指定公共构造函数。 构造器<?>[] getConstructors() 返回一个包含 构造器对象的数组, 构造器对象反映了此 类对象所表示的类的所有公共构造函数。 获取public修饰的构造器 构造器<T> getDeclaredConstructor(类<?>... parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类或接口的指定构造函数。 构造器<?>[] getDeclaredConstructors() 返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。 获取所有权限的构造器
-
b. 调用Constructor类中的newInstance方法,创建对象的同时调用当前构造器为对象初始化信息
public class Class004_Reflect { public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //表示Emp类的Class对象 Class<Emp> cls = Emp.class; // 1) Class--> T newInstance() Emp emp = cls.newInstance(); System.out.println(emp); // 2)Constructor --> T newInstance(Object... initargs) // a. 获取指定的构造器 Constructor[] cons = cls.getConstructors(); for(Constructor con:cons){ System.out.println(con); } Constructor<Emp> con = cls.getDeclaredConstructor(String.class,double.class); System.out.println(con); System.out.println(con.getParameterCount()); System.out.println(Modifier.toString(con.getModifiers())); //b.调用Constructor类中的newInstance方法,创建对象的同时调用当前构造器为对象初始化信息 //忽略权限 con.setAccessible(true); Emp emp2 = con.newInstance("zhangsan",19980); System.out.println(emp2); } } class Emp{ private int no; private String name; private double sal; public Emp() { } private Emp(String name) { this.name = name; } private Emp(String name, double sal) { this.name = name; this.sal = sal; } public Emp(int no, String name, double sal) { this.no = no; this.name = name; this.sal = sal; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } @Override public String toString() { return "Emp{" + "no=" + no + ", name='" + name + '\'' + ", sal=" + sal + '}'; } }
8.1.8反射操作方法与属性
-
通过反射操作方法 1.获取方法 方法 getMethod(String name, 类<?>... parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。 方法[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。 方法 getDeclaredMethod(String name, 类<?>... parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。 方法[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。
-
2.调用方法 Object invoke(Object obj, Object... args)
public static void testMethod(Class<Emp> cls) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { Method[] methods = cls.getMethods(); for(Method method:methods){ System.out.println(method); } Method method = cls.getDeclaredMethod("testPrivate",int.class); System.out.println(method); System.out.println(method.getParameterCount()); System.out.println(method.getReturnType()); //创建对象 Emp emp = cls.newInstance(); //调用方法 method.setAccessible(true); System.out.println(method.invoke(emp,100));; } /* 操作属性 1.获取属性 字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。 字段[] getDeclaredFields() 返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。 字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。 字段[] getFields() 返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。 2.为属性赋值 void set(Object obj, Object value) 将指定对象参数上此 字段对象表示的字段设置为指定的新值。 3.获取属性的值 Object get(Object obj) 返回指定对象上此 字段表示的字段的值。 */ public static void testField(Class<Emp> cls) throws NoSuchFieldException, IllegalAccessException { //1.获取属性 //获取非静态成员属性 Field field = cls.getDeclaredField("name"); System.out.println(field); System.out.println(field.getType()); //获取静态属性 Field field2 = cls.getField("comName"); System.out.println(field2); Emp emp = new Emp(1001,"wangwu",2000); //私有的成员忽略权限 field.setAccessible(true); //2.为属性赋值 field.set(emp,"王五五"); //3.获取属性的值 System.out.println(field.get(emp));; System.out.println(field2.get(emp)); System.out.println(field2.get(null)); } }