Java源码解析(3) —— Class(2)

来源:互联网 发布:网络优化工程师的公司 编辑:程序博客网 时间:2024/05/16 11:14

Class 源码详解续(2)

  续Class,详见:Java源码解析(2) —— Class(1)。
  关于嵌套类、内部类、成员类、局部类、匿名类、静态类等知识详见:Java各种称呼类详解。

源码

//以下说的类是Class而非class//如果该Class对象位于一个方法内,返回包含这个类的方法的信息(Method对象)public Method getEnclosingMethod() {...}//如果该方法具有(内部)局部类或匿名类,获取其信息,包括Class对象、name以及描述。private native Object[] getEnclosingMethod0();//获取包含局部类或匿名类的方法的信息private EnclosingMethodInfo getEnclosingMethodInfo() {        Object[] enclosingInfo = getEnclosingMethod0();        if (enclosingInfo == null)            return null;        else {            return new EnclosingMethodInfo(enclosingInfo);        }    }//包含局部类或匿名类的方法的信息描述类private final static class EnclosingMethodInfo {...}//将参数Type对象o转化为Class对象private static Class<?> toClass(Type o) {        if (o instanceof GenericArrayType)            return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),                                     0)                .getClass();        return (Class<?>)o;     }//类似getEnclosingMethod,只是这是针对构造器@CallerSensitivepublic Constructor<?> getEnclosingConstructor() {}//若该类是成员类,返回外部类Class对象,否则返回nullpublic Class<?> getDeclaringClass() {...}private native Class<?> getDeclaringClass0();@CallerSensitive//类似getEnclosingMethod,只是这是针对类public Class<?> getEnclosingClass() {}//如果该类是顶级类,返回null,否则返回该类去除顶级类外后字符串//非顶级类名称命名:顶级类全限定名+$+[(该种类类的,有的话)顺序]+[类名称(如果有的话)]//成员类:com.fcc.test.OuterClass$MemberClass,调用该方法后,返回//$MemberClassprivate String getSimpleBinaryName() {        Class<?> enclosingClass = getEnclosingClass();        if (enclosingClass == null) //无外部类,即为顶级类            return null;        try {            return getName().substring(enclosingClass.getName().length());        } catch (IndexOutOfBoundsException ex) {            throw new InternalError("Malformed class name");        }    }//返回简单类名称(不包含包名)public String getSimpleName() {    if (isArray())//首先判断该类是否是数组            return getComponentType().getSimpleName()+"[]";//是数组,返回形式:元素类名称[]        String simpleName = getSimpleBinaryName();        if (simpleName == null) { //等于null,即该类为顶级类            simpleName = getName();            return simpleName.substring(simpleName.lastIndexOf(".")+1);         //顶级类的简单名称即去掉包名即可         }        int length = simpleName.length();        //非顶级类即嵌套类,却有顶级类名称命名格式,说明这个类命名不合法        if (length < 1 || simpleName.charAt(0) != '$')            throw new InternalError("Malformed class name");        int index = 1;        while (index < length && isAsciiDigit(simpleName.charAt(index)))            index++;        // 找到$字符位置        return simpleName.substring(index);//返回嵌套类名称}//判断字符是否是ASCII码private static boolean isAsciiDigit(char c) {        return '0' <= c && c <= '9';}//除数组外,同getName方法,数组时,getName返回的是[Ljava.lang.String之类的表现//形式,而getCanonicalName返回的就是跟我们声明类似的形式。public String getCanonicalName() {}//判断是否是注释类型public boolean isAnonymousClass() {        return "".equals(getSimpleName());    }//判断是否是局部类public boolean isLocalClass() {        return isLocalOrAnonymousClass() && !isAnonymousClass();    }//判断是否是成员类public boolean isMemberClass() {        return getSimpleBinaryName() != null && !isLocalOrAnonymousClass();        //非顶级类,且不是局部类也不是匿名类,即为成员类    }//判断是否是局部类或匿名类private boolean isLocalOrAnonymousClass() {        return getEnclosingMethodInfo() != null;    }//获取该类中所有公有的成员类//getDeclaredClasses则是获取所有成员类Class对象    @CallerSensitivepublic Class<?>[] getClasses() {}//获取所有公有字段@CallerSensitive    public Field[] getFields() throws SecurityException {...}//获取所有公有方法@CallerSensitive    public Method[] getMethods() throws SecurityException {...}//获取所有公有构造器 @CallerSensitive    public Constructor<?>[] getConstructors() throws SecurityException {...}//根据名称获取字段(该字段需要为public的否则抛异常)@CallerSensitive    public Field getField(String name)        throws NoSuchFieldException, SecurityException {        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);//公有成员访问限定        Field field = getField0(name);//本地方法获取字段信息        if (field == null) {//为null,表示没有,抛不存在该字段异常            throw new NoSuchFieldException(name);        }        return field;    }//根据方法名称获取方法信息,后面的变长参数是该方法的每一个参数的对应的Class类型//同样需要方法是公有的@CallerSensitive    public Method getMethod(String name, Class<?>... parameterTypes)        throws NoSuchMethodException, SecurityException {...}//根据构造器名称获取构造器信息,后面的变长参数是该构造器的每一个参数的对应的Class类型//同样需要构造器是公有的@CallerSensitive    public Constructor<T> getConstructor(Class<?>... parameterTypes)        throws NoSuchMethodException, SecurityException {...}

概述

上面有很多类似的方法,总结起来需要知道:
1.类里面有这么些东西:类(Class)、字段(Field)、方法(Method)、构造器(Constructor),这样就会有类似的方法,比如:getClass()/getClasses()、getField()/getFields()、getMethod()/getMethods()等,但要注意,Class这一对方法和其他的不同。
2.另外,类似getDeclaredFields(),中间加了Declared的表示获取所有对象,而未加的则表示获取公有的所有对象。
3.enclosingMethod、enclosingConstructor、enclosingClass,enclosing表示该类是被包装起来的,那么就分为三种,分别是被包装在方法、构造器或类中。

源码详解

1.getEnclosingXxx
  这个Xxx表示某种对象,比如Method,表示如果这个类存在于某个方法内,返回这个方法(Method对象),否则返回null。(注意,构造器不是方法)
  类似的还有getEnclosingClass()/getEnclosingConstructor():分别是如果类位于类中、构造器中,返回相应的类、构造器信息。

public class {    class A;//位于类中,有enclosed class属性    public Main(){        class B;//类位于构造器中,有enclosed constructor属性    }    public static void main(String[] args) throws Exception    {        Class c1 = new InterfaceA(){}.getClass();        //类位于方法中,有enclosed method属性    }}

2.getXxx
  这里的Xxx可以是:Class、Field、Method、Constructor,表示获取该类中的指定的(参数)对应的公有对象(Class不同,表示获取该类的Class对象),也可以是他们的复数,表示获取该类中对应的所有公有对象(getClasses表示获取所有公有成员类)。
3.getDeclaredXxx
  和2类似,只不过这次获取的是该类所有对应的对象,而不是仅仅是公有的。
4.getName、getSimpleName、getCanonicalName
  (1).getName:获取类全限定名,形如:com.fcc.test.ClassName,当这个类是数组的时候,会得到奇怪的结果:[[Ljava.lang.String;这是个二元数组。
  (2).getSimpleName:去掉包名的简单类名称,数组时候返回正常:String[][]。
  (3).getCanonicalName:同getName,但数组的时候返回正常:java.lang.String[][]。

0 0
原创粉丝点击