反射与类加载机制总结

反射与类加载机制总结,第1张

反射与类加载机制总结 反射与类加载机制总结 1、反射的定义

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期 借助于ReflectionAPI取得任何类的内部信息,并能直接 *** 作任意对象的内部属性及方法
原理 : 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看
到类的结构,所以,我们形象的称之为:反射

2、获取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
        Class personClass1 = Person.class;
     
        //方法2 通过运行时的类对象
        Person person1 = new Person();
        Class 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");

哪些类型可以有Class对象?
(1)class: 外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2)interface:接口
(3)[]:数组
(4)enum:枚举
(5)annotation:注解@interface
(6)primitive type:基本数据类型
(7)void

3、Class对象的作用 3.1、创建对应的运行时类的对象

方法1、通过Class类的静态方 法forName()获取
Class aClass = (Class)Class.forName("com.sinux.inhaite.reflection.Person");
Person o = aClass.newInstance();
方法2、 调用Class的newInstance()方法
Class personClass = Person.class;
Person person = personClass.newInstance();

3.2、获取全部的接口
    1.获取全部的接口 public Class[] getInterfaces()
  Class[] interfaces = aClass.getInterfaces();
3.3、获取类继承的全部父类 public Class getSuperclass()
  Class 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();
    //获取参数类型
    TypeVariable>[] typeParameters = aClass.getTypeParameters();
    
4、反射获取全部字段 field

public Field[] getFields() 只能获取到当前运行时类及其父类的public属性(其他属性都获取不到)
public Field[] getDeclaredFields() 获取当前运行时类中的所有声明属性(无论什么权限public/protected/private),但是不能获取父类的属性
 Field方法中:
 public int getModifiers() 以整数形式返回此Field的修饰符
 public ClassgetType() 得到Field的属性类型
 public String getName() 返回Field的名称

		Class 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();
        }
5、获取全部方法

public Method[] getDeclaredMethods() 获取当前运行时类的所有的声明的方法(无论权限),不获取父类的方法
public Method[] getMethods() 获取当前运行时类及其父类或接口所有声明为public的权限方法
public Class getReturnType() 取得全部的返回值 public Class[]
getParameterTypes() 取得全部的参数
public int getModifiers() 取得修饰符
public Class[] getExceptionTypes()取得异常信息

   Class 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);
    }
6、获取全部构造器、注解、泛型、类所在的包

public Constructor[] getConstructors() 返回此 Class 对象所表示的类的所有public构造方法。
public Constructor[] getDeclaredConstructors() 返回此 Class 对象表示的类声明的所有构造方法getDeclaredConstructors()。
 Constructor类中:
取得修饰符: public int getModifiers();
取得方法名称: public String getName();
取得参数的类型:public Class[] getParameterTypes();

Class 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 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);
        }
7、调用运行时类的指定结构(重点) 7.1、调用指定属性

在反射机制中,可以直接通过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)

 Class 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.2、关于setAccessible方法的使用

Method和Field、Constructor对象都有setAccessible()方法。
setAccessible启动和禁用访问安全检查的开关。
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
使得原本无法访问的私有成员也可以访问
参数值为false则指示反射的对象应该实施Java语言访问检查

7.3、调用指定方法

通过反射,调用类中的方法,通过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.获取指定构造器(传入参数列表)
        Constructor declaredConstructor = studentClass.getDeclaredConstructor(String.class);
        //3.2 保证构造器可访问
        declaredConstructor.setAccessible(true);
        //3.3 调用此构造器创建运行时对象
        Student liaochao = declaredConstructor.newInstance("liaochao");
        System.out.println(liaochao);
8、类加载器

类加载的作用:将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);

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5684035.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存