zoukankan      html  css  js  c++  java
  • 类加载器和反射

    一、类加载器

      1、类的加载

        当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

    加载

    就是指将class文件读入内存,并为之创建一个Class对象。

    任何类被使用时系统都会建立一个Class对象

    连接

    验证 是否有正确的内部结构,并和其他类协调一致

    准备 负责为类的静态成员分配内存,并设置默认初始化值

    解析 将类的二进制数据中的符号引用替换为直接引用

    初始化

    就是我们以前讲过的初始化步骤

      2、类初始化时机

        1.) 创建类的实例

        2. )类的静态变量,或者为静态变量赋值

        3. )类的静态方法

        4. )使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

        5. )初始化某个类的子类

        6. )直接使用java.exe命令来运行某个主类

      3、类加载器的组成

        1)Bootstrap ClassLoader 根类加载器也被称为引导类加载器,负责Java核心类的加载

              比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

        2)Extension ClassLoader 扩展类加载器

           负责JRE的扩展目录中jar包的加载。

           在JDK中JRE的lib目录下ext目录

        3)System ClassLoader 系统类加载器

           负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。

    二、反射

      JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

      对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

      1、Class类

        获取Class对象的三种方式

        方式: 通过Object类中的getObject()方法

            Person p = new Person();

            Class c = p.getClass();

          方式二: 通过 类名.class 获取到字节码文件对象(任意数据类型都具备一个class静态属性,看上去要比第一种方式简单)。

            Class c2 = Person.class;

          方式三: 通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName即可)。

            Class c3 = Class.forName("Person");

        注意:第三种和前两种的区别

            前两种你必须明确Person类型.

            后面是指定这种类型的字符串就行.这种扩展更强.我不需要知道你的类.我只提供字符串,按照配置文件加载就可以了

    代码演示: 

    /*
     * 获取.class字节码文件对象的方式
     *         1:通过Object类中的getObject()方法
     *         2: 通过 类名.class 获取到字节码文件对象
     *         3: 反射中的方法,
     *             public static Class<?> forName(String className) throws ClassNotFoundException
     *             返回与带有给定字符串名的类或接口相关联的 Class 对象 
     */
    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException {
            // 1: 通过Object类中的getObject()方法
            // Person p1 = new Person();
            // Class c1 = p1.getClass();
            // System.out.println("c1 = "+ c1);
    
            // 2: 通过 类名.class 获取到字节码文件对象
            // Class c2 = Person.class;
            // System.out.println("c2 = "+ c2);
    
            // 3: 反射中的方法
            Class c3 = Class.forName("cn.oracle_01_Reflect.Person");// 包名.类名
            System.out.println("c3 = " + c3);
        }
    }

    Person类

    package cn.oracle_01_Reflect;
    public class Person {
        //成员变量
        public String name;
        public int age;
        private String address;
    
        //构造方法
        public Person() {
            System.out.println("空参数构造方法");
        }
        
        public Person(String name) {
            this.name = name;
            System.out.println("带有String的构造方法");
        }
        //私有的构造方法
        private Person(String name, int age){
            this.name = name;
            this.age = age;
            System.out.println("带有String,int的构造方法");
        }
        
        public Person(String name, int age, String address){
            this.name = name;
            this.age = age;
            this.address = address;
            System.out.println("带有String, int, String的构造方法");
        }
        
        //成员方法
        //没有返回值没有参数的方法
        public void method1(){
            System.out.println("没有返回值没有参数的方法");
        }
        //没有返回值,有参数的方法
        public void method2(String name){
            System.out.println("没有返回值,有参数的方法 name= "+ name);
        }
        //有返回值,没有参数
        public int method3(){
            System.out.println("有返回值,没有参数的方法");
            return 123;
        }
        //有返回值,有参数的方法
        public String method4(String name){
            System.out.println("有返回值,有参数的方法");
            return "哈哈" + name;
        }
        //私有方法
        private void method5(){
            System.out.println("私有方法");
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
        }
    }

      2、通过反射获取构造方法并使用

        在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示。

        其中,构造方法使用类Constructor表示。可通过Class类中提供的方法获取构造方法:

        返回一个构造方法

        public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法

        public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)

        返回多个构造方法

        public Constructor<?>[] getConstructors() 获取所有的public 修饰的构造方法

        public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法(包含私有的)

    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
            //获取Class对象
            Class c = Class.forName("cn.oracle_01_Reflect.Person");//包名.类名
            
            //获取所有的构造方法
            //Constructor[] cons = c.getConstructors();
            Constructor[] cons = c.getDeclaredConstructors();
            for (Constructor con : cons) {
                System.out.println(con);
            }
            
            System.out.println("------------------------");
            //获取一个构造方法
            //public Person() 
            Constructor con1 = c.getConstructor(null);
            System.out.println(con1);
            
            //public Person(String name)
            Constructor con2 = c.getConstructor(String.class);
            System.out.println(con2);
            
            //private Person(String name, int age)
            Constructor con3 = c.getDeclaredConstructor(String.class, int.class);
            System.out.println(con3);
            
            //public Person(String name, int age, String address)
            Constructor con4 = c.getDeclaredConstructor(String.class, int.class, String.class);
            System.out.println(con4);
        }
    }

      3、通过反射方式,获取构造方法,创建对象

        获取构造方法,步骤如下:

        1. 获取到Class对象

        2. 获取指定的构造方法

        3. 通过构造方法类Constructor中的方法,创建对象

        public T newInstance(Object... initargs)

    public class ConstructorDemo {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            //1,获取到Class对象
            Class c = Class.forName("cn.oracle_01_Reflect.Person");//包名.类名
            //2,获取指定的构造方法
            //public Person()
            //Constructor con = c.getConstructor(null);
            
            //public Person(String name, int age, String address)
            Constructor con = c.getConstructor(String.class, int.class, String.class);
            
            //3,通过构造方法类中Constructor的方法,创建对象
            //Object obj = con.newInstance(null);
            Object obj = con.newInstance("小明", 22, "哈尔滨");
            
            //显示
            System.out.println(obj);
        }
    }

      4、通过反射方式,获取私有构造方法,创建对象

        获取私有构造方法,步骤如下:

        1. 获取到Class对象

        2. 获取指定的构造方法

        3. 暴力访问, 通过setAccessible(boolean flag)方法

        4. 通过构造方法类Constructor中的方法,创建对象

        public T newInstance(Object... initargs)

    public class ConstructorDemo2 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            //1,获取到Class对象
            Class c = Class.forName("cn.oracle_01_Reflect.Person");//包名.类名
            
            //2,获取指定的构造方法
            //private Person(String name, int age)
            Constructor con = c.getDeclaredConstructor(String.class, int.class);
            
            //3,暴力反射 
            con.setAccessible(true);//取消 Java 语言访问检查
            
            //4,通过构造方法类中的功能,创建对象
            Object obj = con.newInstance("小明", 23);
            System.out.println(obj);
            
        }
    }

      5、通过反射获取成员变量并使用

        在反射机制中,把类中的成员变量使用类Field表示。可通过Class类中提供的方法获取成员变量:

        返回一个成员变量

        public Field getField(String name) 获取指定的 public修饰的变量

        public Field getDeclaredField(String name) 获取指定的任意变量

        返回多个成员变量

        public Field[] getFields() 获取所有public 修饰的变量

        public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)

    public class FieldDemo {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
            //获取Class对象
            Class c = Class.forName("cn.oracle_01_Reflect.Person");
            
            //获取成员变量
            //多个变量
            //Field[] fields = c.getFields();
            Field[] fields =  c.getDeclaredFields();
            for (Field field : fields) {
                System.out.println(field);
            }
            System.out.println("-----------------");
            //一个变量
            //public int age;
            Field ageField = c.getField("age");
            System.out.println(ageField);
            
            //private String address
            Field addressField = c.getDeclaredField("address");
            System.out.println(addressField);
        }
    }

      6、通过反射获取成员方法并使用

        在反射机制中,把类中的成员方法使用类Method表示。可通过Class类中提供的方法获取成员方法:

        返回获取一个方法:

        public Method getMethod(String name, Class<?>... parameterTypes)

          获取public 修饰的方法

        public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

          获取任意的方法,包含私有的

        参数1: name 要查找的方法名称; 参数2parameterTypes 该方法的参数类型

        返回获取多个方法:

        public Method[] getMethods() 获取本类与父类中所有public 修饰的方法

        

    public class MethodDemo {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
            //获取Class对象
            Class c = Class.forName("cn.oracle_01_Reflect.Person");
            
            //获取多个方法
            //Method[] methods = c.getMethods();
            Method[] methods = c.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println(method);
            }
            
            System.out.println("-----------------------");
            //获取一个方法:
            //public void method1()
            Method method = c.getMethod("method1", null);
            System.out.println(method);
            //public String method4(String name){
            method = c.getMethod("method4", String.class);
            System.out.println(method);
            //私有方法
            //private void method5()
            method = c.getDeclaredMethod("method5", null);
            System.out.println(method);
        }
    }

    public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)

  • 相关阅读:
    恢复ubuntu和windows的双引导
    手把手教你做MVC3中的完美分页控件
    201521123024 《Java程序设计》第5周学习总结
    201521123024 《Java程序设计》第1周学习总结
    201521123024 《Java程序设计》第6周学习总结
    201521123024 《Java程序设计》第2周学习总结
    201521123024 《Java程序设计》第4周学习总结
    201521123024《Java程序设计》第3周学习总结
    201521123024《Java程序设计》第7周学习总结
    201521123024《Java程序设计》第8周学习总结
  • 原文地址:https://www.cnblogs.com/luzhijin/p/13469364.html
Copyright © 2011-2022 走看看