javac的Resolve类解读
方法1:isInitializer()
/** An environment is an "initializer" if it is a constructor or
* an instance initializer.
*/
static boolean isInitializer(Env<AttrContext> env) {
Symbol owner = env.info.scope.owner;
return owner.isConstructor() ||
owner.owner.kind == TYP &&
(owner.kind == VAR || owner.kind == MTH && (owner.flags() & BLOCK) != 0) &&
(owner.flags() & STATIC) == 0;
}
根据如上方法可以看出检查了如下三种情况的initializer:
public class TestInitializer {
TestInitializer() { // constructor
}
int a = 2; // instance variable initializer
{ // instance initializer block
a = 3;
}
}
方法2:isAccessable()
/** Is class accessible in given environment?
* @param env The current environment.
* @param c The class whose accessibility is checked.
*/
public boolean isAccessible(Env<AttrContext> env, TypeSymbol c) {
return isAccessible(env, c, false);
}
public boolean isAccessible(Env<AttrContext> env, TypeSymbol c, boolean checkInner) {
boolean isAccessible = false;
switch ((short)(c.flags() & AccessFlags)) {
case PRIVATE:
isAccessible = env.enclClass.sym.outermostClass() == c.owner.outermostClass();
break;
case 0:
isAccessible =
env.toplevel.packge == c.owner // fast special case
||
env.toplevel.packge == c.packge()
||
// Hack: this case is added since synthesized default constructors
// of anonymous classes should be allowed to access
// classes which would be inaccessible otherwise.
env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0; // anonconstr 匿名构造函数
break;
default: // error recovery
case PUBLIC:
isAccessible = true;
break;
case PROTECTED:
isAccessible =
env.toplevel.packge == c.owner // fast special case
||
env.toplevel.packge == c.packge()
||
isInnerSubClass(env.enclClass.sym, c.owner);
break;
}
return (checkInner == false || c.type.getEnclosingType() == Type.noType) ?
isAccessible :
isAccessible && isAccessible(env, c.type.getEnclosingType(), checkInner);
}
检查的是TypeSymbol是否在某个Env中被访问到,能否访问到最终还要看Java的权限控制符public、protected、default和private。
另外需要知道的是只有Inner Class才可以为protected和private进行修饰。重点看一下protected修饰的类的逻辑。
public class Test {
protected class D {
public D() {
// TODO Auto-generated constructor stub
}
}
}
class A { // only public, abstract & final are permitted
// protected class D{}
}
public class TestAccessible {
protected class B { // public,protected,private are permitted
}
public void method() {
new A(); // 走env.toplevel.packge == c.owner
new B(); // 走env.toplevel.packge == c.packge
}
class C extends Test{
public void method3(){
new D(); // 走isInnerSubClass(env.enclClass.sym,c.owner)
}
}
}
继续看isInnerSubClass,如下:
/** Is given class a subclass of given base class, or an inner class of a subclass?
* Return null if no such class exists.
* @param c The class which is the subclass or is contained in it.
* @param base The base class
*/
private boolean isInnerSubClass(ClassSymbol c, Symbol base) {
while (c != null && !c.isSubClass(base, types)) {
c = c.owner.enclClass();
}
return c != null;
}
方法3:isProtectedAccessible()
/** Is given protected symbol accessible if it is selected from given site
* and the selection takes place in given class?
* @param sym The symbol with protected access
* @param c The class where the access takes place
* @site The type of the qualifier
*/
private boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) {
while( c != null &&
!(
c.isSubClass(sym.owner, types) &&
(c.flags() & INTERFACE) == 0 &&
// In JLS 2e 6.6.2.1, the subclass restriction applies only to instance fields and methods
// -- types are excluded regardless of whether they are declared 'static' or not.
((sym.flags() & STATIC) != 0 || sym.kind == TYP || site.tsym.isSubClass(c, types))
)
) {
c = c.owner.enclClass();
}
return c != null;
}
这个方法中包含了太多的逻辑,有一占需要说明,参数sym的修饰符已经判断为protected,下面分几个步骤来说:
(1)c.isSubClass(sym.owner,types)
类c(获取protected修饰符修饰的sym的类)是否与sym符号所属的符号形成了父子关系,如果是父子关系,当然有访问权限了。
(2)c.flags() & INTERFACE ==0 判断c是否为接口,如果c为接口,那么这个等式不成立。也就说明当c与sym.owner形成父子关系时,如果c为接口,那么有访问的权限。因为接口中所有成员(变量,方法,静态类与非静态类)的访问修饰符为public
(3) ((sym.flags() & STATIC) != 0 || sym.kind == TYP || site.tsym.isSubClass(c, types))
当protected修饰符修饰的sym为静态成员或者是个类型时,由于c为非接口且c与sym.owner已经形成了父子关系,所以有访问的权限。另外还有最后一种情况,site.tsym.isSubClass(c,types),举个例子:
package com.test05;
import com.test06.SubClass;
public class Temp extends SubClass{
protected int b = 2;
}
package com.test05;
public class ParentClass {
protected static int a = 1;
}
package com.test06;
import com.test05.ParentClass;
import com.test05.Temp;
public class SubClass extends ParentClass{
class Inner{
public void test() {
int y = new Temp().a;
}
}
}
由于Temp与所属的Inner类没有形成父子关系,所以c = c.owner.enclClass(),此时c已经成为了SubClass,而SubClass与符号a的owner(ParentClass)形成了父子关系并且SubClass不为接口,这时候就要判断如上的表达式了。
Temp与SubClass形成了父子关系,当然也就可以访问ParentClass中的protected修饰的成员了。
javac的Resolve类解读的更多相关文章
- Java类文件结构及javac的ClassReader类解读
首先来看一下ClassFile,类注释如下: A JVM class file. Generic Java classfiles have one additional attribute for c ...
- JAVA String、StringBuffer、StringBuilder类解读
JAVA String.StringBuffer.StringBuilder类解读 字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作 ...
- 用javac编译servlet类出现问题
本人写了一个关于servlet的webapp,但是在用javac编译的时候,只是单纯的将jsp-api.jar和servlet-api.jar拷贝放在了其目录下面,然后利用命令行 javac XXX. ...
- package-info类解读
类不能带有public.private访问权限.package-info.java再怎么特殊,也是一个类文件,也会被编译成package-info.class,但是在package-info.java ...
- FS及CacheFS类解读
Javac中有FSInfo与CacheFSInfo两个类,CacheFSInfo继承了FSInfo类,这两个类的主要功能就是通过map缓存Jar文件,核心代码如下: private Map<Fi ...
- Bundle类解读
1.Bundle bundle = Platform.getBundle("org.eclipse.ui.views"); Platform是eclipse平台运行时的核心类,它是 ...
- Javac常量池的解读
interface IA{ public void md(); } public class Test07 implements IA{ final double d = 2.0d; final fl ...
- JavacProcessingEnvironment类解读
JavacProcessingEnvironment类的继承体系如下: 其中含有很多内部类,最重要的是迭代注解处理器相关的类,如下:
- C#封装CRUD到SqlHelper类解读
1.简单说明一下,一般情况下,数据库连接字符串是在App.config文件中进行配置,然后再在代码中进行引用.因此,我们在这里先看一下App.config文件. 首先看需要添加的内容: 参数说明: n ...
随机推荐
- zstu4273 玩具 2017-03-22 14:18 49人阅读 评论(0) 收藏
4273: 玩具 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 700 Solved: 129 Description 商店有n个玩具,第i个玩具有 ...
- bootstrap-treeview中文API 以及后台JSON数据处理
bootstrap-treeview 简要教程 bootstrap-treeview是一款效果非常酷的基于bootstrap的jQuery多级列表树插件.该jQuery插件基于Twitter Bo ...
- AutoMapper在C#中的有趣应用
最近发现了一个比较有趣的东西 AutoMapper,主要将Model转换为DTO,DTO更注重数据,对领域对象进行合理封装,从而不会将领域对象的行为过分暴露给表现层. 先来看一点实例,两个类之间的映射 ...
- WP8.1StoreApp(WP8.1RT)---发送邮件和短信
在WP7/8中,发送短信是利用了EmailComposeTask和SmsComposeTask来实现的. 在WP8.1 Store App中,原来的方式已经失效,采用了新的方法:ChatMessage ...
- openstack 的 lbaas 疑问
1 为什么lbaas的haproxy实现没有将其放到vrouter中,而vpnaas/fwaas都放到vrouter中呢? 放在vrouter上,可以减少vrouter到haproxy的流量路径,是怕 ...
- 如何让Gogland不过期,一直使用?
Gogland是jetBrains公司出品的GO语言开发IDE,是目前最好的GO语言开发工具!!但是目前Gogland提供的试用版,有一定的使用期限,如何到期还能使用?经过我的测试,如果Gogland ...
- 点击input消除默认背景颜色:focus
1.在谷歌浏览器会出现默认点击input框黄色背景,如何去除? //消除google浏览器黄色框 input:-webkit-autofill, input:-webkit-autofill:hove ...
- “全栈2019”Java多线程第十四章:线程与堆栈详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho
数论入门2 另一种类型的数论... GCD,LCM 定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有: 将a和b分解质因数为\(a=p1^{a1}p ...
- 使用memcache或redis限制某个用户或者某ip用户一段时间内最大投票次数
实现每个用户在某网站10分钟内最多投票5次 function isFrequently($key){ $t = 60*10; $n = 5; $mem = new Memcache(); $mem-& ...