자바의 합성 클래스


143

Java의 합성 클래스는 무엇입니까? 왜 사용해야합니까? 어떻게 사용하나요?


1
람다는 합성 (익명 아님) 클래스로 구현 될 수 있으므로 모든 "코드에 없음"답변은 Java 8에서 오래되었습니다.
OrangeDog

공평하게 말하면, 람다는 여전히 코드 내에 명시 적으로 정의 된 "엄격한"클래스가 아닙니다. 따라서 "코드에 없음"은 여전히 ​​유효합니다. 컴파일러는 코드에서 명시적인 정의없이 합성 클래스를 생성합니다.
ManoDestra

답변:


15

예를 들어, switch 문이 있으면 java는 $로 시작하는 변수를 만듭니다. 이에 대한 예제를 보려면 switch 문이 포함 된 클래스의 Java 리플렉션을 살펴보십시오. 클래스 어딘가에 적어도 하나의 switch 문이있을 때 이러한 변수가 표시됩니다.

귀하의 질문에 대답하기 위해 합성 클래스에 액세스 할 수 있다고 생각하지 않습니다.

리플렉션을 통해 알지 못하는 클래스를 분석하고 해당 클래스에 대해 매우 구체적이고 저수준 인 것을 알아야하는 경우 합성 클래스와 관련된 Java 리플렉션 방법을 사용할 수 있습니다. 여기서 유일한 "사용"은 코드에서 클래스를 적절하게 사용하기 위해 클래스에 대한 자세한 정보를 얻는 것입니다.

(이 작업을 수행하는 경우 다른 개발자가 사용할 수있는 일종의 프레임 워크를 구축하고있을 것입니다.)

그렇지 않으면 리플렉션을 사용하지 않는 경우 내가 아는 합성 클래스를 실제로 사용하지 않습니다.


1
예, 예제를 제공 할 수 있다면 샘플 코드가 좋을 것입니다.
nanofarad

36
이것은 질문에 대답하지 않습니다.
Dawood ibn Kareem

스위치의 경우, 이것이 모든 스위치에 대해 발생하는지 확실하지 않지만 열거 형이있는 스위치에 대해서는 이것을 관찰했습니다. 컴파일러는 매핑 Enum.ordinal ()-> 1, 2, 3 ... (갭이없는 시퀀스)을 제공하는 단일 정적 필드를 가진 익명 클래스를 생성 한 다음 lookupswitch 명령어가 직접이 아닌이 시퀀스에서 스위치를 실행합니다. 서수에.
Radim Vansa

106

Java는 런타임에 클래스를 작성할 수 있습니다. 이러한 클래스를 합성 클래스 또는 동적 프록시라고합니다.

자세한 내용은 http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html 을 참조하십시오.

CGLIBASM 과 같은 다른 오픈 소스 라이브러리 도 합성 클래스를 생성 할 수 있으며 JRE와 함께 제공된 라이브러리보다 강력합니다.

합성 클래스는 Spring AOP 및 AspectJ와 같은 AOP (Aspect Oriented Programming) 라이브러리와 Hibernate와 같은 ORM 라이브러리에서 사용됩니다.


6
동적 프록시는 합성 Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
클래스

3
javadoc for java.lang.reflect.Member#isSyntheticsays : 이 멤버가 컴파일러에 의해 도입 된 경우 true를 리턴합니다. 그렇지 않으면 false를 반환합니다.
기 illa Husta 2012

나는 javadoc java.lang.reflect.Member#isSynthetic이 원래의 질문과 관련이 없다고 생각합니다 . 멤버는 필드, 생성자 및 메서드입니다. 원래 질문은 합성 멤버가 아니라 합성 클래스 에 관한 것이 었습니다 . Java 8에서 람다 식은 합성 클래스를 생성합니다. 다른 상황이 발생할 수 있는지 잘 모르겠습니다.
Fr Jeremy Krieg

54

글쎄, 나는 구글의 첫 번째 질문에 대한 답을 찾았다.

클래스가 컴파일러에 의해 생성 된 경우, 즉 소스 코드에 나타나지 않으면 합성으로 표시 될 수 있습니다.

이것은 단지 기본 정의이지만 포럼 스레드에서 찾았으며 설명이 없습니다. 여전히 더 나은 것을 찾고 있습니다 ...


15

합성 수업 / 방법 / 분야 :

이러한 것들이 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() {
    }
  }
}

2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, 아니, 단지 합성 접근 자 방법.
Miha_x64

8

이 논의 에 따르면 , 언어 사양은 클래스에 대한 "isSynthetic"속성을 설명하지만 구현에서는 거의 무시되고 동적 프록시 또는 익명 클래스에는 사용되지 않습니다. 합성 필드 및 생성자는 중첩 클래스를 구현하는 데 사용됩니다 (바이트 코드에는 중첩 클래스 개념이 없으며 소스 코드에만 있음).

나는 합성 클래스의 개념이 단순히 유용하지 않은 것으로 입증되었다고 생각합니다. 즉, 클래스가 합성인지 아닌지는 아무도 신경 쓰지 않습니다. 필드와 메소드를 사용하면 IDE 클래스 구조 뷰에 표시 할 항목을 결정하기 위해 정확히 한 곳에 사용됩니다. 중첩 된 클래스를 시뮬레이션하는 데 사용되는 합성 메소드와 일반 메소드 및 필드가 표시되기를 원합니다. OTOH, 익명 클래스가 나타나기를 원합니다.


@OrangeDog : 예, 제가 쓴 것입니다.
Michael Borgwardt '

java 8-람다 및 메소드 참조 가이 기능을 사용하기 때문에이 답변은 구식 인 것 같습니다. 나는 이것을 증명하는 답변을
Hulk

7

디버깅 목적으로 내부 클래스의 개인 멤버를 호출 할 때 런타임시 JVM에 의해 작성됩니다.

실행 목적으로 런타임 동안 JVM이 작성한 메소드, 필드 및 클래스를 Synthetic이라고합니다.

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

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


런타임이 아니라 컴파일 타임을 의미한다고 생각합니다.
Mostowski Collapse

@sathis, JVM이 아닌 javac를 의미 했습니까?
Miha_x64


2

Java 컴파일러는 내부 클래스와 같은 특정 구문을 컴파일 할 때 합성 구문을 만듭니다 . 이들은 클래스, 메소드, 필드 및 소스 코드에 해당 구문이없는 기타 구문입니다.
용도 : 합성 구조를 통해 Java 컴파일러는 JVM을 변경하지 않고도 새로운 Java 언어 기능을 구현할 수 있습니다. 그러나 합성 구문은 Java 컴파일러 구현마다 다를 수 있습니다. 즉, .class 파일도 구현마다 다를 수 있습니다.
참조 : docs.oracle.com


2

다양한 답변이 이미 지적했듯이 컴파일러는 소스 코드의 내용과 직접적으로 일치하지 않는 다양한 구문 (클래스 포함)을 생성 할 수 있습니다. 이들은 합성으로 표시되어야합니다.

13.1. 이진의 형태

클래스 또는 인터페이스에 대한 이진 표현은 다음을 모두 포함해야합니다.
[...]
11. Java 컴파일러가 생성 한 구성이 소스 코드에서 명시 적 또는 암시 적으로 선언 된 구성과 일치하지 않으면 합성으로 표시되어야합니다. 생성 된 구문이 클래스 초기화 방법이 아닌 경우 (JVMS §2.9)
[...]

다른 질문에 대한 주석에서 @Holger 가 지적한 것처럼 이러한 구문의 관련 예제는 메소드 참조 및 람다를 나타내는 Class 객체입니다.

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

산출:

true
true

이것은 명시 적으로 언급되어 있지 않지만 15.27.4 부터 따릅니다. Lambda 식의 런타임 평가 :

람다 식의 값은 다음 속성을 가진 클래스의 인스턴스에 대한 참조입니다. [...]

그리고 메소드 참조에 대한 거의 동일한 표현 ( 15.13.3. 메소드 참조의 런타임 평가 ).

이 클래스는 소스 코드의 어느 곳에서도 명시 적으로 언급되지 않았으므로 합성되어야합니다.


1

내가 올바르게 이해하면 합성 클래스는 명시적인 이름을주지 않고 즉시 생성됩니다. 예를 들면 다음과 같습니다.

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

그러면 Thread의 합성 서브 클래스가 생성되고 run () 메서드가 재정의 된 다음 인스턴스화되어 시작됩니다.


3
나는 그것이 익명의 내부 클래스라고 생각했다
Kumar Abhinav

2
@KumarAbhinav에 동의해야합니다. 익명의 내부 클래스가 모두 합성 인 것은 아닙니다. 참조 : xinotes.net/notes/note/1339
bvdb

익명의 내부 클래스는 Oracle JDK 1.8.0_45에서 합성 클래스를 생성하지 않으며 이름이 type 인 별도의 비 합성 클래스를 생성합니다 Outer$1.class.
Ciro Santilli 郝海东 冠状 病 六四 事

1

Java의 합성 클래스는 무엇입니까?

synthetic클래스는 인 .class에 의해 생성 된 파일 자바 컴파일러 과 소스 코드에 존재하지 않습니다.

synthetic클래스 사용 예 : 익명 내부 클래스

  • java.text.DigitList $ 1synthetic클래스이며 java.text.DigitList 내부의 익명 내부 클래스입니다.
  • 그리고 같은 소스 코드 파일은 DigitList$1.java없지만 내부 파일입니다.DigitList.java

왜 사용해야합니까?

.class파일 을 생성하는 것은 Java 컴파일러 논리 내부의 메커니즘입니다.

어떻게 사용하나요?

아니요, 개발자는 직접 사용 하지 않습니다 .

Java 컴파일러 synthetic.class파일 을 생성 하는 데 사용 하고 JVM은 .class파일을 읽어 프로그램 논리를 실행합니다.

자세한 내용은

  • 기사에서는synthetic 수업에 대해 자세히 설명합니다.
  • 링크JDK의 모든 synthetic클래스 이탈을 나열합니다.

기사 는 매우 유용합니다. 감사합니다
JasonMing

0

합성 구문은 소스 코드에 해당 구문이없는 클래스, 메서드, 필드 등입니다. 합성 구조를 통해 Java 컴파일러는 JVM을 변경하지 않고도 새로운 Java 언어 기능을 구현할 수 있습니다. 그러나 합성 구문은 Java 컴파일러 구현마다 다를 수 있습니다. 즉, .class 파일도 구현마다 다를 수 있습니다.


1
-1. 매우 동일한 텍스트 인 그대로의 문장이 귀하의 답변 [ stackoverflow.com/a/24271953/1144395] 보다 1 년 전에 제공된 답변에 게시되었으며, 그 대답은 텍스트의 출처 인 공식 참조를 추가로 인용하고보다 쉽게 ​​읽을 수있는 형식을 제공했습니다. . 답변이 명확하게 중복 된 질문에는 탐욕스럽게 스팸 메일을 보내지 마십시오.
naki

0

합성 클래스는 코드에 나타나지 않습니다. 컴파일러로 구성됩니다. 예를 들어, 자바에서 컴파일러가 구성하는 브리지 방법은 일반적으로 합성입니다.

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

이것은 컴파일러에 의해 구성되었습니다. 코드에 나타나지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.