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("--------执行非静态代码块--------"); } }
/** * 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();
测试结果:
写在最后
哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!