1. 程式人生 > >Scope及其子類介紹

Scope及其子類介紹

AR ica oat 元素 equal mco ans font style

之前寫的文章:

關於作用域範圍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.*;
import java.math.BigDecimal;

import static com.test19.TestStatic.*;
import static com.test19.TestStatic.method;  // 導入

public class TestScope{
	public void t(){
		InputStream p;
		BigDecimal d;
		int b = v;
		method();
	}
}

無論靜態還是非靜態導入,最終都會調用MemberEnter類中的visitImport()方法,  

  

  

  

  

Scope及其子類介紹