1.类加载器

     a.类的加载:   

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

     一个类在加载过程中的三部曲:

A.加载 :

就是指将class文件读入内存,并为之创建一个Class对象. 任何类被使用时系统都会建立一个Class对象。

B.连接:

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

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

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

C.初始化 

      b.类的加载时机:

A.创建类的实例

B.访问类的静态变量,或者为静态变量赋值

C.调用类的静态方法

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

E.初始化某个类的子类

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

      c.加载器分类

A.类加载的作用:

    负责将.class文件加载到内在中,并为之生成对应的Class对象。

B.类加载器的分类

   ①.Bootstrap ClassLoader 根类加载器

   也被称为引导类加载器,负责Java核心类的加载

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

  ②. Extension ClassLoader 扩展类加载器

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

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

 

   ③.Sysetm ClassLoader 系统类加载器

   负责在JVM启动时加载来自java命令的class文件


2.反射

    Student.java--Student.class(字节码文件)--看成一个对象,这个对象就叫字节码文件对象--对应的类Class

    定义:通过字节码文件对象去使用成员。

    获取字节码文件对象的三种方式:

A:Object类的getClass()方法

B:数据类型的静态class属性

C:Class类的静态方法forName()

注意:

在平常写案例的时候,我们直接使用第二种最方便。但是实际开发中,我们一般用的都是第三          种。是因为第三种接收的是一个字符串类型的参数,我们可以把这个参数作为配置文件的内容进行          配置,这样就实现了一个变化的内容。

//获取Person类对应的Class字节码文件对象

//A.Object类的getClass()方法

Person p1 = new Person();

Person p2 = new Person();

Class c1 = p1.getClass();

Class c2 = p2.getClass();


//B.数据类型的静态class属性

Class c3 = Person.class;

//C.Class类的静态方法forName()

Class c4 = Class.forName("com.edu_01.Person");//全类名


    反射的使用步骤:

 Class:

  成员变量Field

  构造方法Constructor

  成员方法Method

 反射:class字节码文件对象 -- 去得到对应的成员对象 -- 通过该成员的对象调用方法使用,通过反射获取构造方法并使用


    


 a.通过反射获取构造方法

 public Constructor[] getConstructors() 获取公共的构造方法

 public Constructor[] getDeclaredConstructors() 获取所有的构造方法(包括私有)

 public Constructor getConstructor(Class... parameterTypes) 根据构造参数获取公共的指定构造

 public Constructor getDeclaredConstructor(Class<?>... parameterTypes) 根据构造参数获取指定构造(包括私有,但是私有在使用的时候需要取消访问限制)


                //获取Peroson类对应的字节码文件对象

Class c = Class.forName("com.edu_01.Person");

//获取Perosn类中对应的构造方法

Constructor[] cons = c.getConstructors();

//遍历所有获取到的构造方法

for (Constructor con : cons) {

System.out.println(con);

}

Constructor[] cons2 = c.getDeclaredConstructors();

for (Constructor con : cons2) {

System.out.println(con);

}

System.out.println("---------------");

//获取Person类中的公共的无参数的构造方法

Constructor con  = c.getConstructor();

System.out.println(con);


Object obj = con.newInstance();

System.out.println(obj);

 


                //获取Person类中的非公共的构造方法

Constructor con2 = c.getDeclaredConstructor(String.class,int.class,String.class);

//获取构造器的时候,传入的什么参数,在调用获取到的这个构造方法对象的时候也就需要传入什么类型的参数

//取消这个构造器对象所对应的访问权限检测

con2.setAccessible(true);

Object obj2 = con2.newInstance("陈奕迅",45,"香港");

System.out.println(obj2);

//获取被Protected修饰的构造方法

Constructor con3 = c.getDeclaredConstructor(String.class,int.class);

//取消访问权限的检测

con3.setAccessible(true);

Object obj3 = con3.newInstance("周杰伦",35);

System.out.println(obj3);

 b.通过反射获取构造方法并创建对象

          public T newInstance(Object... initargs)


 c.通过反射获取成员变量并使用

 public Field[] getFields()获取公有的成员变量

 public Field[] getDeclaredFields()获取全部的成员变量,包括私有

 public Field getDeclaredField(String name) 传入变量名称返回指定的成员变量对象,包括私有

 public Field getField(String name)传入变量名称返回指定的成员变量对象,仅可获取共有的

 public void set(Object obj,Object value)给一个对象的一个字段设置一个值

               //获取Perosn类对应的字节码文件对象

Class c = Class.forName("com.edu_01.Person");

//利用反射获取一个Person对象

Constructor con = c.getConstructor();

Object obj = con.newInstance();

//获取所有公共的字段对象

Field[] fields = c.getFields();

for (Field field : fields) {

System.out.println(field);

}


//获取所有的字段对象,包括私有

Field[] fields2 = c.getDeclaredFields();

for (Field field : fields2) {

System.out.println(field);

}

//获取String name;字段

Field f = c.getDeclaredField("name");

//使用f这个对象给一个Perosn对象设置姓名

//取消访问修饰符的限制

f.setAccessible(true);

f.set(obj, "周杰伦");

//获取public int age;

Field f2 = c.getField("age");

f2.set(obj, 30);

Field f3 = c.getDeclaredField("address");

//取消权限检测

f3.setAccessible(true);

f3.set(obj, "香港");

System.out.println(obj);


d.通过反射获取成员方法并使用

 public Method[] getMethods()获取所有公共成员方法

 public Method[] getDeclaredMethods()获取所有成员方法,包括私有

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

              参数一:方法名 参数二:方法参数类型.class 获取指定的公共方法

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

              参数一:方法名 参数二:方法参数类型.class 获取指定的方法,包括私有

 Object invoke(Object obj, Object... args) 让某一个对象使用这个方法,并且传入参数

 

                //获取Person类中所有的公有的成员方法

//创建Pwrson类对应的字节码文件对象

Class c = Class.forName("com.edu_01.Person");

//利用反射的方式创建一个Person对象

Constructor con  = c.getConstructor();

Object obj = con.newInstance();

Method[] methods = c.getMethods();

for (Method method : methods) {

System.out.println(method);

}

//获取Person类中的所有的成员方法

Method[] methods2 = c.getDeclaredMethods();

for (Method method : methods2) {

System.out.println(method);

}


//获取method()这个公有的成员方法

Method m  = c.getMethod("method");

System.out.println(m);


//需求获取method这个个方法

Method m2 = c.getDeclaredMethod("method");

System.out.println(m2);

//使用m2这个成员方法的对象

m2.invoke(obj);

//获取Person类中function方法

Method m3 = c.getDeclaredMethod("function", int.class);

//取消权限检测

m3.setAccessible(true);

m3.invoke(obj, 10);

Method m4 = c.getDeclaredMethod("show", String.class,String.class);

m4.setAccessible(true);

m4.invoke(obj, "周杰伦","昆凌");