Class类简介

Class类 Java中所有的类、接口、枚举、注解、数组、基本数据类型、void关键字,都有Class对象。通过Class对象可以得到类的完整结构,一个Class对象在jvm中只有一个实例。
Class类简介
文章图片

获取类实例测试代码

package com.kuang; public class Test {public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("这个人是 " + person.name); //方式一 通过getClass()获取类 Class c1 = person.getClass(); System.out.println(c1.hashCode()); //方式二 通过forName获取类 可以获取到静态的类 Class c2 = Class.forName("com.kuang.Student"); System.out.println(c2.hashCode()); //方式三 通过类名.class获得 Class c3 = Student.class; System.out.println(c3.hashCode()); //方式4 基本内置类型的 `包装类` 都有一个Type属性 通过该属性获得 Class c4 = Integer.TYPE; System.out.println(c4); // 获取父类的类型 Class c5 = c1.getSuperclass(); System.out.println(c5); } }class Person { public String name; public Person() {}public Person(String name) { this.name = name; }@Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } }class Student extends Person { public Student() { this.name = "学生"; } }class Teacher extends Person { public Teacher() { this.name = "老师"; } }

package com.kuang; //哪些类有class对象import java.lang.annotation.ElementType; public class Test2 {public static void main(String[] args) { Class c1 = Object.class; //类 Class c2 = Comparable.class; //接口 Class c3 = String[].class; //一维数组 Class c4 = int[][].class; //二位数据 Class c5 = Override.class; //注解 Class c6 = ElementType.class; //枚举 Class c7 = Integer.class; //基本类型的包装类 Class c8 = void.class; //void Class c9 = Class.class; ///Class System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); //输出结果注意数组的输出结果有点特殊 //class java.lang.Object //interface java.lang.Comparable //class [Ljava.lang.String; //class [[I //interface java.lang.Override //class java.lang.annotation.ElementType //class java.lang.Integer //void //class java.lang.Class } }

Class类实际是一个泛型类。
Class类简介
文章图片

Class常用方法 Class类简介
文章图片

JAVA内存分析 Class类简介
文章图片

java类装载过程分为3步: Class类简介
文章图片

Class类简介
文章图片

1、加载 Jvm把class文件字节码加载到内存中,并将这些静态数据装换成运行时数据区中方法区的类型数据,在运行时数据区堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。
注:方法区不仅仅是存放方法,它还存放的是类的类型信息(class对象)。
2、链接 执行下面的校验、准备和解析步骤,其中解析步骤是可选的
  • 校验:检查加载的class文件的正确性和安全性
  • 准备:为类变量(static)分配存储空间并设置类变量初始值(变量类型的默认值),类变量随类型信息存放在方法区中,生命周期很长,使用不当很容易造成内存泄漏。
  • 解析:jvm将常量池内的符号引用(常量名)转换为直接引用(地址)
3、初始化 执行类变量赋值和静态代码块
Class.forName和ClassLoader的区别? 在了解了类装载过程之后我们继续比较二者区别:
Classloder.loaderClass(String name)
其实该方法内部调用的是:Classloder. loadClass(name, false)
方法:Classloder. loadClass(String name, boolean resolve)
a:参数name代表类的全限定类名
b:参数resolve代表是否解析,resolve为true是解析该类
Class.forName(String name)
其实该方法内部调用的是:Class.forName(className, true, ClassLoader.getClassLoader(caller))
方法:Class.forName0(String name, boolean initialize, ClassLoader loader)
参数name代表全限定类名
参数initialize表示是否初始化该类,为true是初始化该类
参数loader 对应的类加载器
两者最大的区别
  • Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。也会加载静态方法。
  • classloader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
  • Class.forName(name,initialize,loader)带参数也可控制是否加载static块。并且只有调用了newInstance()方法才执行构造函数,创建类的对象。
【Class类简介】测试代码
package com.kuang; public class ClassloaderAndForNameTest { public static void main(String[] args) { String wholeNameLine = "com.kuang.Line"; String wholeNamePoint = "com.kuang.Point"; System.out.println("下面是测试Classloader的效果"); testClassloader(wholeNameLine, wholeNamePoint); System.out.println(); System.out.println("下面是测试Class.forName的效果"); testForName(wholeNameLine, wholeNamePoint); }/** * classloader * @param wholeNameLine * @param wholeNamePoint */ private static void testClassloader(String wholeNameLine, String wholeNamePoint) { Class line; Class point; ClassLoader loader = ClassLoader.getSystemClassLoader(); try { line = loader.loadClass(wholeNameLine); point = loader.loadClass(wholeNamePoint); System.out.println("line " + line.getName()); System.out.println("point " + point.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } }/** * Class.forName * @param wholeNameLine * @param wholeNamePoint */ private static void testForName(String wholeNameLine, String wholeNamePoint) { try { Class line = Class.forName(wholeNameLine); Class point = Class.forName(wholeNamePoint); System.out.println("line" + line.getName()); System.out.println("point" + point.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); }} }class Point { static { System.out.println("静态代码块执行: loading point"); } public static String s = getString(); private static String getString() { System.out.println("静态方法执行给静态变量赋值:loading point"); return "mask"; }public static void test() { System.out.println("普通静态方法执行:loading point"); }{ System.out.println("point普通代码块"); }public Point() { System.out.println("point构造方法执行"); } } class Line { static { System.out.println("静态代码块执行: loading line"); }public static String s = getString(); private static String getString() { System.out.println("给静态变量赋值的静态方法执行:loading line"); return "mask"; }public static void test() { System.out.println("普通静态方法执行:loading line"); }{ System.out.println("普通代码块"); }public Line() { System.out.println("构造方法执行"); }}//输出结果: //下面是测试Classloader的效果 //line com.kuang.Line //point com.kuang.Point // //下面是测试Class.forName的效果 //静态代码块执行: loading line //给静态变量赋值的静态方法执行:loading line //静态代码块执行: loading point //静态方法执行给静态变量赋值:loading point //linecom.kuang.Line //pointcom.kuang.Point

    推荐阅读