O Java 8 começou a aparecer, trazendo um novo recurso: use a expressão Lambda (JSR-335) para programação funcional. Hoje vamos discutir parte do Lambda: Extensão Virtual, também conhecida como Método Defender. Esse recurso permite implementar o método de fornecer métodos na definição da interface. Por exemplo, você pode definir um método para interfaces existentes (como LIST e MAP) para que outros desenvolvedores não precisem implementar esses métodos, o que é um pouco como abstrato, mas na verdade é uma interface. Obviamente, o Java 8 é teoricamente compatível com as bibliotecas existentes.
O método de extensão virtual traz múltiplas características de herança ao Java. Talvez você possa ver a sombra da herança múltipla através desse recurso. Mas você ainda pode simular a herança do estado da instância. Descreverei a herança do estado através do Mixin no próximo artigo em detalhes.
O que é misturado no mixin?
A mistura é uma classe abstrata de uma combinação. Por exemplo, se você tem uma aula para indicar "cavalo", pode instantar essa classe para criar um exemplo de "cavalo" e depois expandi -lo herdando como "garagem" e "jardim".
Val myhouse = nova casa com garagem com jardim
Da herança de Mixin não é uma especificação específica, este é apenas um método usado para adicionar várias funções às categorias existentes. Em OOP, com Mixin, você tem a legibilidade da classe através dela.
Por exemplo, existe um método Mixin no módulo SocketServer de Python.
Classe forkingpServer (forkingmixin, udpServer): Passclass forkingtcpServer (forkingmixin, tcpServer): passa classe threadingudpServer (threadMixin): passtclass ThreadingtcpServer (ThreadingMixin, tcpServer): passagem
O que é um método de extensão virtual?
O Java 8 introduzirá o conceito de extensão virtual, também chamado de método de defensor público.
O Vem pretende fornecer o método padrão para a interface Java. Essa biblioteca de terceiros como o Hibernate não precisa repetir todos os métodos dessas APIs de coleta, pois forneceu alguns métodos padrão.
A seguir, é apresentado um exemplo de como definir o método na interface:
Coleção de interface pública <t> estende Iterable <T> {<r> Coleção <r> filtro (predicado <t> P) padrão {Return Collections.
Simulação mista de Java 8
Agora chegamos a alcançar um efeito misto através do VEM, mas o aviso com antecedência é: por favor, não use no trabalho!
A implementação a seguir não é segura e pode haver um problema de vazamento de memória, o que depende dos métodos HashCode e é igual à definida na classe.
Primeiro de tudo, definimos uma definição de um método (Bean de Estado simulado) e fornecemos o método:
Interface pública switchablemixin {boolean isAtivated () padrão {return switchables.isactivated (this);} void setActivated (atividade booleana) falha {switchables.setActivated (this, ativado);}}
Em seguida, definimos uma classe de ferramentas que contém uma instância do mapa para salvar a associação de instâncias e status.
Classe final Public Switchable {private estático mapa <switchablemixin, switchableDevicestate> switch_states = new hashmap <() (); Atividade;} public static void SetActivated (dispositivo SwitchableMixin, ativado booleano) {switchableDevicestate = switch_states.get (dispositivo); .Activated = ativado;} classe estática privada SwitchableDevicestate {private boolean ativado;}}
Aqui está um caso de uso que destaca a herança do estado:
Classe estática privada Dispositivo {} classe estática privada Devicea estende o dispositivo implementa SwitchableMixin {} classe estática privada dispositivo estende o dispositivo IMP LIMET SWITCHABLEMIXIN {}
"Coisas completamente diferentes"
A implementação acima parece ser normal, mas o arquiteto de idioma Java da Oracle, Brian Goetz
Interface FakeBrokenMixin {mapa estático <FakeBrokenMixin, String> BackingMap = Coleções. Put (este, nome);}} interface x estende Runnable, FakebrokenMixin {} x makex () {return () -> {System.println ("x");}; (); x1.setName (x1 ");
Que resultado você adivinhará que este código será exibido após a execução?
Solução de dúvida
À primeira vista, não há problema com este código de implementação. X é uma interface que contém apenas um método, porque GetName e SetName já têm a definição padrão, mas o método de execução da interface executável não está definido. implementação do método de execução. Portanto, o resultado que você deseja este programa após a execução é:
X1x2
Se você excluir a chamada do método GetName, o resultado da execução se tornará:
MyTest $ 1@30AE8764MYTEST $ 1@123ACF34
Essas duas linhas mostram que a execução do método Makex vem de duas instâncias diferentes e, neste momento, o atual OpenJDK 8 é gerado (aqui eu uso o OpenJDK 8 24.0-B07).
De qualquer forma, o atual OpenJDK 8 não reflete o comportamento final do Java 8.
X2x2
Se você não chamar o método getName, ele será exibido:
Mytest $ $ lambda $ 1 a 5506d4eamytest $ $ lambda $ 1@5506d4ea
Cada método makex chama parece ser uma instância de singles da mesma classe interna anônima.
Porque durante a compilação, a expressão de Lambda não passou por uma tradução completa. Esta instrução contém todas as meta -informações necessárias sobre a expressão do Labda em tempo de execução. Incluindo o nome do método, o tipo de entrada e saída e um método chamado bootstrap. O método de bootstrap é usado para definir a instância de receber esse método.
De volta à pergunta agora, a expressão de Lambda se transformou em um método estático privado, () -> {System.out.println ("x");} foi transferido para o mytest:
Private estático void lambda $ 0 () {System.out.println ("x");}
Se você usar o parâmetro privado com o dispositivo de contra-compilação Javap e poder ver esse método, também poderá usar o parâmetro -c para visualizar uma conversão mais completa.
Quando você executa o programa, a JVM chama o método metafativo Lambda para tentar explicar as instruções invocedynâmicas. Em nosso exemplo, quando o Makex é chamado pela primeira vez, o método de metafactoria lambda gera uma instância de um X e vinculou dinamicamente o método de execução ao método Lambda $ 0 Na memória, a instância da sua segunda chamada é a mesma da primeira vez.
Você consertou? Existe uma solução?
Não há reparo ou solução direta para esse problema. Embora o programa Java 8 da Oracle padrão-XDlambdatomethod, porque esse parâmetro não faz parte da especificação da JVM, a implementação de diferentes fornecedores e a JVM é diferente. Para uma expressão de Lambda, a única coisa que você pode esperar é implementar seu método de interface na classe.
Outros métodos
Até agora, embora nossa imitação de Mixin não possa ser compatível com o Java 8, ainda é possível adicionar vários serviços por meio de herança e compromisso múltipla a existir. Este método é o padrão de campo virtual (modo de campo virtual).
Então dê uma olhada na nossa comunhão.
interface comutável {boolean isactive ();
Precisamos de uma interface comutável e fornecemos um método de abstração adicional para retornar à implementação comutável. O método integrado contém a definição padrão.
Interface pública comutableview estende comutável {switchable getSwitchable ();
Em seguida, criamos uma implementação completa comutável:
Classe pública SwitchableImpl implementa comunhão {private boolean Active;
Este é um exemplo do nosso modo de campo virtual:
Public Class Device {} classe pública Devicea estende o dispositivo implementa o SwitchableView {private comutável comutableImpl (); Comutável getSwitcable () {return switcle;}}
para concluir
Neste artigo, usamos dois métodos para adicionar vários serviços através do método de expansão virtual do Java 8. O primeiro método usa um mapa para armazenar o estado da instância. Outro método é usar um modo de campo virtual para retornar o exemplo de implementação final por meio de um getter abstrato. O segundo método é mais independente e seguro.
O método de extensão virtual é o novo recurso do Java.