Scope及其子类介绍
之前写的文章:
Scope及相关的子类如下:

同时有些Scope还继承了Scope.ScopeListener类,如下:

1、StarImportScope及ImportScope
在JCCompilationUnit中定义了两个属性,其类型就是这两个类型:
public ImportScope namedImportScope; public StarImportScope starImportScope;
但在初始化JCCompilationUnit语法节点时并不初始化这两个属性,而是在Enter的如下类中进行初始化,代码如下:
/** Create a fresh environment for toplevels.
* @param tree The toplevel tree.
*/
public Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
tree.namedImportScope = new ImportScope(tree.packge);
tree.starImportScope = new StarImportScope(tree.packge);
Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
localEnv.toplevel = tree;
localEnv.enclClass = predefClassDef;
// JCCompilationUnit的环境Scope中使用的是namedImportScope
localEnv.info.scope = tree.namedImportScope;
localEnv.info.lint = lint;
return localEnv;
}
Scope最重要的作用就是用来查找特定范围内定义的符号,而这些符号的填充在MemberEnter类中完成的。首先看StarImportScope的填充,代码如下:
/** Import all classes of a class or package on demand.
* @param pos Position to be used for error reporting.
* @param tsym The class or package the members of which are imported.
* @param toScope The (import) scope in which imported classes are entered.
*/
private void importAll(int pos,
final TypeSymbol tsym,
Env<AttrContext> env) {
// Check that packages imported from exist (JLS ???).
// 在调用tsym.members()会调用complete()方法来完成这个符号属性的填充
if (tsym.kind == PCK01 &&
tsym.members().elems == null &&
!tsym.exists()) {
// If we can't find java.lang, exit immediately.
if (((PackageSymbol)tsym).fullname.equals(names.java_lang)) {
// 致命错误: 在类路径或引导类路径中找不到程序包 java.lang
JCDiagnostic msg = diags.fragment("fatal.err.no.java.lang");
throw new FatalError(msg);
} else {
// 程序包{0}不存在
log.error(JCDiagnosticFlag.RESOLVE_ERROR, pos, "doesnt.exist", tsym);
}
}
Scope sp = tsym.members();
env.toplevel.starImportScope.importAll(sp);
}
每个JCCompilationUnit编译单元通过import导入需要的依赖,有一个是默认导入的,就是java.lang.*下面的定义的类,而代码sp中包含的类符号如下:
Scope[ Void,VirtualMachineError, VerifyError,UnsupportedOperationException, UnsupportedClassVersionError,UnsatisfiedLinkError, UnknownError, TypeNotPresentException, Throwable, Throwable$WrappedPrintWriter, Throwable$WrappedPrintStream,Throwable$SentinelHolder, Throwable$PrintStreamOrWriter,ThreadLocal, ThreadLocal$ThreadLocalMap,ThreadLocal$ThreadLocalMap$Entry, ThreadGroup,ThreadDeath, Thread, Thread$WeakClassKey, Thread$UncaughtExceptionHandler, Thread$State, Thread$Caches, Terminator, SystemClassLoaderAction, System, SuppressWarnings, StringIndexOutOfBoundsException, StringCoding, StringCoding$StringEncoder, StringCoding$StringDecoder, StringBuilder, StringBuffer, String, String$CaseInsensitiveComparator, StrictMath, StackTraceElement, StackOverflowError, Shutdown,Shutdown$Lock, Short, Short$ShortCache, SecurityManager, SecurityException, SafeVarargs, RuntimePermission, RuntimeException, Runtime, Runnable, ReflectiveOperationException, Readable, ProcessImpl, ProcessImpl$LazyPattern, ProcessEnvironment, ProcessEnvironment$NameComparator, ProcessEnvironment$EntryComparator, ProcessEnvironment$CheckedValues, ProcessEnvironment$CheckedKeySet, ProcessEnvironment$CheckedEntrySet, ProcessEnvironment$CheckedEntry, ProcessBuilder, ProcessBuilder$Redirect, ProcessBuilder$Redirect$Type,ProcessBuilder$NullOutputStream, ProcessBuilder$NullInputStream, Process, Package, Override, OutOfMemoryError, Object,NumberFormatException, Number, NullPointerException, NoSuchMethodException, NoSuchMethodError, NoSuchFieldException, NoSuchFieldError, NoClassDefFoundError, NegativeArraySizeException, Math, Long, Long$LongCache, LinkageError, Iterable, InterruptedException, InternalError, Integer, Integer$IntegerCache, InstantiationException, InstantiationError, InheritableThreadLocal, IndexOutOfBoundsException, IncompatibleClassChangeError,IllegalThreadStateException, IllegalStateException, IllegalMonitorStateException, IllegalArgumentException, IllegalAccessException, IllegalAccessError, Float, ExceptionInInitializerError, Exception, Error, EnumConstantNotPresentException, Enum, Double, Deprecated, ConditionalSpecialCasing, ConditionalSpecialCasing$Entry, Compiler, Comparable, Cloneable,CloneNotSupportedException, ClassValue, ClassValue$Version, ClassValue$Identity, ClassValue$Entry, ClassValue$ClassValueMap,ClassNotFoundException, ClassLoaderHelper, ClassLoader, ClassLoader$ParallelLoaders, ClassLoader$NativeLibrary, ClassFormatError, ClassCircularityError, ClassCastException,Class, Class$SecurityManagerHelper, Class$ReflectionData, Class$MethodArray, Class$EnclosingMethodInfo, Class$Atomic, CharacterName, CharacterDataUndefined, CharacterDataPrivateUse, CharacterDataLatin1, CharacterData0E, CharacterData02,CharacterData01, CharacterData00, CharacterData, Character, Character$UnicodeScript, Character$UnicodeBlock, Character$Subset, Character$CharacterCache, CharSequence, Byte, Byte$ByteCache, BootstrapMethodError, Boolean, AutoCloseable, AssertionStatusDirectives, AssertionError, ArrayStoreException, ArrayIndexOutOfBoundsException, ArithmeticException, ApplicationShutdownHooks, Appendable, AbstractStringBuilder, AbstractMethodError ]
调用了StarImportScope的importAll()方法,传入了sp参数:importAll()方法代码如下:
public class StarImportScope extends ImportScope implements Scope.ScopeListener {
public StarImportScope(Symbol owner) {
super(owner);
}
public void importAll (Scope fromScope) {
for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
if (e.sym.kind == Kinds.TYP02 && !includes(e.sym)) {
enter(e.sym, fromScope);
}
}
// Register to be notified when imported items are removed
fromScope.addScopeListener(this);
}
public void symbolRemoved(Symbol sym, Scope s) {
remove(sym);
}
public void symbolAdded(Symbol sym, Scope s) { }
}
将sp中的所有符号导入StarImportScope中,并且StarImportScope中的table属性(Entry[]类型)中的元素为ImportEntry,如下部分截图:

说一下静态导入和非静态导入:
import java.io.*; // 代码1
import java.math.BigDecimal; // 代码2
import static com.test19.TestStatic.*; // 代码3
import static com.test19.TestStatic.method; // 代码4
public class TestScope{
public void t(){
InputStream p;
BigDecimal d;
int b = v;
method();
}
}
无论静态还是非静态导入,最终都会调用MemberEnter类中的visitImport()方法,这个方法的代码如下:
// process the non-static imports and the static imports of types.
public void visitImport(JCImport tree) {
JCTree imp = tree.qualid;
Name name = TreeInfo.name(imp);
TypeSymbol p;
// Create a local environment pointing to this tree to disable
// effects of other imports in Resolve.findGlobalType
Env<AttrContext> localEnv = env.dup(tree); // todo
// Attribute qualifying package or class.
JCFieldAccess s = (JCFieldAccess) imp;
// 对于staticImport来说s.selected肯定是TYPE。因为import static TypeName . Identifier ;
// 对于非staticImport来说s.selected可能是Type,也可能是PCK。如
// 1、import PackageName.TypeName
// 2、import PackageName.TypeName.TypeName
p = attr.attribTree(s.selected,
localEnv,
tree.staticImport ? TYP02 : (TYP02 | PCK01),
Type.noType).tsym;
if (name == names.asterisk) {
// Import on demand.
chk.checkCanonical(s.selected);
if (tree.staticImport) {
importStaticAll(tree.pos, p, env);
}else {
importAll(tree.pos, p, env);
}
} else {
// Named type import.
if (tree.staticImport) {
importNamedStatic(tree.pos(), p, name, localEnv);
chk.checkCanonical(s.selected);
} else {
TypeSymbol c = attribImportType(imp, localEnv).tsym;
chk.checkCanonical(imp);
importNamed(tree.pos(), c, env);
}
}
}
从如上的判断逻辑可以看出:
1、importStaticAll()方法
主要用来处理代码3。由于在导入时可能是静态类(包括TestStatic从父类或者接口中继承的),也可能是静态变量,两个有不同的处理逻辑。
(1)静态类的导入是立马执行导入的。
(2)非静态类的导入是在运行注解之前导入的
package com.test01;
public class MA {
public static void x(){}
}
package com.test01;
import static com.test01.MA.*;
public class MB{
public static void t(){}
}
同一个包中定义了MA与MB类,然后测试:
package com.test02;
import static com.test01.MB.*;
public class Test {
public void test(){
t();
x(); // 报错
}
}
说明导入MB中的MA的静态方法没有在TestX中导入MB静态方法时一同将MA中的静态方法导入,如果MB继承MA,则如上不会报错。
2、importAll()方法
主要用来处理代码1,与处理java.lang.*是一样的逻辑
3、importNamedStatic()方法
主要用来处理代码4,代码在执行中还需要调用Check类的checkUniqueStaticImport()方法
4、importNamed()方法
主要用来处理代码2,代码在执行中还需要调用Check类的checkUniqueImport()方法
其实importNamed()方法与importNamedStatic()方法将符号导入namedImportScope中,而importStaticAll()与importAll()方法将符号导入
starImportScope中。而对于importStaticAll()与importNamedStatic()方法,只导入类,不导入方法与变量。
2、CompoundScope
与方法的检查有关
3、DelegatedScope
查看MemberEnter类中的initEnv()方法,代码如下:
/** Create a fresh environment for a variable's initializer.
* If the variable is a field, the owner of the environment's scope
* is be the variable itself, otherwise the owner is the method
* enclosing the variable definition.
*
* @param tree The variable definition.
* @param env The environment current outside of the variable definition.
*/
public Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) {
AttrContext ac = env.info.dup();
AttrContextEnv ace = new AttrContextEnv(tree, ac);
Env<AttrContext> localEnv = env.dupto(ace);
if (tree.sym.owner.kind == TYP02) { // the variable is a field
localEnv.info.scope = new DelegatedScope(env.info.scope);
localEnv.info.scope.owner = tree.sym;
}
if ( (tree.mods.flags & STATIC) != 0 ||
(env.enclClass.sym.flags() & INTERFACE) != 0 ){ // 表示在接口中定义的变量
localEnv.info.staticLevel++;
}
return localEnv;
}
只有当variable是field时才将Scope替换为DelegatedScope,并且这个Scope的owner为这个Field本身。
Scope及其子类介绍的更多相关文章
- Android Drawable的9种子类 介绍
原文: Android Drawable的9种子类 介绍 Drawable 在android里面 就是代表着图像,注意是图像 而不是图片. 图片是图像的子集.图像除了可以包含图片以外 还可以包含颜 ...
- java并发编程(十)----JUC原子类介绍
今天我们来看一下JUC包中的原子类,所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程),原子操作可以是 ...
- AVCaptureInput和AVCaptureOutput子类介绍
AVCaptureInput AVCaptureDeviceInput:用于从AVCaptureDevice对象捕获数据. AVCaptureScreenInput:从macOS屏幕上录制的一种捕获输 ...
- Juc中Atomic原子类总结
1 Atomic原子类介绍 2 基本类型原子类 3 数组类型原子类 4 引用类型原子类 5 对象的属性修改类型原子类
- java高并发系列 - 第23天:JUC中原子类,一篇就够了
这是java高并发系列第23篇文章,环境:jdk1.8. 本文主要内容 JUC中的原子类介绍 介绍基本类型原子类 介绍数组类型原子类 介绍引用类型原子类 介绍对象属性修改相关原子类 预备知识 JUC中 ...
- JUC之原子类
在分析原子类之前,先来了解CAS操作 CAS CAS,compare and swap的缩写,中文翻译成比较并交换. CAS 操作包含三个操作数 —— 内存位置(V).预期原值(A)和新值(B).如果 ...
- angulajs 详解 directive 中 的 scope 概念
Directive 是 angularjs 中最重要的概念,我的理解就是自定义html tag, 这个自定的tag 浏览器不会解析,会有angularjs 来动态解析. 比如在html 中添加 < ...
- JUC 中的 Atomic 原子类总结
1 Atomic 原子类介绍 Atomic 翻译成中文是原子的意思.在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的.在我们这里 Atomic 是指一个操作是不可中断的.即使是 ...
- java核心-多线程(8)- 并发原子类
使用锁能解决并发时线程安全性,但锁的代价比较大,而且降低性能.有些时候可以使用原子类(juc-atomic包中的原子类).还有一些其他的非加锁式并发处理方式,我写这篇文章来源于Java中有哪些 ...
随机推荐
- 简单的cxf-ws 基于web容器
pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...
- HTML中submit和button的区别
submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了. 如果表单在点击提交按钮后需要用JS进行处理(包括输入验证)后再提交的话,通常都必须把submit改成butt ...
- Codeforces777B Game of Credit Cards 2017-05-04 17:19 29人阅读 评论(0) 收藏
B. Game of Credit Cards time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- DBCC--CHECKDB--结果收集
--由宋沄剑提供 CREATE TABLE [dbo].[dbcc_history]( [Error] [int] NULL, [Level] [int] NULL, [State] [int] NU ...
- ASP.Net C#---Excel导入导入后台方法
https://www.cnblogs.com/chendaye/p/10693983.html 这里写了Excel的导入导入方法, 后台我用的是MVC 以及 C#语句用来在后台做接受和输出数据 / ...
- C#操作字符串之常用函数总结
1:使用string.Join 泛型集合快速转换拼接字符串. 2:使用 string.Split 将字符串截断转换成字符数组. 3:使用 string.Substring,string.Remove ...
- IBM主机家族——大型机、中型机、小型机
对于x86架构的开放品台机器来说,IBM的封闭平台系列可以说是另一个“体系世界”. IBM z series 大型机, z/os操作系统 IBM i series/AS400 中型机, i ...
- Python实现汉诺塔问题的可视化(以动画的形式展示移动过程)
学习Python已经有一段时间了,也学习了递归的方法,而能够实践该方法的当然就是汉诺塔问题了,但是这次我们不只是要完成对汉诺塔过程的计算,还要通过turtle库来体现汉诺塔中每一层移动的过程. 一.设 ...
- 极大提高Web开发效率的8个工具和建议(含教程)
面对复杂的 Web 应用的开发,良好的流程和工具支持是必不可少的,它们可以让日常的开发工作更加顺畅.更加高效.本文介绍了6个Web开发利器以及相关的教程,帮助你在开发.调试.集成和发布过程极大地提高效 ...
- 纯文本-FileOutputStream的解码方式
1.通过string.getBytes(charsetNane)获得的字节数组,字节数组的编码方式,决定了FileOutStream写出文件的格式 例1:字节数组采用“GBK”编码,write生成的文 ...