首页 > 其他 > 详细

类加载器,,,,,反射

时间:2020-08-05 23:35:46      阅读:89      评论:0      收藏:0      [点我收藏+]

    类加载器

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

l  加载

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

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

l  连接

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

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

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

l  初始化

就是我们以前讲过的初始化步骤(进栈进堆调方法)

 

      类初始化时机(什么时候类进内存)

1. 创建类的实例(new类对象的时候,创建class文件对象)

2. 类的静态变量,或者为静态变量赋值(类名 . 静态成员变量或成员变量赋值时,进内存)

3. 类的静态方法(调用类的静态方法时进内存)

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

5. 初始化某个类的子类(初始化子类时,父类会进内存。因为构造方法先调super())

6. 直接使用java.exe命令来运行某个主类(main方法所在的类,主类)

//如何证明进内存:一进内存就会执行静态代码块

public class Demo01 {
public static void main(String[] args) {
    //System.out.println(Person.a);//先进内存再打印a
    //Person.aa();//先进内存再调方法
    new Person();//先父类进内存,再子类进内存
}
}

 

public class Person extends God{
    public static int a=1;
static{
    System.out.println("Person类进内存了");
}
public static void aa(){
    System.out.println("静态方法");
}

}

 

public class God {
static{
    System.out.println("父类进内存了");
}
}

 

      类加载器

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

 

      类加载器的组成

l  Bootstrap ClassLoader 根类加载器(已经写好的JDK中的类)

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

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

l  Extension ClassLoader 扩展类加载器

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

在JDK中JRE的lib目录下ext目录(jdk所依赖的jar包里面的类)

l  System ClassLoader 系统类加载器(我们自定义的类,以及导入jar包里面的类)

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

 

技术分享图片

 

 

     反射

      Class类(字节码类)

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

 

l  获取Class对象的三种方式

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

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

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

public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
    //获取Class字节码文件对象的方式
    Person p=new Person();
    Class c1=p.getClass();//person类的字节码文件对象
    System.out.println(c1);//公共空参构造(new调用构造方法执行的),class是Person类的字节码文件对象
    //Class属性获取
    Class c2=Person.class;
    System.out.println(c2);
    //System.out.println(c1==c2);获取只有一个,一个类的字节码文件只有一个
    //通过class。forname()
    Class c3=Class.forName("com.oracle.demo06.Person");//要加载类的完整包名+类名
    System.out.println(c3);
}
}
public class Person {
public String name;
private int age;
public Person(){
    System.out.println("公共空参构造");
}
public Person(String name){
    System.out.println("公共有参构造");
}
private Person(String name,int age){
    System.out.println("私有有参构造");
}
public void eat(){
    System.out.println("公共无参方法");
}
public void sleep(String name){
    System.out.println("公共有参方法");
}
public void smoke(int age){
    System.out.println("私有有参方法");
}

 

反射获取构造方法并使用

在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示。其中,构造方法使用类Constructor表示。可通过Class类中提供的方法获取构造方法:

//构造方法封装成一个类

 

l  返回一个构造方法

 

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

//Class<?>字节码文件对象(参数写的啥就获取啥),... 可变参

 

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

 

l  返回多个构造方法

 

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

 

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

 

public class Demo02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //获取Person的字节码文件对象
    Class c=Class.forName("com.oracle.demo06.Person");
    //获取公共指定构造方法对象
    Constructor con=c.getConstructor(String.class);//完整报名+类名String.class
    System.out.println(con);//公共有参public修饰完整包名+类名,String类完整包名+类名
    //获取私有构造方法对象
    Constructor con2=c.getDeclaredConstructor(String.class,int.class);
    System.out.println(con2);
    //用公共构造方法对象创建Person对象
    //返回值Object类型
    Person p=(Person)con.newInstance("admin");
    p.eat();//调方法
    //用私有构造方法创建Person类对象
    //暴力反射(不提倡,破坏了面向对象封装)
    //con2.setAccessible(true);
    //不用暴力反射报错:不能被创建
    Person p2=(Person)con2.newInstance("小红",18);
    p2.eat();
}
}

Person类

public class Person {
public String name;
private int age;
public Person(){
    System.out.println("公共空参构造");
}
public Person(String name){
    System.out.println("公共有参构造");
}
private Person(String name,int age){
    System.out.println("私有有参构造");
}
public void eat(){
    System.out.println("公共wu参方法");
}
public void sleep(String name){
    System.out.println("公共有参方法");
}
public void smoke(int age){
    System.out.println("siyou有参方法");
}
}

 

创建对象的三种方法:new,反序列,反射

 

类加载器,,,,,反射

原文:https://www.cnblogs.com/111wdh/p/13443377.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!