关于Env的源代码如下:

/** A class for environments, instances of which are passed as
 *  arguments to tree visitors.  Environments refer to important ancestors
 *  of the subtree that's currently visited, such as the enclosing method,
 *  the enclosing class, or the enclosing toplevel node. They also contain
 *  a generic component, represented as a type parameter, to carry further
 *  information specific to individual passes.
 *
 *   一个类的环境,它的实例将被作为树访问者的参数进行传递。环境涉及到重要的子树的先祖,
 *   子树是目前被访问过的。例如封闭的方法、封闭的类或者是封闭的顶层结点。它们也包含了
 *   一个一般性的组件,被描述为类型参数,针对个别的传递携带更多的信息
 *
 */
public class Env<A> implements Iterable<Env<A>> {

    /** The next enclosing env.
     *
     *  下一个封闭的环境,和作用域是不同的。这个与语法树的组织嵌套是一样的
     */
    public Env<A> next;

    /** The env enclosing the current class.
     *
     * 参考文章:
     */
    public Env<A>  outer;

    /** The tree with which this environment is associated.
     */
    public JCTree tree;

    /**
     * The enclosing toplevel tree.封闭的顶层语法树,语法节点类型为JCCompilationUnit
     */
    public JCCompilationUnit toplevel;

    /** The next enclosing class definition.
     */
    public JCClassDecl enclClass;

    /** The next enclosing method definition.
     */
    public JCMethodDecl enclMethod;

    /** A generic field for further information.
     */
    public A info;

    // ...
}

主要通过三种途径来获取Env对象,如下:

(1)构造函数创建Env对象并返回

代码如下:

/** Create an outermost environment for a given (toplevel)tree,with a given info field.
 */
public Env(JCTree tree, A info) {
    this.next = null;
    this.outer = null;
    this.tree = tree; // 初始化时就赋值
    this.toplevel = null;
    this.enclClass = null;
    this.enclMethod = null;
    this.info = info; // 初始化时就赋值
}

调用的地方如下图所示。

除去Env中的dup方法与子类通过super()进行调用后,剩下了两个主要的地方在调用。

(2)调用dupto()方法获取Env对象

/** Duplicate this environment into a given Environment,
 *  using its tree and info, and copying all other fields.
 */
public Env<A> dupto(Env<A> that) {
    that.next = this;
    that.outer = this.outer;
    that.toplevel = this.toplevel;
    that.enclClass = this.enclClass;
    that.enclMethod = this.enclMethod;
    return that;
}

被调用的地方如下图所示。

  

(3)调用dup()方法获取Env对象  

/** Duplicate this environment, updating with given tree,
 *  and copying all other fields.
 */
public Env<A> dup(JCTree tree) { // 更新tree的信息
    return dup(tree, this.info);
}

/** Duplicate this environment, updating with given tree and info,
 *  and copying all other fields.
 */
public Env<A> dup(JCTree tree, A info) { // 更新tree与info的信息
    return dupto(new Env<A>(tree, info));
}

如上两个dup()方法都将调用dupto()方法来获取Env对象。

第一个方法的调用地方如下图所示。

第二个方法的调用地方如下图所示。 

下面来介绍各个属性。 

1、info属性:

参考文章:https://www.cnblogs.com/extjs4/p/9285113.html

2、outer属性:

class A {
	static class B { // 只有在toplevel类中可用static,所有的内部类不可以使用static关键字
		int b = 2;

		public  void methodB(){
			class C {

				Object c = new Object(){
					int c = b;
				};

				{
				 class D{
						public void t() {
							int c = b;
						}
				   }
				 }
			}
		}
	}
}

对于匿名内部类的int c = b语句来说,其outer是JCNewClass(JCNewClass属于类C)。类C的outer为类B的JCBlock。类B的outer为类A。

对于方法t中的int c = b语句来说,语句属于类D,类D的外层为JCBlock(JCBlock{classD{...}},而JCBlock(JCBlock{classD{...}}的outer为methodB的Block。

3、enclClass属性:

一个编译单元JCCompilationUnit的Env下的enclClass属性为:

/** Create a fresh environment for toplevels.
 *  @param tree     The toplevel tree.
 */
public Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {

    // 初始化namedImportScope属性
    tree.namedImportScope = new ImportScope(tree.packge);
    tree.starImportScope = new StarImportScope(tree.packge);

    Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
    localEnv.toplevel = tree;
    // predefClassDef:A dummy class to serve as enclosingClass
    // for toplevel environments.
    localEnv.enclClass = predefClassDef;
    // JCCompilationUnit的环境Scope中使用的是namedImportScope
    localEnv.info.scope = tree.namedImportScope;
    localEnv.info.lint = lint;

    return localEnv;
}

是一个预先定义好的predefClassDef。 

public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
    Scope sp = new Scope(tree.sym);
    AttrContext ac = env.info.dup(sp);
    Env<AttrContext> localEnv =  env.dup(tree, ac);

    localEnv.enclClass = tree;
    localEnv.outer = env;
    localEnv.info.isSelfCall = false;
    localEnv.info.lint = null; // leave this to be filled in by Attr,
                                 // when annotations have been processed
    return localEnv;
}

被调用的截图如下:

JCClassDecl语法节点的Env的属性enclClass为自己本身,而JCTypeParameter语法节点举例如下:

interface IA{}
interface IB{}
class CA{}
class CB{}
class TestC<T extends CA&IA&IB>{
	public <B extends CB&IA&IB> void method(B b){}
}

则visitTypeParameter()方法的cd属性类型为JCClassDecl,分别为:

1、public abstract class T extends CA implements IA,IB{} 最终生成的Env如下截图。

2、public abstract class B extends CB implements IA,IB{} 最终生成的Environment如下截图。

对于Scope属性举个例子,如下:

package com.test07;

import java.io.FileInputStream;
import java.io.InputStream;
class TestScope {

    public int a = 2;

    public void test(int b) {
        int c = 3;
        for (int d = 3; a < 6; a++) {
            int e = 4;
        }
    }
}

Scope如下截图。

 

在如上的例子中,JCVariableDecl节点及子结点的staticLevel都为1,而其父结节点及以上为0。再举个例子,如下:

public class Test3{
	static{                      // staticLevel = 1
		// 在static块中不允许再有static出现,如
		// static int a = 1;
		// static class A{}
		// class A{
		//  public static void m1(){}
		// }
		int a = 1;               // staticLevel = 1
	}
	// 这个类的staticLevel为0,与一般类没有任何区别
	static class Inner{          // staticLevel = 0
		public static void m1(){ // staticLevel = 1
			int b = 1;           // staticLevel = 1
		}
	}
}

举个例子,如下:

interface I{
	void m1();
}
public class Test3{
	static void t(){}
	static I a = new I(){
		@Override
		public void m1() {
			t();
		}
	};
}

那么t()的环境Env的结构如下截图。

  

这是outer属性,而next属性和语法树的组织结构是严格一致的,如下截图。

Javac之Environment的更多相关文章

  1. Fedora javac 命令提示 [javac: 未找到命令...]

    [joy@localhost ~]$ java -version openjdk version "1.8.0_91" OpenJDK Runtime Environment (b ...

  2. Java SE series:1. environment configure and Hello world! [We use compiler and packager to create an application!]

    1. cli (command line interface) and gui (graphic user interface) use javahome path, search classpath ...

  3. Storm(1) - Setting Up Development Environment

    Setting up your development environment 1. download j2se 6 SDK from http://www.oracle.com/technetwor ...

  4. JDK Environment Variable And Change default JDK

    Environment Variable : change(import) /etc/bashrc export JAVA_HOME=/software/jdk1.8.0 export PATH=$J ...

  5. Config the Android 5.0 Build Environment

    In this document Choosing a Branch    Setting up a Linux build environment        Installing the JDK ...

  6. 在XP系统下搭建maven环境出的问题 Unable to locate the Javac Compiler in: C:\Program Files\Java\jre6\..\lib\tools.jar

    Build errors for spider; org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute g ...

  7. google官方提供的编译android源码的环境初始化,Initializing a Build Environment

    原文网址:http://source.android.com/source/initializing.html Initializing a Build Environment IN THIS DOC ...

  8. 解决linux下javac -version和java -version版本显示不一致

    解决linux下javac -version和java -version版本显示不一致 [javascript] view plaincopy [root@localhost usr]# $JAVA_ ...

  9. 第六章-Javac符号表

    需要参考: (1)Architecture of a Java Compiler (2)关于符号Symbol第一篇 (3)关于符号Symbol第二篇 (4)关于类型Type (5)关于作用域范围Sco ...

随机推荐

  1. 注册一个GitHub用户的过程

    今天,我注册了一个GitHub用户.一开始,不知道GitHub是什么,还以为叫什么"getup",心里还想着什么网站名字这么奇怪,后来在舍友的帮助之下知道了原来是叫GitHub.下 ...

  2. 【原创】在Windows系统中使用VC9、VC11编译32位、64位PHP及其扩展

    项目中需要使用runkit模块实现AOP,但是团队成员的开发环境都是Windows,而runkit模块官方没有提供Windows环境下的dll扩展,只能自己编译. 下面是编译过程的分类总结.(操作系统 ...

  3. ce+od无法同时附加进程的问题

    CE+OD无法附加游戏进程的破解方法 来吧 别在为这烦恼了 其实看过 windows 核心编程那本书的人都知道 计算机编程领域 那些所谓的游戏保护 真的只是为难菜鸟而已,对于大鸟基本不起作用. 游戏无 ...

  4. SQL表连接查询inner join left join right join full join ...

    一.最常见的连接查询 select  s.name,m.mark from student s,mark m  where s.id=m.studentid. 二.内连接-inner join sel ...

  5. C#导出EXCEL,并生成charts表

    需要添加引用  Microsoft.Office.Interop.Excel 注意:使用Microsoft.Office.Interop.Excel 非常耗时.对性能有要求建议用其他. 如果要用,把数 ...

  6. sharepoint 2016 download

     链接: http://pan.baidu.com/s/1pLBwvnt 密码: c928 SharePoint 2016 Server中文版,

  7. iOS 添加字体

    1. 将字体(ttf 文件)导入项目. 2. 在项目plist 文件里的 Fonts provided by application 添加新导入的字体. 3. 代码中的调用 [aLabel setFo ...

  8. Exp2 后门原理与实践 20164323段钊阳

    220164323 Exp2 后门原理与实践 (1)例举你能想到的一个后门进入到你系统中的可能方式?在使用盗版软件,盗版系统,甚至游戏外挂时,往往会让我们关闭杀毒软件,.(2)例举你知道的后门如何启动 ...

  9. BootStrap框架引入文件

    bootstrap -- 框架 引入需要的  这是外网的------************************************************************* < ...

  10. mxonline实战11,课程详情页2,课程章节页

    对应github地址:第11天   一. 课程详情页2   1. 课程详情页第2块中的课程介绍中,修改course-detail.html中代码,搜索课程详情,找到如下代码