1、java.lang.Class

Class是一个非常有用的类,在jvm底层很多功能都是通过这个类实现的;

Object是所有类的父类,所有类都是Class的实例:

public final
    class Class<T> implements java.io.Serializable,
                              java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;   //8192
    private static final int ENUM      = 0x00004000;   //16384
    private static final int SYNTHETIC = 0x00001000;   //4096

final声明的类,表明该类不能被继承,属性和方法不能被复写;

 

private static native void registerNatives();  
    static {
        registerNatives();
    }

利用静态块调动静态方法,这个方法时native声明的,表明是调用系统方法; RegisterNatives将本地对象向VM进行登记,使得VM迅速找到;

 执行顺序:是看该属性有没有分配到空间(载体);如果有空间就执行,没有空间的要创建空间后(实例化、初始化)才执行;方法有没有被调用,被调用后才被执行;

private Class() {}

构造方法私有化,外部不能创建实例,通过只有内部类创建和获得实例,或者通过A getA(){return new A();}方式获得;

 public String toString() {
       return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) + getName();
    }

 覆写toString()方法,返回接口名,基本数据类型,类名,比如:

  Class clazz = int.class;
  System.out.println(clazz.toString());  //int

 

参考文档:http://msdn.microsoft.com/zh-cn/library/aa989577(v=vs.80).aspx ;

                  jdk api中文版

 

1、public static Class forName(java.lang.String className);

获得Class实例的4种方法:
Class clazz = Class.forName("java.lang.String");
Class clazz = String.class;
Class clazz = new String("").getClass();
Class clazz2 = Integer.Type;             //这种获得Class实例的方法只适合包装类
System.out.println(clazz2.toString());   //返回的基本类 :int
2、 public static Class forName(String className, boolean initialize, ClassLoader loader);

    方法1调用方法2

ClassLoader:根据className来加载这个class类;
3、public java.lang.Class[] getClasses() 得到当前类中定义的public内部类/接口:
public class Demo1 {
	private class Demo1a{}
        class Demo1b{}
        public class Demo1c{}
        public interface Demo1d{}
        public String str;
}
 test: 
public static void main(String[] args) {
	Class clazz = Demo1.class;
	Class[] claz = clazz.getClasses();
	System.out.println(claz.length);
	for(int i= 0; i<claz.length;i++){
		System.out.println(claz[i].getName());
	}
}
输出:
2
org.skx.test.Demo1$Demo1c
org.skx.test.Demo1$Demo1d
4、public java.lang.ClassLoader getClassLoader() ,获得类加载器:
Class clazz1 = String.class;
Class clazz2 = Demo1.class;
System.out.println(clazz1.getClassLoader());
System.out.println(clazz2.getClassLoader());
输出:
null
sun.misc.Launcher$AppClassLoader@15253d5
为什么第一个的类加载器为null ? 因为它是由启动类Bootstrap加载器完成加载的,启动类加载是所有类加载器的父类,返回值都为null, 类加载器将在以后章节详解;

 

5、public java.lang.Class getComponentType() ,获得一个数组的组件类型

Class clazz = new Demo1[4].getClass();
System.out.println(clazz.getComponentType());
输出:
class org.skx.test.Demo1
6、public java.lang.reflect.Constructor   getConstructor(java.lang.Class[] parameterTypes) ,获得public,含参的  构造方法,唯一匹配; 
Demo1(){}
public  Demo1(String str){System.out.println("ok");}
public  Demo1(String str,int x){System.out.println("ok");}
private  Demo1(String str,int x,String s){System.out.println("ok");}  //非public的构造方法
  测试:
try{
	Class clazz = Demo1.class;
	Class[] argss = new Class[3];
	argss[0] = String.class;
	argss[1] = int.class;
	argss[2] = String.class;
	System.out.println(clazz.getConstructor(argss[0]));
	System.out.println(clazz.getConstructor(argss[0],argss[1]));
	System.out.println(clazz.getConstructor(argss[0],argss[1],argss[2]));  //抛出异常
}catch (NoSuchMethodException e){
	System.out.println("找不到这个构造方法");
}
输出:
public org.skx.test.Demo1(java.lang.String)
public org.skx.test.Demo1(java.lang.String,int)
找不到这个构造方法
 7、public java.lang.reflect.Constructor[]  getConstructors()    获得public的构造方法,返回数组
Class clazz = Demo1.class;
Constructor[] constructor = clazz.getConstructors();
System.out.println(constructor.length);
for(int i=0; i<constructor.length;i++){
      System.out.println(constructor[i]);
}
输出:
2
public org.skx.test.Demo1(java.lang.String,int)
public org.skx.test.Demo1(java.lang.String)
 8、public java.lang.reflect.Constructor  getDeclaredConstructor(java.lang.Class[ ] parameterTypes)  唯一匹配,从所用声明过的构造方法中,不管是不是public的:

       复制6的测试,改写为:

System.out.println(clazz.getDeclaredConstructor());			
System.out.println(clazz.getDeclaredConstructor(argss[0]));			
System.out.println(clazz.getDeclaredConstructor(argss[0],argss[1]));			
System.out.println(clazz.getDeclaredConstructor(argss[0],argss[1],argss[2]))
输出:
org.skx.test.Demo1()
public org.skx.test.Demo1(java.lang.String)
public org.skx.test.Demo1(java.lang.String,int)
private org.skx.test.Demo1(java.lang.String,int,java.lang.String)
 9、public java.lang.reflect.Constructor[ ]  getDeclaredConstructors() ,放回所有构造方法数组;

 

10、在方法3中,获取的是public的内部类,这里获取所有的内部类;public java.lang.Class[ ] getDeclaredClasses();

 

11、public java.lang.reflect.Field getField(java.lang.String fieldName) 获得public 配对的属性:

Class clazz = Demo1.class;
try {
	System.out.println(clazz.getField("str"));
} catch (NoSuchFieldException e) {
	System.out.println("没有找到这个属性");
}

12、public java.lang.reflect.Field[ ] getFields()  获得public声明的属性

13、public java.lang.reflect.Field getDeclaredField(java.lang.String fieldName)

14、public java.lang.reflect.Field[ ] getDeclaredFields()  

 

15、public java.lang.reflect.Method getMethod(java.lang.String methodName, java.lang.Class[ ] parameterTypes)  获得public 匹配的方法:

Demo1:
//  public void say0(){System.out.println(str);}
    public void say0(String str){System.out.println(str);}
    private void say1(int a){System.out.println(a);}
    public void say(String str,int a){System.out.println("ok");} 

 test:

Class clazz = Demo1.class;
try {
	System.out.println(clazz.getMethod("say0", null));
} catch (NoSuchMethodException e) {
	System.out.println("没有找到say0()方法");
}	
			
try {
	System.out.println(clazz.getMethod("say0", String.class));
} catch (NoSuchMethodException e) {
	System.out.println("没有找到say0(String str)方法");
}
			
try {
	System.out.println(clazz.getMethod("say1",int.class));
} catch (NoSuchMethodException e) {
	System.out.println("没有找到say1(int a)方法");
}
			
try {
	System.out.println(clazz.getMethod("say",String.class,int.class));
} catch (NoSuchMethodException e) {
	System.out.println("没有找到say(String str,int a)方法");
}

输出:
没有找到say0()方法
public void org.skx.test.Demo1.say0(java.lang.String)
没有找到say1(int a)方法
public void org.skx.test.Demo1.say(java.lang.String,int)

16、public java.lang.reflect.Method[ ] getMethods() ,获取public声明的所有方法

17、public java.lang.reflect.Method getDeclaredMethod(java.lang.String methodName, java.lang.Class[ ] parameterTypes)

18、public java.lang.reflect.Method[ ] getDeclaredMethods()

 

19、public java.lang.Class[ ] getInterfaces() 获得接口数组,如

Demo impliments  INinterface{}

 

20、public int getModifiers(),获取修饰符,如public,abstract,private等的声明符,注意返回的是int型的;使用Modifier.toString(int a)进行转换

Class clazz = Demo1.class;
int x=clazz.getModifiers();
System.out.println(x);
System.out.println(Modifier.toString(x)); 
输出:
1
public

 Modifier.toString(int x)

 public static String toString(int mod) {
        StringBuffer sb = new StringBuffer();
        int len;

        if ((mod & PUBLIC) != 0)        sb.append("public ");
        if ((mod & PROTECTED) != 0)     sb.append("protected ");
        if ((mod & PRIVATE) != 0)       sb.append("private ");
        if ((mod & ABSTRACT) != 0)      sb.append("abstract ");
        if ((mod & STATIC) != 0)        sb.append("static ");
        if ((mod & FINAL) != 0)         sb.append("final ");
        if ((mod & TRANSIENT) != 0)     sb.append("transient ");
        if ((mod & VOLATILE) != 0)      sb.append("volatile ");
        if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");
        if ((mod & NATIVE) != 0)        sb.append("native ");
        if ((mod & STRICT) != 0)        sb.append("strictfp ");
        if ((mod & INTERFACE) != 0)     sb.append("interface ");

        if ((len = sb.length()) > 0)    /* trim trailing space */
            return sb.toString().substring(0, len-1);
        return "";
    }

 

21、getName()

 

22、public java.lang.Class getSuperclass()

23、public Type getGenericSuperclass() //获得含泛型参数的父类

24、public Type[] getGenericInterfaces() { //获得带泛型参数的接口

 

25、public java.lang.Object newInstance() 创建实例

public T newInstance()throws InstantiationException, IllegalAccessException{
        if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
        }
        return newInstance0();
    }

这里对SecurityManager这个类说明一下,安全管理类java.lang.SecurityManager,通过抛出异常来提供阻止操作完成的机会。该类的方法以checkXXX命名,如果允许执行,安全管理器不做任何操作,但如果不允许执行该操作,抛出一个 SecurityException,唯一例外是 checkTopLevelWindow,它返回 boolean 值。通过System.getSecurityManager()获取一个实例(通过set设置一个实例,SecurityManager在System静态设置获取);checkMemberAccess表示:如果不允许调用线程访问程序,抛出 SecurityException

 

private volatile transient Constructor<T> cachedConstructor;
private volatile transient Class<?>       newInstanceCallerCache;

这里有两个关键字:volatile['v?l?ta?l]和transient['trænz??nt]以前没有接触过,他们是什么意思呢?字面意思易变的和短暂的,这里简单说明一下

volatile的适用:在多线程机制中,每个线程中有一块memory来保存资源的副本,方便自己访问以提高运行效率,使用synchronized声明一个方法,使得对象对资源的访问变为直接向主资源访问并在访问时进行加锁;volatile声明一个属性,VM限制其他对象拷贝这个成员变量,只能直接访问这个变量;

Java的serialization提供了一种持久化(串行化)对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。 transient是Java语言的关键字,用来表示一个域是不会被该对象 串行化。当一个对象被串行化的时候,transient型变量不会被串行化,然而非transient型的变量被序列化。

 

public native boolean isInstance(Object obj);

通过系统程序来判断一个对象是不是clazz所代表类的实例;

Class clazz = Arrays.class;
String obj = "ok";
System.out.println(clazz.isInstance(obj));  //false  表示判断obj是否为clazz的实列

 

判断两个类是否相同,或判断是否为另一个类的父类/接口

public native boolean isAssignableFrom(Class<?> cls);
public class TestUtil  extends FileUtil implements TestInt{
	public static void main(String[] args) throws Exception {
		Class clazz = TestUtil.class;
		Class clazz2 = FileUtil.class;
		Class intE = TestInt.class;
		System.out.println(clazz.isAssignableFrom(clazz));  //true
		System.out.println(clazz2.isAssignableFrom(clazz)); //true注意是clazz是从clazz2派生而来的
		System.out.println(intE.isAssignableFrom(clazz));   //true表示clazz AssignableFrom intE;
}}

 

 判断类是否为接口、数组、基本数据类型;

public native boolean isInterface();
public native boolean isArray();
public native boolean isPrimitive();
Class intE = TestInt.class;
Class arr = Class.forName("java.util.Arrays");
Class arr2 = new int[4].getClass();
Class primi = int.class;
System.out.println(intE.isInterface()+"||"+arr.isArray()+"||"+arr2.isArray()+"||"+primi.isPrimitive());
//true||false||true||true

为什么arr不是一个Array呢?因为Arrays只是一个普通类,就好比你顺便写了个类,你觉得那是数组,jvm不会执行你的类来判断是不是数组(jvm不会给类分配执行内存),所以jvm不是根据名字就判断出他是不是数组,应该是根据名字找到类所在的.class文件;而接口和基本类可以判断出来,可能是接口有interface关键字声明,基本数据类型用相应的关键字(就不用在内存中去查看,就能判断是不是接口和基本类了);如何判断是不是一个数组呢?先创建一个数组实列new int[4];添加getClass()就返回了一个Class实列,可以通过clazz.getName()查看到底返回了一个怎么样的类型:[I ,而不是想象的java.util.Arrays,这又是怎么回事呢?假如现在创建的是一个new  long[4],返回了[J;double[4]返回[D;float[4] 返回[F;short[4]返回[S;byte[4]返回[B;char[4],返回[C;boolean[4]返回[Z,;new  String[4]返回[Ljava.lang.String;Double[4]返回[Ljava.lang.Double;Arrays[4]返回[Ljava.util.Arrays;FileUtil[4]返回[Lorg.skx.api  发现了一个规律:基本类数组返回是[+“X”,而其他基本类返回的是一个[+“X”+包.类;还是因为jvm从头到尾都不知道Arrays是干什么的!所以只返回基本类型的数组表示如int型为[I;只有在new开辟了一个内存之后,jvm能通过内存得知这是一个对象数组的形式(数组都可以称为对象数组,有些是基本类型数组);并得到他的相关属性;

Class clazz = String.class;
System.out.println(clazz.isArray()); //false  clazz只能等到String的类名、包名、属性、方法、等等,但不能知道String在内存中是个什么形式;
new int[3][4][5][6][7][8][9]).getClass().getName()
     returns "[[[[[[[I"

isInterface()和isPrimitive()在Class.toString()中被调用;

 

public boolean isAnnotation() {
    return (getModifiers() & ANNOTATION) != 0;
}

 判断该类是不是一个注解类,比如:

import java.lang.annotation.*;
@Target(ElementType.TYPE)    
@Retention(RetentionPolicy.RUNTIME)  
public @interface Annotation1 {    //创建一个注解类
    String value();  
} 

Class anno = Annotation1.class;
System.out.println(anno.isAnnotation());

 

判断一个类是不是复合类:内部类是复合类,但只会返回false;

public boolean isSynthetic() {
     return (getModifiers() & SYNTHETIC) != 0;
}

 查看资料:isSynthetic()是用来判断Class是不是“复合类”。这在java应用程序中只会返回false,不会返回true。因为,JVM中才会产生复合类,在java应用程序中不存在“复合类”!

  

获得类<变量>:获得泛型参数,不是一般的变量:

public TypeVariable<Class<T>>[] getTypeParameters()
public class Demo1<E,T> {
   private String str = "ok";
   private int x = 32;
   private long[] l = {2,3,4,5,6};
}
Class demo1 = Demo1.class;
TypeVariable[] attr = demo1.getTypeParameters();
	for(int i=0;i<attr.length;i++){
		System.out.println(attr[i].toString());  //或者getName();
	}  //E,T

  

获得包名:

  public Package getPackage() {

 

获得方法里面的 局部类(含匿名类),比如:

  public Method getEnclosingMethod() {
public class Demo6 {
    Object say(){
    	class A{
    		A(){
    			System.out.println("hello");
    		}
    	}
    	return new A();
    }
}
Class clazz =new  Demo6().say().getClass();  //得到A
System.out.println(clazz.getEnclosingMethod());  //A是通过这个方法创建的
hello
java.lang.Object org.skx.api.Demo6.say()	
 public Constructor<?> getEnclosingConstructor()

 

如果该 Class 对象表示构造方法中的一个本地或匿名类,则返回 Constructor 对象,它表示底层类的立即封闭构造方法。否则返回 null。实现方法同上

 

其他的方法暂不再介绍,没有发现如何获取import字段的方法,

如何获取属性是什么类型和方法返回类型,查看Field和Method的相关方法;

这里讲解了如何获取:包名,声明符,类名,泛型参数,接口,父类名,构造方法,属性,一般方法,判断是否为接口、基本类、数组、注解等;

创建Class的4中方法,获取类加载器,获取数组组件类型;

 

猜你喜欢

转载自nickfover.iteye.com/blog/2124089