2、获取Class实例的方法Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期 借助于ReflectionAPI取得任何类的内部信息,并能直接 *** 作任意对象的内部属性及方法。
原理 : 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看
到类的结构,所以,我们形象的称之为:反射
1)前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠, 程序性能最高 实例:
Class clazz = String.class;
2)前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象 实例:
Class clazz = “类实例(对象)”.getClass();
3)前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方 法forName()获取,可能抛出ClassNotFoundException 实例:
Class clazz = Class.forName(“java.lang.String”);
4)其他方式(不做要求)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 =cl.loadClass(“类的全类名”);
//方法1 调用运行时的类属性.class ClasspersonClass1 = Person.class; //方法2 通过运行时的类对象 Person person1 = new Person(); Class extends Person> personClass2 = person1.getClass(); //方法3 调用Class的静态方法 forName **重点常用** Class> personClass3 = Class.forName("com.sinux.inhaite.reflection.Person"); //方法4 类加载器 ClassLoader classLoader = this.getClass().getClassLoader(); Class> personClass4 = classLoader.loadClass("com.sinux.inhaite.reflection.Person");
3、Class对象的作用 3.1、创建对应的运行时类的对象哪些类型可以有Class对象?
(1)class: 外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2)interface:接口
(3)[]:数组
(4)enum:枚举
(5)annotation:注解@interface
(6)primitive type:基本数据类型
(7)void
3.2、获取全部的接口方法1、通过Class类的静态方 法forName()获取
ClassaClass = (Class )Class.forName("com.sinux.inhaite.reflection.Person");
Person o = aClass.newInstance();
方法2、 调用Class的newInstance()方法
ClasspersonClass = Person.class;
Person person = personClass.newInstance();
3.3、获取类继承的全部父类 public Class Super T> getSuperclass()1.获取全部的接口 public Class>[] getInterfaces() Class>[] interfaces = aClass.getInterfaces();
Class super Person> superclass = aClass.getSuperclass();3.4、返回此 Class 对象所表示的类的所有public构造方法 getConstructors()
Constructor>[] constructors = aClass.getConstructors();3.5、返回此 Class 对象表示的类声明的所有构造方法getDeclaredConstructors()
Constructor>[] declaredConstructors = aClass.getDeclaredConstructors();3.6 从Constructor类中获去以下
Constructor类中: 取得修饰符: public int getModifiers(); 取得方法名称: public String getName(); 取得参数的类型:public Class>[] getParameterTypes();
//获取类的修饰符 int modifiers = aClass.getModifiers(); //获取类名 String name = aClass.getName(); //获取参数类型 TypeVariable4、反射获取全部字段 field>[] typeParameters = aClass.getTypeParameters();
public Field[] getFields() 只能获取到当前运行时类及其父类的public属性(其他属性都获取不到)
public Field[] getDeclaredFields() 获取当前运行时类中的所有声明属性(无论什么权限public/protected/private),但是不能获取父类的属性
Field方法中:
public int getModifiers() 以整数形式返回此Field的修饰符
public Class>getType() 得到Field的属性类型
public String getName() 返回Field的名称
Class5、获取全部方法studentClass = Student.class; Field[] fields = studentClass.getFields(); for(Field f:fields){ System.out.println(f); } Field[] declaredFields = studentClass.getDeclaredFields(); for(Field f : declaredFields){ System.out.println(f); System.out.println(f); //返回的int类型 int modifiers = f.getModifiers(); String s = Modifier.toString(modifiers); //这里输出的就是权限符而不是数字了 System.out.println(s); Class> type = f.getType(); System.out.println(type.getName()+"t"); String name = f.getName(); }
public Method[] getDeclaredMethods() 获取当前运行时类的所有的声明的方法(无论权限),不获取父类的方法
public Method[] getMethods() 获取当前运行时类及其父类或接口所有声明为public的权限方法
public Class> getReturnType() 取得全部的返回值 public Class>[]
getParameterTypes() 取得全部的参数
public int getModifiers() 取得修饰符
public Class>[] getExceptionTypes()取得异常信息
Class6、获取全部构造器、注解、泛型、类所在的包studentClass = Student.class; Method[] methods = studentClass.getMethods(); for(Method m:methods){ System.out.println(m); Annotation[] annotations = m.getAnnotations(); for (Annotation a:annotations) { System.out.println("注解:"+a); } String s = Modifier.toString(m.getModifiers())+"t"; System.out.println(m+"的权限属性是:"+s); System.out.println(m+"方法的返回值是:"+m.getReturnType().getName()+"t"); System.out.println(m+"的方法名:"+m.getName()+"t"); System.out.println("("); Class>[] parameterTypes = m.getParameterTypes(); if(parameterTypes!=null && parameterTypes.length!=0){ for (Class p :parameterTypes){ System.out.println(m+"的形参是:"+p.getName()); } } System.out.println(")"); Class>[] exceptionTypes = m.getExceptionTypes(); if(exceptionTypes!=null && exceptionTypes.length!=0){ System.out.println("throws "); for (Class e:exceptionTypes) { System.out.println(m+"的异常:"+e.getName()+","); } } } Method[] declaredMethods = studentClass.getDeclaredMethods(); for(Method m:declaredMethods){ System.out.println(m); }
public Constructor[] getConstructors() 返回此 Class 对象所表示的类的所有public构造方法。
public Constructor[] getDeclaredConstructors() 返回此 Class 对象表示的类声明的所有构造方法getDeclaredConstructors()。
Constructor类中:
取得修饰符: public int getModifiers();
取得方法名称: public String getName();
取得参数的类型:public Class>[] getParameterTypes();
Class7、调用运行时类的指定结构(重点) 7.1、调用指定属性studentClass = Student.class; Constructor>[] constructors = studentClass.getConstructors(); for (Constructor c:constructors) { System.out.println(c); } Constructor>[] declaredConstructors = studentClass.getDeclaredConstructors(); for (Constructor c:declaredConstructors) { System.out.println(c); } Class super Student> superclass = studentClass.getSuperclass(); System.out.println(superclass); Type genericSuperclass = studentClass.getGenericSuperclass(); System.out.println("获取父类泛型类型:"+genericSuperclass); ParameterizedType parameterizedType =(ParameterizedType)genericSuperclass; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); System.out.println(actualTypeArguments[0]); Class>[] interfaces = studentClass.getInterfaces(); for (Class i:interfaces) { System.out.println(i); } Class>[] interfaces1 = studentClass.getSuperclass().getInterfaces(); for (Class i:interfaces1 ) { System.out.println(i); } Annotation[] annotations = studentClass.getAnnotations(); for (Annotation a:annotations ) { System.out.println("类上的注解"+a); }
在反射机制中,可以直接通过Field类 *** 作类中的属性,通过Field类提供的set()和 get()方法就可以完成设置和取得属性内容的 *** 作。
public Field getField(String name) 获取运行时类和父类的public属性,设定值,并取出值
public Field getDeclaredField(String name)获取运行时类的任何属性(不能获取父类)
在Field中:
//从属性获取值(参数:从哪个对象获取值)
public Object get(Object obj)
// 给属性设定值(参数1,指明设置哪个对象的属性,参数2,设定值)
public void set(Object obj,Object value)
Class7.2、关于setAccessible方法的使用studentClass = Student.class; Student student = studentClass.newInstance(); Field id = studentClass.getField("id"); //给属性设定值(参数1,指明设置哪个对象的属性,参数2,设定值) id.set(student,121); //从属性获取值(参数:从哪个对象获取值) System.out.println((int)id.get(student)); Field brast = studentClass.getField("brast"); brast.set(student,"A罩杯"); System.out.println(brast.get(student)); Field name = studentClass.getDeclaredField("name"); //setAccessible启动和禁用访问安全检查的开关.为true则指示反射的对象在使用时应该取消Java语言访问检查,为false则指示反射的对象应该实施Java语言访问检查 name.setAccessible(true); name.set(student,"战三"); System.out.println(name.get(student));
7.3、调用指定方法Method和Field、Constructor对象都有setAccessible()方法。
setAccessible启动和禁用访问安全检查的开关。
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
使得原本无法访问的私有成员也可以访问
参数值为false则指示反射的对象应该实施Java语言访问检查
通过反射,调用类中的方法,通过Method类完成。步骤:
1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得 一个Method对象,并设置此方法 *** 作时所需要的参数类型。
2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中 传递要设置的obj对象的参数信息。 Object invoke(Object obj, Object … args) 说明:
1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
2.若原方法若为静态方法,此时形参Object obj可为null
3.若原方法形参列表为空,则Object[] args为null
4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用 方法对象的setAccessible(true)方法,将可访问private的方法。
Method show = studentClass.getDeclaredMethod("show", String.class); //访问私有方法要先禁用访问安全检查的开关 show.setAccessible(true); Object nation = show.invoke(student, "日本"); System.out.println(nation); Method eat = studentClass.getMethod("eat"); Object invoke = eat.invoke(student); System.out.println(invoke); // private Student(String name) { // this.name = name; // } //3.1.获取指定构造器(传入参数列表) Constructor8、类加载器declaredConstructor = studentClass.getDeclaredConstructor(String.class); //3.2 保证构造器可访问 declaredConstructor.setAccessible(true); //3.3 调用此构造器创建运行时对象 Student liaochao = declaredConstructor.newInstance("liaochao"); System.out.println(liaochao);
类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方
法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为 方法区中类数据的访问入口
获取类加载器
//1.对于自定义类,使用系统类加载器进行加载 ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); //.获取一个系统类加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); //虎丘指定类的类加载器 ClassLoader classLoader1 = Class.forName("com.sinux.inhaite.reflection.Person").getClassLoader();
①关于类加载器的一个主要方法:getResourceAsStream(String
str):获取类路径下的指定文件的输入流。这种方式获取的默认是src/resouces目录下的文件
②FileInputStream方法:new FileInputStream(“config.properties”)
文件默认在当前的module下(即项目名下与src平级)
通过类加载器读取配置文件
Properties prop = new Properties(); ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); //这种方式获取的默认是src/resouces目录下的文件 InputStream resourceAsStream = classLoader.getResourceAsStream("config1.properties"); prop.load(resourceAsStream); String user = prop.getProperty("user"); String password = prop.getProperty("password"); System.out.println("user:"+user+",password:"+password);
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)