Classe sintética em Java

143

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

andHapp
fonte
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.

Milhous
fonte
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.

Andrew Newdigate
fonte
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 ...

andHapp
fonte
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() {
    }
  }
}
Vinay W
fonte
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á.

Michael Borgwardt
fonte
@ 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/

sathis
fonte
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/

user2427
fonte
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

anavaras lamurep
fonte
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.

Hulk
fonte
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.

Ivan
fonte
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.

JavaFresher
fonte
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
Feliz
fonte
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.

Anoop Dixith
fonte
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