O que é uma classe sintética em Java? Por que deveria ser usado? Como posso usá-lo?
O que é uma classe sintética em Java? Por que deveria ser usado? Como posso usá-lo?
Respostas:
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.
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.
Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
java.lang.reflect.Member#isSynthetic
diz: Retorna true se esse membro foi introduzido pelo compilador; retorna false caso contrário.
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.
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 ...
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() {
}
}
}
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á.
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/
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.
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
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:
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.
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.
Outer$1.class
.
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.
O que é uma classe sintética em Java?
Uma synthetic
classe é um .class
arquivo gerado pelo Java Compiler e não existe no código-fonte.
Exemplo de uso da synthetic
classe: Classe interna anônima
synthetic
classe e é uma classe interna anônima dentro de java.text.DigitListDigitList$1.java
mas é um arquivo interno emDigitList.java
Por que deveria ser usado?
É um mecanismo dentro da lógica do compilador Java para gerar o .class
arquivo
Como posso usá-lo?
Não, os desenvolvedores NÃO o usam diretamente.
O compilador Java usa synthetic
para gerar .class
arquivo e, em seguida, a JVM lê o .class
arquivo para executar a lógica do programa.
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.