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[][]。
- Java源码解析(3) —— Class(2)
- Java源码解析(4) —— Class(3)
- Java源码解析(2) —— Class(1)
- Java源码解析(5) —— Class(4)
- 解析Java的Class文件格式——解析魔…
- Java源码解析(附录)(3) —— GenericDeclaration
- Java源码解析(附录)(2) —— TypeVariable
- Java源码解析(1) —— Object
- Java技术——CopyOnWriteArrayList源码解析
- java集合—结合要点解析源码
- java.util.concurrent解析——FutureTask源码解析
- java.util.concurrent解析——ThreadPoolExecutor源码解析
- 【JVM系列】Java class文件解析2
- java class文件格式解析
- Java Class 文件解析
- java class文件解析
- JAVA CLASS 文件解析
- jdk源码解析(六)——类(class)文件结构
- js去重
- http://blog.csdn.net/zhangweiwtmdbf/article/details/52369276
- ConvertLUnicodeStringToNullTerminatedString
- 抽象工厂模式
- HDOJ 5927 Auxiliary Set【树】
- Java源码解析(3) —— Class(2)
- BZOJ2798/POI2012 Squarks
- 软件工程(一)
- 变量和函数
- Codeforces 724C 预处理
- (Leetcode)92. Reverse Linked List II ——反转单链表
- Openfiler 2.99命令行下添加Volume Group
- [bzoj3682]Phorni
- 利用Java从班级通联电子表中剔除部分指定同学之后生成新的Excel表格