簡體   English   中英

Java 中的合成類

[英]Synthetic Class in Java

Java 中的合成類是什么? 為什么要使用它? 我怎樣才能使用它?

Java 具有在運行時創建類的能力。 這些類被稱為合成類或動態代理。

有關詳細信息,請參閱http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html

其他開源庫(例如CGLIBASM)也允許您生成合成類,並且比 JRE 提供的庫更強大。

合成類由 AOP(面向方面​​的編程)庫(例如 Spring AOP 和 AspectJ)以及 ORM 庫(例如 Hibernate)使用。

好吧,我在谷歌上找到了第一個問題的答案:

如果一個類是由編譯器生成的,即它沒有出現在源代碼中,則它可能被標記為合成類。

這只是一個基本定義,但我在論壇帖子中找到了它,沒有任何解釋。 仍在尋找更好的...

合成類/方法/字段:

這些東西對 VM 很重要。 看看下面的代碼片段:

class MyOuter {

  private MyInner inner;

  void createInner() {
    // The Compiler has to create a synthetic method
    // to construct a new MyInner because the constructor
    // is private.
    // --> synthetic "constructor" method
    inner = new MyInner();

    // The Compiler has to create a synthetic method
    // to doSomething on MyInner object because this
    // method is private.
    // --> synthetic "doSomething" method
    inner.doSomething();
  }

  private class MyInner {
    // the inner class holds a syntetic ref_pointer to
    // the outer "parent" class
    // --> synthetic field
    private MyInner() {
    }
    private void doSomething() {
    }
  }
}

例如,當您有一個 switch 語句時,java 會創建一個以 $ 開頭的變量。 如果您想看到這樣的示例,請查看其中包含 switch 語句的類的 Java 反射。 當您在類中的任何地方至少有一個 switch 語句時,您就會看到這些變量。

為了回答您的問題,我認為您無法訪問(反射除外)合成類。

如果您正在分析一個您一無所知的類(通過反射)並且需要了解關於該類的非常具體和低級的事情,那么您最終可能會使用與合成類有關的 Java 反射方法。 此處唯一的“用途”是獲取有關該類的更多信息,以便在您的代碼中適當地使用它。

(如果您這樣做,您可能正在構建其他開發人員可以使用的某種框架。)

否則,如果您不使用反射,那么我所知道的合成類就沒有實際用途。

根據這個討論,雖然語言規范描述了類的“isSynthetic”屬性,但實現幾乎忽略了這一點,並且不用於動態代理或匿名類。 合成字段和構造函數用於實現嵌套類(字節碼中沒有嵌套類的概念,只有在源代碼中)。

我認為合成類的概念已經被證明是沒有用的,即沒有人關心一個類是否是合成的。 對於字段和方法,它可能正好用在一個地方:確定在 IDE 類結構視圖中顯示什么 - 您希望在那里顯示普通方法和字段,而不是用於模擬嵌套類的合成方法和字段。 OTOH,您確實希望匿名類出現在那里。

它們是由 JVM 在運行時為調試目的調用內部類的私有成員時創建的

JVM 在運行時為其執行目的創建的方法、字段、類稱為 Synthetic

http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html

http://javapapers.com/core-java/java-synthetic-class-method-field/

Java 中的合成類是什么?

synthetic類是由Java Compiler生成的.class文件,它不存在於源代碼中。

synthetic類的使用示例:匿名內部類

為什么要使用它?

它是 Java 編譯器邏輯內部的一種機制,用於生成.class文件

我怎樣才能使用它?

不,開發人員直接使用它。

Java 編譯器使用synthetic生成.class文件,然后 JVM 讀取.class文件來執行程序邏輯。

更多詳情

  • 這篇文章詳細解釋了synthetic
  • 鏈接列出了JDK中的所有synthetic類出口

EasyMock 還使用合成類或動態代理在運行時創建接口或抽象類的實現。

http://www.easymock.org/

當 Java 編譯器編譯某些構造(例如內部類)時,它會創建合成構造 這些是在源代碼中沒有相應構造的類、方法、字段和其他構造。
用途:合成構造使 Java 編譯器能夠在不更改 JVM 的情況下實現新的 Java 語言功能。 但是,不同的 Java 編譯器實現之間的合成構造可能會有所不同,這意味着 .class 文件也可能因不同的實現而有所不同。
參考: docs.oracle.com

正如各種答案已經指出的那樣,編譯器可以生成不直接對應於源代碼中的某些內容的各種構造(包括類)。 這些必須標記為合成:

13.1. 二進制的形式

類或接口的二進制表示還必須包含以下所有內容:
[...]
11. 如果 Java 編譯器發出的構造與源代碼中顯式或隱式聲明的構造不對應,則必須將其標記為合成的,除非發出的構造是類初始化方法(JVMS §2.9)。
[...]

正如@Holger在對另一個問題的評論中指出的那樣,此類構造的相關示例是表示方法引用和 lambda 的 Class 對象:

System.out.println(((Runnable) System.out::println).getClass().isSynthetic());
System.out.println(((Runnable) () -> {}).getClass().isSynthetic());

輸出:

true
true

雖然沒有明確提到這一點,但它來自15.27.4。 Lambda 表達式的運行時評估

lambda 表達式的值是對具有以下屬性的類實例的引用:[...]

以及方法引用的幾乎相同的措辭( 15.13.3.方法引用的運行時評估)。

由於在源代碼的任何地方都沒有明確提到這個類,它必須是合成的。

合成類不會出現在您的代碼中:它是由編譯器組成的。 例如,在java 中由編譯器組成的橋接方法通常是合成的。

public class Pair<T> {
    private T first;
    private T second;
    public void setSecond(T newValue) {
        second = newValue;
    }
}


public class DateInterval extends Pair<String> {
    public void setSecond(String second) {
        System.out.println("OK sub");
    }

    public static void main(String[] args) throws NoSuchFieldException, SecurityException {
        DateInterval interval = new DateInterval();
        Pair pair = interval;
        pair.setSecond("string1");
    }
}

使用命令javap -verbose DateInterval ,可以看到橋接方法:

public void setSecond(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC

這是由編譯器組成的; 它不會出現在您的代碼中。

如果我猜對了,合成類是動態生成的,而不必給它一個明確的名稱。 例如:

//...
Thread myThread = new Thread() {
         public void run() {
           // do something ...
         }
       };
myThread.start();
//...

這將創建 Thread 的合成子類並覆蓋其 run() 方法,然后實例化它並啟動它。

合成構造是在源代碼中沒有相應構造的類、方法、字段等。 合成構造使 Java 編譯器能夠在不更改 JVM 的情況下實現新的 Java 語言功能。 但是,不同的 Java 編譯器實現之間的合成構造可能會有所不同,這意味着 .class 文件也可能因不同的實現而有所不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM