认识Class对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RRTI的说法则是源于《Thinking in Java》一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种:传统的”RRTI”,它假定我们在编译期已知道了所有类型(在没有反射机制创建和使用类对象时,一般都是编译期已确定其类型,如new对象时该类必须已定义好),另外一种是反射机制,它允许我们在运行时发现和使用类型的信息。在Java中用来表示运行时类型信息的对应类就是Class类,Class类也是一个实实在在的类,存在于JDK的java.lang包中,其部分源码如下:
public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type, AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
/*
* Private constructor. Only the Java Virtual Machine creates Class objects.(私有构造,只能由JVM创建该类)
* This constructor is not used and prevents the default constructor being
* generated.
*/
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}1234567891011121314151617181920
前面我们已提到过,Class对象是由JVM加载的,那么其加载时机是?实际上所有的类都是在对其第一次使用时动态加载到JVM中的,当程序创建第一个对类的静态成员引用时,就会加载这个被使用的类(实际上加载的就是这个类的字节码文件),注意,使用new操作符创建类的新实例对象也会被当作对类的静态成员的引用(构造函数也是类的静态方法),由此看来Java程序在它们开始运行之前并非被完全加载到内存的,其各个部分是按需加载,所以在使用该类时,类加载器首先会检查这个类的Class对象是否已被加载(类的实例对象创建时依据Class对象中类型信息完成的),如果还没有加载,默认的类加载器就会先根据类名查找.class文件(编译后Class对象被保存在同名的.class文件中),在这个类的字节码文件被加载时,它们必须接受相关验证,以确保其没有被破坏并且不包含不良Java代码(这是java的安全机制检测),完全没有问题后就会被动态加载到内存中,此时相当于Class对象也就被载入内存了(毕竟.class字节码文件保存的就是Class对象),同时也就可以被用来创建这个类的所有实例对象。下面通过一个简单例子来说明Class对象被加载的时机问题(例子引用自Thinking in Java):
package com.zejian;
class Candy {
static { System.out.println("Loading Candy"); }
}
class Gum {
static { System.out.println("Loading Gum"); }
}
class Cookie {
static { System.out.println("Loading Cookie"); }
}
public class SweetShop {
public static void print(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
print("inside main");
new Candy();
print("After creating Candy");
try {
Class.forName("com.zejian.Gum");
} catch(ClassNotFoundException e) {
print("Couldn't find Gum");
}
print("After Class.forName(\"com.zejian.Gum\")");
new Cookie();
print("After creating Cookie");
}
}1234567891011121314151617181920212223242526272829303132
class Initable {
//编译期静态常量
static final int staticFinal = 47;
//非编期静态常量
static final int staticFinal2 =
ClassInitialization.rand.nextInt(1000);
static {
System.out.println("Initializing Initable");
}
}
class Initable2 {
//静态成员变量
static int staticNonFinal = 147;
static {
System.out.println("Initializing Initable2");
}
}
class Initable3 {
//静态成员变量
static int staticNonFinal = 74;
static {
System.out.println("Initializing Initable3");
}
}
public class ClassInitialization {
public static Random rand = new Random(47);
public static void main(String[] args) throws Exception {
//字面常量获取方式获取Class对象
Class initable = Initable.class;
System.out.println("After creating Initable ref");
//不触发类初始化
System.out.println(Initable.staticFinal);
//会触发类初始化
System.out.println(Initable.staticFinal2);
//会触发类初始化
System.out.println(Initable2.staticNonFinal);
//forName方法获取Class对象
Class initable3 = Class.forName("Initable3");
System.out.println("After creating Initable3 ref");
System.out.println(Initable3.staticNonFinal);
}
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
执行结果:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74123456789
public class C {
static void test(Object x) {
print("Testing x of type " + x.getClass());
print("x instanceof A " + (x instanceof A));
print("x instanceof B "+ (x instanceof B));
print("A.isInstance(x) "+ A.class.isInstance(x));
print("B.isInstance(x) " +
B.class.isInstance(x));
print("x.getClass() == A.class " +
(x.getClass() == A.class));
print("x.getClass() == B.class " +
(x.getClass() == B.class));
print("x.getClass().equals(A.class)) "+
(x.getClass().equals(A.class)));
print("x.getClass().equals(B.class)) " +
(x.getClass().equals(B.class)));
}
public static void main(String[] args) {
test(new A());
test(new B());
}
}1234567891011121314151617181920212223242526
执行结果:
Testing x of type class com.zejian.A
x instanceof A true
x instanceof B false //父类不一定是子类的某个类型
A.isInstance(x) true
B.isInstance(x) false
x.getClass() == A.class true
x.getClass() == B.class false
x.getClass().equals(A.class)) true
x.getClass().equals(B.class)) false
---------------------------------------------
Testing x of type class com.zejian.B
x instanceof A true
x instanceof B true
A.isInstance(x) true
B.isInstance(x) true
x.getClass() == A.class false
x.getClass() == B.class true
x.getClass().equals(A.class)) false
x.getClass().equals(B.class)) true12345678910111213141516171819
/**
* Created by zejian on 2017/5/1.
* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
*/
public class ReflectDemo implements Serializable{
public static void main(String[] args) throws Exception {
System.out.println("-----getDeclaringClass-----");
Class uclazz=cs3.getDeclaringClass();
//Constructor对象表示的构造方法的类
System.out.println("构造方法的类:"+uclazz.getName());
class Person{
public int age;
public String name;
//省略set和get方法
}
class Student extends Person{
public String desc;
private int score;
//省略set和get方法
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
/**
* 接收一个泛型数组,然后创建一个长度与接收的数组长度一样的泛型数组,
* 并把接收的数组的元素复制到新创建的数组中,
* 最后找出新数组中的最小元素,并打印出来
* @param a
* @param <T>
*/
public <T extends Comparable<T>> void min(T[] a) {
//通过反射创建相同类型的数组
T[] b = (T[]) Array.newInstance(a.getClass().getComponentType(), a.length);
for (int i = 0; i < a.length; i++) {
b = a;
}
T min = null;
boolean flag = true;
for (int i = 0; i < b.length; i++) {
if (flag) {
min = b;
flag = false;
}
if (b.compareTo(min) < 0) {
min = b;
}
}
System.out.println(min);
}1234567891011121314151617181920212223242526
//获取修饰符,返回值可通过Modifier类进行解读
public native int getModifiers();
//获取父类,如果为Object,父类为null
public native Class<? super T> getSuperclass();
//对于类,为自己声明实现的所有接口,对于接口,为直接扩展的接口,不包括通过父类间接继承来的
public native Class<?>[] getInterfaces();
//自己声明的注解
public Annotation[] getDeclaredAnnotations();
//所有的注解,包括继承得到的
public Annotation[] getAnnotations();
//获取或检查指定类型的注解,包括继承得到的
public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
/**
* 内部类相关
*/
//获取所有的public的内部类和接口,包括从父类继承得到的
public Class<?>[] getClasses();
//获取自己声明的所有的内部类和接口
public Class<?>[] getDeclaredClasses();
//如果当前Class为内部类,获取声明该类的最外部的Class对象
public Class<?> getDeclaringClass();
//如果当前Class为内部类,获取直接包含该类的类
public Class<?> getEnclosingClass();
//如果当前Class为本地类或匿名内部类,返回包含它的方法
public Method getEnclosingMethod();
/**
* Class对象类型判断相关
*/
//是否是数组
public native boolean isArray();
//是否是基本类型
public native boolean isPrimitive();
//是否是接口
public native boolean isInterface();
//是否是枚举
public boolean isEnum();
//是否是注解
public boolean isAnnotation();
//是否是匿名内部类
public boolean isAnonymousClass();
//是否是成员类
public boolean isMemberClass();
//是否是本地类
public boolean isLocalClass(); 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051