[英]How to access fields declared inside anonymous object without reflection?
可以使匿名類在Java中有新字段:
class A {
public static void main(String[] args) {
Object o = new Object() {
public int x = 0;
{
System.out.println("x: " + x++);
System.out.println("x: " + x++);
}
};
System.out.println(o.x);
}
}
但是在這個例子中無法訪問它們,因為o
是Object
類型:
$ javac A.java && java A
A.java:10: cannot find symbol
symbol : variable x
location: class java.lang.Object
System.out.println(o.x);
^
1 error
請注意, o
實際上不是Object
,它是擴展Object
的不同類的實例。 這個類有一個公共字段x
。 這個班有名字嗎? 我怎樣才能使o
成為合適的類型以便我可以獲得ox
? (請注意, 可以使用反射執行此操作 ,但我想靜態執行此操作)。
這個類有一個名字。 這是A$1
。 但是,您無法在編譯時訪問它(編譯器為您創建A$1
)。 因此,您無法在沒有反射的情況下訪問該字段。
如果您在Eclipse中,則可以使用“ 源”菜單( Alt Shift S )→“ 將匿名類轉換為嵌套”將其自動轉換為“真實”類。
或者,您可以:
class A {
public static void main(String[] args) {
I o = new I() {
public int x = 0;
{
System.out.println("x: " + x++);
System.out.println("x: " + x++);
}
public int getX() { return x; }
};
System.out.println(o.getX());
}
interface I {
public int getX();
}
}
編輯:這是一個非常邪惡的方法 ,你不應該做到這一點 :
class A {
public static void main(String[] args) {
Object o = new Object() {
public int x = 0;
{
System.out.println("x: " + x++);
System.out.println("x: " + x++);
}
public Object clone() {
// BAD BAD BAD
return x;
}
};
try {
System.out.println(o.clone());
} catch (CloneNotSupportedException cnse) {
assert false;
}
}
}
您可以直接在匿名類創建表達式上訪問它:
class A {
public static void main(String[] args) {
System.out.println(new Object() {
public int x = 0;
{
System.out.println("x: " + x++);
System.out.println("x: " + x++);
}
}.x);
}
}
但是,你不能再使用創建的對象了,所以它有點無用。
Java不是C#,如果我沒有弄錯,那里允許這樣的語法糖。 你可以看一下sun.reflect.MagicAccessorImpl。 但這門課程並不常見。 僅用於自動生成的代碼。 如果擴展MagicAccessorImpl,JVM將不會執行字段訪問級別檢查。 所以你可以這樣做:
// ----- A.java -----
class A {
private int privateField = 5;
}
// ----- B.java -----
class B extends sun.reflect.MagicAccessorBridge {
public static void main(String[] args) {
A a = new A();
a.privateField = 10;
System.out.println(a.privateField);
}
}
// ----- MagicAccessorBridge.java -----
package sun.reflect;
public class MagicAccessorBridge extends MagicAccessorImpl {
// Since MagicAccessorImpl is package-private, we'll make a public bridge
}
像這樣
class A {
public static void main(String[] args) {
Object o = new Object() {
public int x = 0;
{
System.out.println("x: " + x++);
System.out.println("x: " + x++);
}
};
//System.out.println(((A$1)o).x);
}
}
編譯一次
$ java A.java
取消注釋打印線
重新編譯和運行
$ java A.java && java A
x: 0
x: 1
2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.