关于符号Symbol第一篇
Symbol类的一个实例代表一个符号。对于语法树来说,并不是每个节点都有一个符号实例。下面列举了哪些语法树节点具有符号的引用,如下表格:
其中JCNewClass、JCAssignOp、JCUnary、JCBinary、JCFieldAccess与JCIdent继承了JCExpression,可出现在表达式中。
如上的PackageSymbol、ClassSymbol、MethodSymbol、VarSymbol与TypeSymbol这些符号由用户指定,而剩下的一些都是对既有符号的引用。如语法节点JCAssignOp中的operator。
下面来举个具体的例子说明一下。
package m20170208; public class A<T> { public void test1() { int a = 3; int b = a + 2; } public void test2() { A ins = new A(); ins.test1(); } }
查看JCCompilationUnit语法节点的packge属性,如下:
查看JCClassDecl语法节点,如下:
查看JCTypeParameter节点。这个节点没有直接对Symbol进行引用,而是通过type属性的tsym来引用的,如下:
查看JCMethodDecl节点的sym属性,如下:
查看JCVariableDecl节点的sym属性,如下:
查看JCBinary节点的operator属性,如下:
查看JCIdent节点的sym属性,如下:
查看JCNewClass节点的constructor属性,如下:
查看JCFieldAccess节点的sym属性,如下:
下面来介绍一下Symbol中一些重要的属性。
属性1:kind
** The kind of this symbol. * @see Kinds * * Java语言符号的种类,有包的符号、类型的符号、变量的符号、值的符号和方法的符号 */ public int kind;
kind值取的是类Kinds中定义的一些常量,如下:
/** The empty set of kinds. */ public final static int NIL = 0; // 0 /** The kind of package symbols. */ public final static int PCK = 1 << 0; // 1 /** The kind of type symbols (classes, interfaces and type variables). */ public final static int TYP = 1 << 1; // 2 /** The kind of variable symbols. */ public final static int VAR = 1 << 2; // 4 变量符号 /** The kind of values (variables or non-variable expressions), includes VAR. * * 在标记阶段使用 */ public final static int VAL = (1 << 3) | VAR; // 12 值(包括变量和非变量表达式),也包括变量 /** The kind of methods. */ public final static int MTH = 1 << 4; // 16 方法 /** The error kind, which includes all other kinds.包含所有其它类型的错误 */ public final static int ERR = (1 << 5) - 1; // 31 包括剩下的其它种类
VAL一般是表达式的右端,例如:a = Exp;那么Exp可以是变量也可以是一个值,但是a绝对是一个变量。
OperatorSymbol的kind属性值为16,也就是方法。因为这些符号最终的意思是通过方法来体现的,如int a = b+c;假如b与c是int类型变量,那么调用了有两个int类型
参数的方法,将b与c传入后,返回的结果即是a想要的结果。
对比Symbol例子的截图查看kind的值。其中的NIL常量是在创建默认的noSymbol时使用过。在SymbolTable中的定义如下:
/** A symbol that stands for a missing symbol. */ public final TypeSymbol noSymbol;
属性2:flags_field
/** The flags of this symbol. * * 符号的标志 */ public long flags_field; // 值来自Flags类中
Flags中有许多修饰符,如public、abstract等等,表示这个符号上有哪些修饰符。不过树节点中使用的修饰符与这里的flags_field未必是一个值,例如定义在接口中的变量,编译器默认会添加public、static、final修饰符,在记录符号时,这个flags_field也会将这些修饰符在long值中对应的位置为1。
属性3:attributes_field
/** The attributes of this symbol. * * 符号的属性 */ public List<Attribute.Compound> attributes_field;
举个例子,如下:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.PACKAGE) @Retention(RetentionPolicy.RUNTIME) @interface MzTargetPackage { public String version() default ""; }
定义一个包注解
@MzTargetPackage(version="1.0") package m20170208;
在包上使用包注解,查看attributes_field属性的值,如下:
属性4:name
/** The name of this symbol in Utf8 representation. * 符号的名称 */ public Name name;
这个name就是NameImpl对象,在前面也讲解过。
属性5:type
/** The type of this symbol. * * 符号的类型 */ public Type type;
有许多具体的Type类。
属性6:owner
/** The owner of this symbol. */ public Symbol owner;
从Symbol例子的各个截图中可以查看到各个owner的具体值。其中OperatorSymbol由于是预定义好的,所以其owner归属于预定义的ClassSymbol中。
举个例子,如下:
class Test{ Test o = new Test(){},x = o; }
x这个VarSymbol还是属性ClassSymbol(Test),在词法分析阶段就是两个独立变量的声明,变为了如下形式:
class Test{ Test o = new Test(){}; Test x = o; }
new Test(){}为JCNewClass,而del属性为JCClassDecl,如下截图。
其中的匿名类的owner为VarSymbol,如下:
属性6:erasure_field
/** A cache for the type erasure of this symbol. */ public Type erasure_field;
表示泛型擦除后的类型,如类A的泛型擦除后,其值如下:
又如JCNewClass中的MethodSymbol(A())中的此属性值,如下:
创建类对象的实例时,其实是调用的这个类的构造函数(被当作特殊的方法来对待)。、
方法1:public boolean isInheritedIn(Symbol clazz, Types types)
/** Is this symbol inherited into a given class? * PRE: If symbol's owner is a interface, * it is already assumed that the interface is a superinterface of given class. * @param clazz The class for which we want to establish membership. * This must be a subclass of the member's owner. */ public boolean isInheritedIn(Symbol clazz, Types types) { switch ((int)(flags_field & Flags.AccessFlags)) { // AccessFlags中的值只能取其一 default: // error recovery case PUBLIC: return true; case PRIVATE: return this.owner == clazz; case PROTECTED: // we model interfaces as extending Object // 非接口时为true,接口时为false,因为接口里没有public members return (clazz.flags() & INTERFACE) == 0; case 0: // default访问权限为同包或者同类,子类或者其它包是不可以访问的 PackageSymbol thisPackage = this.packge(); for (Symbol sup = clazz; sup != null && sup != this.owner; sup = types.supertype(sup.type).tsym ){ while (sup.type.tag == TYPEVAR14) { sup = sup.type.getUpperBound().tsym; } if (sup.type.isErroneous()) { return true; // error recovery } if ((sup.flags() & COMPOUND) != 0) { /* eg1: interface IA{} interface IB{} class CA{} public class TestMethod{ public <T extends CA&IA&IB>void methodA(){ } } */ continue; } if (sup.packge() != thisPackage) { // 当修饰符为默认时,则不同的包就造成了错误 return false; } } // 非接口时为true,接口时为false,因为接口里没有default members return (clazz.flags() & INTERFACE) == 0; } }
如上的代码在检查某个symbol是否在继承于某个Symbl,例如:
class AA{ void test(){} } public class Outer<T extends AA> { class Inner<D extends T>{ D d; public void x(){ d.test(); } } }
要检查d.test()中的MethodSymbol时就需要判断是否由d这个TypeSymbol继承而来的MethodSymbol。test()方法定义在AA类中,并且修饰符为default,走case 0分支。
关于符号Symbol第一篇的更多相关文章
- 关于符号Symbol第二篇
来看一下继承自Symbol的具体实现类. 1.TypeSymbol /** A class for type symbols. * Type variables are represented by ...
- 回合对战制游戏第一篇(初识java)
回合对战制游戏第一篇 一,所谓的java. java是一门完全面向对象的编程语言,而之前所接触到的C语言是一门面向有一个过程的语音,对于两个的区别应该有一个清楚的认识. java的第一个内容. 类和对 ...
- 微信公众账号开发之微信登陆Oauth授权-第一篇
我曾经在2012年的时候开始研究微信,那时微信的版本还是处于1.0,当时给朋友帮忙做一个基于微信端的web应用,官方的文档是相当少的,百度搜索出来的东西基本也没有多少实用价值,不过是在官网的基础上作了 ...
- RabbitMQ学习总结 第一篇:理论篇
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- 【OpenCV入门指南】第一篇 安装OpenCV
http://blog.csdn.net/morewindows/article/details/8225783/ win10下vs2015配置Opencv3.1.0过程详解(转) http://ww ...
- 【OpenCV第一篇】安装OpenCV
[OpenCV第一篇]安装OpenCV 本篇主要介绍如何下载OpenCV安装程序,如何在VS2008下安装配置OpenCV,文章最后还介绍了一个使用OpenCV的简单小例子. <OpenCV入门 ...
- 分布式文件系统 FastDFS 5.0.5 & Linux CentOS 7 安装配置(单点安装)——第一篇
分布式文件系统 FastDFS 5.0.5 & Linux CentOS 7 安装配置(单点安装)--第一篇 简介 首先简单了解一下基础概念,FastDFS是一个开源的轻量级分布式文件系统,由 ...
- Python之路,第一篇:Python入门与基础
第一篇:Python入门与基础 1,什么是python? Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. 2,python的特征: (1)易于学习,易于利用: (2)开 ...
- 视觉SLAM的数学基础 第一篇 3D空间的位置表示
视觉SLAM中的数学基础 第一篇 3D空间的位置表示 前言 转眼间一个学期又将过去,距离我上次写<一起做RGBD SLAM>已经半年之久.<一起做>系列反响很不错,主要由于它为 ...
随机推荐
- Tensorflow currently has no official prebuild for your CUDA, cuDNN combination.
INFO CUDA version: 10. ERROR cuDNN not found. See https://github.com/deepfakes/faceswap/blob/master/ ...
- (匹配)The Accomodation of Students --HDU --2444
链接: http://acm.hdu.edu.cn/showproblem.php?pid=2444 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- visual studio 2015 rc &cordova -hello world
初始环境,用来看看书,电影,上上网的win8,所以一切从头开始. 1,首先还是装visual studio 2015 rc吧,目前只放出在线安装,所以要很长很长时间.不过有新闻说很快要实现中国网友至 ...
- 团队合作项目—(GG队)
团队展示 一.队名:GG 二.队员信息 队员 学号 叶尚文(队长) 3116008802 蔡晓晴 3216008808 杜婷萱 3216008809 龙剑初 3116004647 于泽浩 311600 ...
- [Linux-vi] The simple set of vi command
Source : https://www.cs.colostate.edu/helpdocs/vi.html What is vi? The default editor that comes wit ...
- asp.net Mvc 模型绑定项目过多会导致页面运行时间卡
asp.net Mvc 模型绑定项目过多会导致页面运行时间卡的问题. 解决方式就是采用ModelView方式进行精简,已减少模型绑定及验证的时间.
- Django:如何给文章列表添加图片
思路: 使用ajax方式将图片和文本一起通过formData提交到后台,Django后台通过request.POST和request.FILES方式接收数据 1.前端代码 {% extends 'ba ...
- Asp.net Core 2.1 Kestrel 现在支持 多协议处理(Tcp)
地址:https://github.com/davidfowl/MultiProtocolAspNetCore.git 在一个Kestrel服务上可以同时处理Tcp,Http,Https等多种协议. ...
- Python3------反射详解
反射: 根据字符串动态的判断,调用,添加/修改,删除类或类的实例化对象中的方法或属性 反射共有四种方法hasattr(),getattr(),setattr(),delattr() 1.通过字符串来判 ...
- CC2530学习路线-基础实验-定时器控制LED灯亮灭(3)
目录 1. 前期预备知识 1.1 定时器中断触发 1.2 相关寄存器 1.3 寄存器相关问题 1.4 T1.T3定时器初始化流程 2 程序及代码 THE END 1. 前期预备知识 1.1 定时器中断 ...