• java 类名.class、object.getClass()和Class.forName()的区别 精析


     

    1.介绍

      getClass()介绍

      java是面向对象语言,即万物皆对象,所有的对象都直接或间接继承自Object类;

      Object类中有getClass()方法,通过这个方法就可以获得一个实例对象在内存中的实际类型。

      类名.class介绍

      通过对类名的引用取得在内存中该类型的实际类型。

      Class.forName("包名xx.类名xx")介绍

      通过"包名+类名"的方式同样可以取得在内存中该类型的实际类型。

    2.区别

      第一,类的加载方式不同

      Class.forName()属于动态加载类,在代码运行时加载指定类;

      Class.class属于静态加载类,在代码编译时加载指定类;

      object.getClass()取决于对象的产生方式:

      既可以是静态加载类(通过new创建的对象),也可以是动态加载类(通过Class.forName(xx.xx)创建的对象,对象可能不存在)。

    Class.forName("bbb").newInstance().getClass();

      第二,Class对象的创建方式不同

       Class.forName()

      运行阶段:JVM使用类装载器, 将类装入内存中,并对类进行初始化(静态代码块、非静态代码块、构造函数调用及静态变量);

      最后返回Class的对象。

      类名.class

      编译阶段:JVM使用类装载器, 将类装入内存中,并对类进行初始化操作;

      最后返回Class的对象。

      实例对象.getClass()

      当调用getClass()方法时,该对象的类已经被加载到内存中并且完成了初始化操作;

      直接返回Class的对象,没有其它操作。

      第三,对象与类的关系不同

      通过类创建对象:

      Class.forName(xxx.xx.xx)和Class.class返回的是一个类,调用newInstance()后才创建一个对象;

    // 获取类
    Class<String> c = String.class;
    // 通过类创建对象
    String s = c.newInstance();

      通过对象获取类:

      object.getClass();

    // 获取类
    Class<String> c = String.class;
    // 通过类创建对象
    String s = c.newInstance();
    // 通过对象获取类
    Class<? extends String> c2 = s.getClass();

    3.测试

      公用代码

    /**
     * class类加载
     * @explain
     * @author Marydon
     * @creationTime 2018年10月19日上午9:26:29
     * @version 1.0
     * @since
     * @email marydon20170307@163.com
     */
    public class ClassLoader2 {
    	
    	/**
    	 * 构造函数
    	 * @explain 在类每次被实例化时执行
    	 */
    	public ClassLoader2() {
    		System.out.println("--------调用构造函数--------");
    	}
    
    	/**
    	 * 静态的参数初始化
    	 * @explain 在类初次被加载到内存中时执行
    	 */
    	static {
    		System.out.println("--------执行静态代码块--------");
    	}
    	
    	/**
    	 * 非静态的参数初始化
    	 * @explain 在类每次被实例化时执行
    	 */
    	{
    		System.out.println("--------执行非静态代码块--------");
    	}
    
    }
      注意:
      类名一定不能是ClassLoader.java,因为已经存在java.lang.ClassLoader了,如果还命名为ClassLoder,会影响测试结果;
      起初自己发现了新大陆,原来是个坑,空欢喜一场!
    /**
     * class类加载测试
     * @explain
     * @author Marydon
     * @creationTime 2018年10月19日下午3:44:32
     * @version 1.0
     * @since
     * @email marydon20170307@163.com
     */
    public class TestClassLoader2 {
    	static {
    		System.out.println("执行TestClassLoader2.class初始化操作!");
    	}
    	
    	public static void main(String[] args) throws ClassNotFoundException{
    		
    	}
    }

      测试:类.class

    // 测试1:类.class
    Class<ClassLoader2> c = ClassLoader2.class;
    System.out.println(c);

      测试结果:ClassLoader2.class在编译时已经加载到了内存中。

      判断依据:静态代码块并没有执行!

      测试:objet.getClass()

      方式一:使用静态加载类创建对象

    Object cl2 = new ClassLoader2();
    System.out.println(cl2.getClass());

      测试结果:

      方式二:使用动态加载类创建对象

    System.out.println(Class.forName("test.ClassLoader2").newInstance().getClass());
    

      说明:

      无论是在通过动态加载类还是静态加载类创建的ClassLoader2类的对象时,ClassLoader2类都会被重新加载到内存当中,

      所以当调用.getClass()方法时,并不会执行任何类的初始化操作。

      测试:Class.forName("包名.类名")

    public static void main(String[] args) throws ClassNotFoundException {
    	// 测试3:Class.forName()
    	Class<?> c3 = Class.forName("test.ClassLoader2");
    	System.out.println(c3);
    }
    

      测试结果:ClassLoader2.class在运行时被加载到内存中。

      判断依据:静态代码块执行!

      类比较(判断是否时同一class类型)

      在上面的main方法中添加

    System.out.println("--------类比较--------");
    System.out.println(c.equals(cl2.getClass()));
    System.out.println(c.equals(c3));

      测试结果:

      证实:非静态代码块与构造函数,每次实例化都会被执行。(与文章主题无关)

      在上面的main方法中添加

    System.out.println("第二次实例化ClassLoader2");
    ClassLoader2 cl3 = new ClassLoader2();

      测试结果:  

    写在最后

      哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

  • 相关阅读:
    第八讲、原型模式
    第七讲、建造者模式
    第六讲、抽象工厂模式
    第五讲、工厂方法模式
    第四讲、简单工厂模式
    第三讲、策略模式
    第二讲、备忘录模式
    第一讲、单例模式
    二、中国黑客
    java 17
  • 原文地址:https://www.cnblogs.com/Marydon20170307/p/9815325.html
Copyright © 2020-2023  润新知