java.lang.Class 类是进行反射操作的源头,所有的反射操作都是基于该类。

java.lang.Class 类的声明

  1. public final class Class<T> implements java.io.Serializable,
  2. GenericDeclaration,
  3. Type,
  4. AnnotatedElement {
  5. }

java.lang.Class 类的特性

  1. 对于每一种类,Java虚拟机都会初始化出一个Class类型的实例,每当我们编写并且编译一个新创建的类就会产生一个对应Class对象,并且这个Class对象会被保存在同名.class文件里
  2. 当我们new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载器系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要实例对象或者提供静态变量的引用值,
  3. 构造器是私有的,只有JVM才可以调用这个构造函数创建Class的对象

    1. private Class(ClassLoader loader) {
    2. classLoader = loader;
    3. }
  4. 每个class(注意class是小写,代表普通类)类,无论创建多少个实例对象,在JVM中都对应同一个Class对象


获取 Class 对象

  1. 通过className.class来获取

    • 该方法获取的Class对象不执行静态块和动态构造块
    • 基本类型同样可以使用这种方法
      1. Class cb = boolean.class;
      2. Class cs = String.class;
      3. Class<int[]> intArray = int[].class; // class [I
      4. Class<double[]> doubleArray = double[].class; // class [D
      5. Class<boolean[]> booleanArray = boolean[].class; // class [Z
      6. Class<String[]> stringArray = String[].class; // class [Ljava.lang.String;
  2. 通过Class.forName()来获取,参数为类的全限定名

    • 该方法获取的Class对象只执行静态块、而不执行动态构造块
    • 基本类型无法使用此方法 ```java //通过Class.forName()方法加载的类,采用的是系统类加载器 Class c = Class.forName(“java.lang.String”);

/ 对于数组比较特殊 / //相当于double[].class Class cDoubleArray = Class.forName(“[D”);
//相当于String[][].class Class cStringArray = Class.forName(“[[Ljava.lang.String;”);

// int[].class 有两个方法 boolean[].class.toString(); // class [Z boolean[].class.toGenericString(); // public abstract final class [Z // 因此可以使用下述方法加载数组类 Class<?> boolArray = Class.forName(boolean[].class.toString());

  1. 3. 通过Object.getClass()来获取
  2. - 该方法获取的Class对象因为需要创建对象,所以会执行静态块和动态构造块
  3. - 基本类型无法使用这种方法
  4. 4. 基本类型和void 类型的包装类可以使用TYPE字段获取**
  5. ```java
  6. Class c = Double.TYPE; //等价于 double.class.
  7. Class c = Void.TYPE;

各种获取 Class 对象的不同点:

  • className.class 和 Object.getClass() 获取 Class 对象,必须 JVM 中先有 Class 对象才可以进行获取
  • Class.forName(String name) 可以在 Class 不存在时保持编译的正确性,可以用于框架设计 ```java class Test{ {
    1. System.out.println("代码块执行!");
    } static {
    1. System.out.println("静态代码块执行!");
    } }

public class ClassObtain { public static void main(String[] args) throws ClassNotFoundException { // 1.ClassName.class:不执行代码块和静态代码块 final Class testClass = Test.class; // 2.Class.forName:执行静态代码块 final Class<?> aClass = Class.forName(“top.songfang.Test”); // 3.Object.getClass:由于创建对象,代码块和静态代码块均执行 final Test test = new Test(); final Class<? extends Test> aClass1 = test.getClass(); } }

  1. <a name="WUEw6"></a>
  2. #### Class 类的常用方法
  3. <a name="XEgg7"></a>
  4. ##### 获取类的基本信息
  5. 1. 获取类所在的包:
  6. - public Package getPackage()
  7. 2. 类的声明方式:
  8. - String getName():以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称(全限定名:**包名.类名**)
  9. - String getCanonicalName():返回 Java Language Specification 中所定义的底层类的规范化名称,即(**包名.类名**)
  10. - **String getSimpleName()**:返回源代码中给出的底层类的简称,即(**类名**)
  11. 3. 获取父类:
  12. - public Class<? super T> getSuperclass()
  13. 4. 获取所有的父接口:
  14. - public Class<?>[] getInterfaces()
  15. <a name="9pWz6"></a>
  16. ##### 判断类方法:
  17. 1. boolean isLocalClass() :判断是不是局部类,也就是方法里面的类<br />
  18. 1. boolean isMemberClass() :判断是不是成员内部类,也就是一个类里面定义的类<br />
  19. 1. boolean isAnonymousClass():判断当前类是不是匿名类,匿名类一般用于实例化接口<br />
  20. 1. boolean isAnnotation():判断当前Class对象是否是注释类型<br />
  21. 1. boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) :如果指定类型的注释存在于此元素上,则返回 true,否则返回 false<br />
  22. 1. boolean isAssignableFrom(Class<?> cls) :判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口<br />
  23. 1. boolean isEnum() :当且仅当该类声明为源代码中的枚举时返回 true<br />
  24. 1. boolean isArray():判定此Class对象所对应的是否是一个数组对象<br />
  25. 1. boolean isInstance(Object obj) :判定指定的 Object 是否与此 Class 所表示的对象赋值兼容,此方法是 Java 语言 instanceof 操作的动态等价方法<br />
  26. 1. boolean isInterface():判定指定的 Class 对象是否表示一个接口类型<br />
  27. 1. boolean isPrimitive():判定指定的 Class 对象是否表示一个 Java 基本类型<br />
  28. 1. boolean isSynthetic():如果此类是复合类,则返回 true,否则 false
  29. <a name="3ePwM"></a>
  30. ##### getResource 方法
  31. Class.getResource 与 ClassLoader.getResource 的路径:
  32. > java中获取资源时,经常用到 Class.getResource(String path) 和ClassLoader.getResource(String path) ,两个 path 的要求不一样
  33. 1. Class.getResource(String path) 或 Class.getResourceAsStream(String path):path支持相对路径和绝对路径
  34. - path 不以 "/" 开头时,默认是从**此类所在的包下获取资源**<br />
  35. - path 以 "/" 开头时,则是从 **ClassPath 根下获取**
  36. 2. Class.getClassLoader().getResource(String path) 或 Class.getClassLoader().getResourceAsStream(String path):
  37. - path是从 ClassPath 根下获取<br />
  38. - path不支持绝对路径,即不能以 "/" 开头
  39. ```java
  40. public class Test {
  41. public static void main(String[] args) {
  42. System.out.println("Test.class.getResource(\"\") = " + Test.class.getResource(""));
  43. System.out.println("Test.class.getResource(\"/\") = " + Test.class.getResource("/"));
  44. System.out.println("Test.class.getClassLoader().getResource(\"\") = " +
  45. Test.class.getClassLoader().getResource(""));
  46. System.out.println("Test.class.getClassLoader().getResource(\"/\") = " +
  47. Test.class.getClassLoader().getResource("/"));
  48. System.out.println("Thread.currentThread().getContextClassLoader().getResource(\"\") = " +
  49. Thread.currentThread().getContextClassLoader().getResource(""));
  50. System.out.println("Thread.currentThread().getContextClassLoader().getResource(\"/\") = " +
  51. Thread.currentThread().getContextClassLoader().getResource("/"));
  52. }
  53. }
  54. // 控制台输出
  55. Test.class.getResource("") = file:/D:/template/basic/thread/target/classes/top/songfang/file/
  56. Test.class.getResource("/") = file:/D:/template/basic/thread/target/classes/
  57. Test.class.getClassLoader().getResource("") = file:/D:/template/basic/thread/target/classes/
  58. Test.class.getClassLoader().getResource("/") = null
  59. Thread.currentThread().getContextClassLoader().getResource("") = file:/D:/template/basic/thread/target/classes/
  60. Thread.currentThread().getContextClassLoader().getResource("/") = null