java this$0

有synthetic标记的field和method是class内部使用的,正常的源代码里不会出现synthetic field。小颖编译工具用的就是jad.所有反编译工具都不能保证完全正确地反编译class。所以你不能要求太多。
下面我给大家介绍一下synthetic

下面的例子是最常见的synthetic field
class parent
{
public void foo()
{
}
class inner
{
inner()
{
foo();
}
}
}
非static的inner class里面都会有一个this$0的字段保存它的父对象。编译后的inner class 就像下面这样:
class parent$inner
{
synthetic parent this$0;
parent$inner(parent this$0)
{
this.this$0 = this$0;
this$0.foo();
}
}
所有父对象的非私有成员都通过 this$0来访问。

还有许多用到synthetic的地方。比如使用了assert 关键字的class会有一个
synthetic static boolean $assertionsDisabled 字段
使用了assert的地方
assert condition;
在class里被编译成
if(!$assertionsDisabled && !condition)
{
throw new AssertionError();
}

还有,在jvm里,所有class的私有成员都不允许在其他类里访问,包括它的inner class。在java语言里inner class是可以访问父类的私有成员的。在class里是用如下的方法实现的:
class parent
{
private int value = 0;
synthetic static int access$000(parent obj)
{
return value;
}
}
在inner class里通过access$000来访问value字段。

 

 

 

 

注意:不支持内部类成员字段 this$0

 

“内部类字段 this$0 迁移到名为 Enclosing_Instance 的公共只读属性。”

当 Java Language Conversion Assistant 遇到 this$0 字段时,此注释出现在代码编辑器中。在 Visual J++ 中,内部类具有名为 this$0 的匿名公共只读成员字段,该字段引用封闭类。由于在 .NET Framework 中不支持此字段,因此为内部类提供了名为 Enclosing_Instance 的公共只读属性,该属性返回由 Java Language Conversion Assistant 提供的私有成员 EnclosingInstance 的值。

示例

原始的 Visual J++ 代码:

public class Class1
{
    int i = 0;
    class Class2
    {
        public Class2()
        {
            System.out.println(this$0.i);
        }
    }
}

等效的 C# 代码:

using System;
public class Class1
{
    internal int i = 0;
    
    class Class2
    {
        private void InitBlock(Class1 EnclosingInstance)
        {
            this.EnclosingInstance = EnclosingInstance;
        }
        private Class1 EnclosingInstance;
        public Class2(Class1 EnclosingInstance)
        {
            InitBlock(EnclosingInstance);
            //UPGRADE_NOTE: Inner class field this$0 migrates to a public read-only Enclosing_Instance property.
            System.Console.Out.WriteLine(Enclosing_Instance.i);
        }
        public Class1 Enclosing_Instance
        {
            get
            {
                return EnclosingInstance;
            }
        }
    }
}

 

 

 

java中this$0的含义及用法

(2012-01-19 22:43:33)
标签:

杂谈

分类: java

java中this$0的含义及用法,具体case是这样的:
通过测试工具去探测界面UI上的控件FlatButton实例对象,但是拿到的最终对象是FlatButton的内部类TextButton对象,
所以这里需要从一个内部类的实例拿到所在外部类的实例,this$0这时就派上用处了。
示例方案如下:

//通过工具获取到TextButton实例对象
textButton=getButtonByToolMethod ();
//获取内部类TextButton的一个字段this$0信息
//this$0特指该内部类所在的外部类的引用,不需要手动定义,编译时自动加上
Filed outerField=textButton.getClass().getDeclaredField("this$0");
//this$0是私有的,提升访问权限
outerField.setAccessible(true);
//拿到该字段上的实例值
FlatButton flatButton=(FlatButton)outerField.get(textButton);

this$0就是内部类所自动保留的一个指向所在外部类的引用。
另外,受到$后的数字0启发,发现原来数字还可以有1,2,3..., 具体可以看如下代码就一清二楚了.
//Outer.java
public class Outer {//this$0
public class FirstInner {//this$1
public class SecondInner {//this$2
public class ThirdInner {
}
}
}

public static void main(String[] args) throws Exception{
//初始化各内外实例
Outer test = new Outer();
FirstInner first = test.new FirstInner();
FirstInner.SecondInner second = first.new SecondInner();
FirstInner.SecondInner.ThirdInner third=second.new ThirdInner();
//Outer,this$0
Field outerfield = first.getClass().getDeclaredField("this$0");
outerfield.setAccessible(true);
Object object = outerfield.get(first);
System.out.println(object instanceof Outer);
//FirstInner,this$1
Field firstInnerfied = second.getClass().getDeclaredField("this$1");
firstInnerfied.setAccessible(true);
object = firstInnerfied.get(second);
System.out.println(object instanceof FirstInner);
//SecondInner,this$2
Field secondInnerfield = third.getClass().getDeclaredField("this$2");
secondInnerfield.setAccessible(true);
object = secondInnerfield.get(third);
System.out.println(object instanceof FirstInner.SecondInner);
}
}

其实用 Java 反编译工具生成内部类可以更加清楚
public class Outer$FirstInner{//FirstInner内部类有一个带外部类参数的构造子
public Outer$FirstInner(Outer paramOuter) {}
....
}

public class Outer$FirstInner$SecondInner{
public Outer$FirstInner$SecondInner(Outer.FirstInner paramFirstInner){}
....
}

public class Outer$FirstInner$SecondInner$ThirdInner{
public Outer$FirstInner$SecondInner$ThirdInner(Outer.FirstInner.SecondInner paramSecondInner){}
}

可见每个内部类都有一个指向所在最近的外部类的一个引用,只不过该引用不需要手动添加,编译器会负责。

 

 

 

 

http://blog.csdn.net/fuuckwtu/article/details/6803624

你可能感兴趣的:(java)