Classe sintética em Java


143

O que é uma classe sintética em Java? Por que deveria ser usado? Como posso usá-lo?


1
Todas as respostas "fora do seu código" estão desatualizadas no Java 8, pois as lambdas podem ser implementadas como classes sintéticas (não anônimas).
OrangeDog

Para ser justo, um lambda ainda não é "estritamente" uma classe definida explicitamente dentro do seu código. Portanto, "fora do seu código" ainda é válido. O compilador gera as classes sintéticas para você sem definição explícita no seu código.
ManoDestra 15/07/19

Respostas:


15

Por exemplo, quando você tem uma instrução switch, o java cria uma variável que começa com um $. Se você quiser ver um exemplo disso, espreite o reflexo java de uma classe que possui uma instrução switch. Você verá essas variáveis ​​quando tiver pelo menos uma instrução switch em qualquer lugar da classe.

Para responder sua pergunta, não acredito que você possa acessar (além da reflexão) as classes sintéticas.

Se você está analisando uma classe sobre a qual você não conhece nada (via reflexão) e precisa saber coisas muito específicas e de baixo nível sobre essa classe, pode acabar usando métodos de reflexão em Java que têm a ver com classes sintéticas. O único "uso" aqui é obter mais informações sobre a classe para usá-la adequadamente em seu código.

(Se você estiver fazendo isso, provavelmente está criando uma estrutura de algum tipo que outros desenvolvedores poderiam usar.)

Caso contrário, se você não estiver usando reflexão, não há usos práticos de classes sintéticas que eu conheça.


1
Sim, código de exemplo seria bom se você pudesse dar um exemplo /
nanofarad

36
Isso não responde à pergunta.
Dawood ibn Kareem

Para o caso do switch, não tenho certeza se isso acontece em todos os switches, mas observei isso no switch com enumerações; o compilador gera classe anônima com um campo estático único que fornece um mapeamento Enum.ordinal () -> 1, 2, 3 ... (para uma sequência sem lacunas) e, em seguida, uma instrução de pesquisa executa o comutador nessa sequência, não diretamente em ordinais.
Radim Vansa

106

Java tem a capacidade de criar classes em tempo de execução. Essas classes são conhecidas como Classes sintéticas ou Proxies dinâmicos.

Consulte http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html para obter mais informações.

Outras bibliotecas de código-fonte aberto, como CGLIB e ASM, também permitem gerar classes sintéticas e são mais poderosas que as bibliotecas fornecidas com o JRE.

As classes sintéticas são usadas pelas bibliotecas AOP (Aspect Oriented Programming), como Spring AOP e AspectJ, bem como pelas bibliotecas ORM, como o Hibernate.


6
Proxies dinâmicos não são Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
classes

3
O javadoc para java.lang.reflect.Member#isSyntheticdiz: Retorna true se esse membro foi introduzido pelo compilador; retorna false caso contrário.
Guillaume Husta 17/02

Eu acredito que o javadoc para java.lang.reflect.Member#isSyntheticé irrelevante para a pergunta original. Membros são campos, construtores e métodos. A pergunta original era sobre classes sintéticas , não membros sintéticos. No Java 8, as expressões lambda dão origem a classes sintéticas - não tenho certeza de que outras circunstâncias possam surgir.
P. Jeremy Krieg

54

Bem, eu encontrei a resposta para a primeira pergunta no google:

Uma classe pode ser marcada como sintética se for gerada pelo compilador, ou seja, não aparecer no código-fonte.

Esta é apenas uma definição básica, mas eu a encontrei em um tópico do fórum e não havia explicação. Ainda procurando um melhor ...


15

classes / métodos / campos sintéticos:

Essas coisas são importantes para a VM. Veja o seguinte snippet de código:

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 六四 事件 法轮功, não, apenas métodos de acesso sintético.
precisa saber é o seguinte

8

De acordo com essa discussão , embora a especificação da linguagem descreva uma propriedade "isSynthetic" para classes, isso é praticamente ignorado pelas implementações e não é usado para proxies dinâmicos ou classes anônimas. Os campos e construtores sintéticos são usados ​​para implementar classes aninhadas (não há conceito de classes aninhadas no código de bytes, apenas no código-fonte).

Eu acho que o conceito de classe sintética simplesmente provou não ser útil, ou seja, ninguém se importa se uma classe é sintética. Com campos e métodos, provavelmente é usado em exatamente um lugar: para determinar o que mostrar em uma exibição de estrutura de classe IDE - você deseja que métodos e campos normais sejam exibidos lá, mas não os sintéticos usados ​​para simular classes aninhadas. OTOH, você deseja que classes anônimas apareçam lá.


@ OrangeDog: sim, foi o que eu escrevi.
Michael Borgwardt

Esta resposta parece estar desatualizada, já que as referências ao método 8 - lambdas e java utilizam esse recurso. Eu adicionei uma resposta demonstrando isso
Hulk

7

Eles são criados pela JVM em tempo de execução, quando invocam membros privados da classe interna para fins de depuração

Os métodos, campos, classe criados pela JVM durante o tempo de execução para sua finalidade de execução são chamados Synthetic

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

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


Eu acho que você quer dizer em tempo de compilação, e não em tempo de execução.
Mostowski Collapse

@athis, você quis dizer javac, não JVM?
Miha_x64

3

Classes sintéticas ou proxies dinâmicos também são usados ​​pelo EasyMock para criar implementações de interfaces ou classes abstratas em tempo de execução.

http://www.easymock.org/


2

Quando o compilador Java compila certas construções, como classes internas, ele cria construções sintéticas ; são classes, métodos, campos e outras construções que não possuem uma construção correspondente no código-fonte.
Usos: Construções sintéticas permitem que os compiladores Java implementem novos recursos da linguagem Java sem alterações na JVM. No entanto, construções sintéticas podem variar entre diferentes implementações do compilador Java, o que significa que os arquivos .class também podem variar entre diferentes implementações.
referência: docs.oracle.com


2

Como várias respostas já apontaram, o compilador pode gerar várias construções (incluindo classes) que não correspondem diretamente a algo no código de fonte. Estes devem ser marcados como sintéticos:

13.1 A forma de um binário

Uma representação binária para uma classe ou interface também deve conter todo o
[...] seguinte:
11. Uma construção emitida por um compilador Java deve ser marcada como sintética se não corresponder a uma construção declarada explícita ou implicitamente no código-fonte. , a menos que a construção emitida seja um método de inicialização de classe (JVMS §2.9).
[...]

Conforme apontado por @Holger em um comentário para outra pergunta, exemplos relevantes para essas construções são os objetos Class que representam referências de método e lambdas:

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

Resultado:

true
true

Embora isso não seja mencionado explicitamente, segue-se de 15.27.4. Avaliação em tempo de execução de expressões lambda :

O valor de uma expressão lambda é uma referência a uma instância de uma classe com as seguintes propriedades: [...]

e a redação quase idêntica para as referências de método ( 15.13.3. Avaliação em tempo de execução das referências de método ).

Como essa classe não é mencionada explicitamente em nenhum lugar do código-fonte, ela deve ser sintética.


1

Se eu entendi direito, uma classe sintética é aquela gerada em tempo real, sem precisar dar um nome explícito. Por exemplo:

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

Isso cria uma subclasse sintética de Thread e substitui seu método run (), depois a instancia e inicia.


3
eu pensei que era uma classe interna anônima
Kumar Abhinav

2
Eu tenho que concordar com @KumarAbhinav. Nem todas as classes internas anônimas são sintéticas. Veja: xinotes.net/notes/note/1339
bvdb

Classes internas anônimas não geram classes sintéticas no Oracle JDK 1.8.0_45, elas geram classes não sintéticas separadas com nomes do tipo Outer$1.class.
Ciro Santilli escreveu:

1

Uma classe sintética não aparece no seu código: é composta pelo compilador. Por exemplo, um método de ponte composto pelo compilador em java é tipicamente sintético.

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");
    }
}

Usando o comando javap -verbose DateInterval, você pode ver um método de ponte:

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

Isso foi composto pelo compilador; não aparece no seu código.


1

O que é uma classe sintética em Java?

Uma syntheticclasse é um .classarquivo gerado pelo Java Compiler e não existe no código-fonte.

Exemplo de uso da syntheticclasse: Classe interna anônima

  • java.text.DigitList $ 1 é uma syntheticclasse e é uma classe interna anônima dentro de java.text.DigitList
  • E não há um arquivo de código-fonte com o nome like, DigitList$1.javamas é um arquivo interno emDigitList.java

Por que deveria ser usado?

É um mecanismo dentro da lógica do compilador Java para gerar o .classarquivo

Como posso usá-lo?

Não, os desenvolvedores NÃO o usam diretamente.

O compilador Java usa syntheticpara gerar .classarquivo e, em seguida, a JVM lê o .classarquivo para executar a lógica do programa.

Mais detalhes

  • Este artigo explica a syntheticaula em detalhes
  • Este link lista todas syntheticas saídas de classe no JDK

o artigo é muito útil, obrigado
JasonMing 16/03

0

Construções sintéticas são classes, métodos, campos etc. que não possuem uma construção correspondente no código-fonte. Construções sintéticas permitem que os compiladores Java implementem novos recursos da linguagem Java sem alterações na JVM. No entanto, construções sintéticas podem variar entre diferentes implementações do compilador Java, o que significa que os arquivos .class também podem variar entre diferentes implementações.


1
-1. O mesmo texto, literalmente, foi publicado na resposta dada um ano antes da sua [ stackoverflow.com/a/24271953/1144395] e, ainda mais, essa resposta citou adicionalmente a referência oficial onde o texto se originou e forneceu formatação para facilitar a leitura . Por favor, não envie mensagens de spam avidamente com respostas claramente duplicadas.
naki 2/09/17
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.