java.lang.Class 类是进行反射操作的源头,所有的反射操作都是基于该类。
java.lang.Class 类的声明
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
}
java.lang.Class 类的特性
- 对于每一种类,Java虚拟机都会初始化出一个Class类型的实例,每当我们编写并且编译一个新创建的类就会产生一个对应Class对象,并且这个Class对象会被保存在同名.class文件里
- 当我们new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载器系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要实例对象或者提供静态变量的引用值,
构造器是私有的,只有JVM才可以调用这个构造函数创建Class的对象
private Class(ClassLoader loader) {
classLoader = loader;
}
每个class(注意class是小写,代表普通类)类,无论创建多少个实例对象,在JVM中都对应同一个Class对象
获取 Class 对象
通过className.class来获取
- 该方法获取的Class对象不执行静态块和动态构造块
- 基本类型同样可以使用这种方法
Class cb = boolean.class;
Class cs = String.class;
Class<int[]> intArray = int[].class; // class [I
Class<double[]> doubleArray = double[].class; // class [D
Class<boolean[]> booleanArray = boolean[].class; // class [Z
Class<String[]> stringArray = String[].class; // class [Ljava.lang.String;
通过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());
3. 通过Object.getClass()来获取
- 该方法获取的Class对象因为需要创建对象,所以会执行静态块和动态构造块
- 基本类型无法使用这种方法
4. 基本类型和void 类型的包装类可以使用TYPE字段获取**
```java
Class c = Double.TYPE; //等价于 double.class.
Class c = Void.TYPE;
各种获取 Class 对象的不同点:
- className.class 和 Object.getClass() 获取 Class 对象,必须 JVM 中先有 Class 对象才可以进行获取
- Class.forName(String name) 可以在 Class 不存在时保持编译的正确性,可以用于框架设计
```java
class Test{
{
} static {System.out.println("代码块执行!");
} }System.out.println("静态代码块执行!");
public class ClassObtain {
public static void main(String[] args) throws ClassNotFoundException {
// 1.ClassName.class:不执行代码块和静态代码块
final Class
<a name="WUEw6"></a>
#### Class 类的常用方法
<a name="XEgg7"></a>
##### 获取类的基本信息
1. 获取类所在的包:
- public Package getPackage()
2. 类的声明方式:
- String getName():以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称(全限定名:**包名.类名**)
- String getCanonicalName():返回 Java Language Specification 中所定义的底层类的规范化名称,即(**包名.类名**)
- **String getSimpleName()**:返回源代码中给出的底层类的简称,即(**类名**)
3. 获取父类:
- public Class<? super T> getSuperclass()
4. 获取所有的父接口:
- public Class<?>[] getInterfaces()
<a name="9pWz6"></a>
##### 判断类方法:
1. boolean isLocalClass() :判断是不是局部类,也就是方法里面的类<br />
1. boolean isMemberClass() :判断是不是成员内部类,也就是一个类里面定义的类<br />
1. boolean isAnonymousClass():判断当前类是不是匿名类,匿名类一般用于实例化接口<br />
1. boolean isAnnotation():判断当前Class对象是否是注释类型<br />
1. boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) :如果指定类型的注释存在于此元素上,则返回 true,否则返回 false<br />
1. boolean isAssignableFrom(Class<?> cls) :判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口<br />
1. boolean isEnum() :当且仅当该类声明为源代码中的枚举时返回 true<br />
1. boolean isArray():判定此Class对象所对应的是否是一个数组对象<br />
1. boolean isInstance(Object obj) :判定指定的 Object 是否与此 Class 所表示的对象赋值兼容,此方法是 Java 语言 instanceof 操作的动态等价方法<br />
1. boolean isInterface():判定指定的 Class 对象是否表示一个接口类型<br />
1. boolean isPrimitive():判定指定的 Class 对象是否表示一个 Java 基本类型<br />
1. boolean isSynthetic():如果此类是复合类,则返回 true,否则 false
<a name="3ePwM"></a>
##### getResource 方法
Class.getResource 与 ClassLoader.getResource 的路径:
> java中获取资源时,经常用到 Class.getResource(String path) 和ClassLoader.getResource(String path) ,两个 path 的要求不一样
1. Class.getResource(String path) 或 Class.getResourceAsStream(String path):path支持相对路径和绝对路径
- path 不以 "/" 开头时,默认是从**此类所在的包下获取资源**<br />
- path 以 "/" 开头时,则是从 **ClassPath 根下获取**
2. Class.getClassLoader().getResource(String path) 或 Class.getClassLoader().getResourceAsStream(String path):
- path是从 ClassPath 根下获取<br />
- path不支持绝对路径,即不能以 "/" 开头
```java
public class Test {
public static void main(String[] args) {
System.out.println("Test.class.getResource(\"\") = " + Test.class.getResource(""));
System.out.println("Test.class.getResource(\"/\") = " + Test.class.getResource("/"));
System.out.println("Test.class.getClassLoader().getResource(\"\") = " +
Test.class.getClassLoader().getResource(""));
System.out.println("Test.class.getClassLoader().getResource(\"/\") = " +
Test.class.getClassLoader().getResource("/"));
System.out.println("Thread.currentThread().getContextClassLoader().getResource(\"\") = " +
Thread.currentThread().getContextClassLoader().getResource(""));
System.out.println("Thread.currentThread().getContextClassLoader().getResource(\"/\") = " +
Thread.currentThread().getContextClassLoader().getResource("/"));
}
}
// 控制台输出
Test.class.getResource("") = file:/D:/template/basic/thread/target/classes/top/songfang/file/
Test.class.getResource("/") = file:/D:/template/basic/thread/target/classes/
Test.class.getClassLoader().getResource("") = file:/D:/template/basic/thread/target/classes/
Test.class.getClassLoader().getResource("/") = null
Thread.currentThread().getContextClassLoader().getResource("") = file:/D:/template/basic/thread/target/classes/
Thread.currentThread().getContextClassLoader().getResource("/") = null