Recursos ocultos do Java

295

Depois de ler os Recursos ocultos do C # , perguntei-me: Quais são alguns dos recursos ocultos do Java?

grom
fonte
17
Observe que nem sempre é uma boa idéia usar esses recursos ocultos; muitas vezes são surpreendentes e confusos para outras pessoas que leem seu código.
Kevin Bourrillion
1
Você (/ alguém) provavelmente deve resumir as respostas ordenadamente no corpo da pergunta, como a pergunta em C #.
Ripper234

Respostas:

432

A inicialização com cinta dupla me pegou de surpresa alguns meses atrás, quando eu a descobri, nunca tinha ouvido falar antes.

ThreadLocals normalmente não são tão amplamente conhecidos como uma maneira de armazenar o estado por thread.

Como o JDK 1.5 Java possui ferramentas de simultaneidade extremamente bem implementadas e robustas além de apenas bloqueios, elas vivem em java.util.concurrent e um exemplo especificamente interessante é o subpacote java.util.concurrent.atomic que contém primitivas seguras para threads que implementam a comparação operação de swap e pode mapear para versões suportadas por hardware nativas reais dessas operações.

Boris Terzic
fonte
40
Inicialização com chaves duplas ... estranho ... eu seria cauteloso em adotar esse idioma em particular demais, já que na verdade ele cria uma subclasse anônima do objeto, o que poderia causar problemas confusos de igual / código de hash. java.util.concurrent é um pacote realmente ótimo.
MB.
6
eu tenho ensinado Java, e esta é a primeira vez que me deparei com esta sintaxe ... que vai mostrar que você nunca parar de aprender = 8-)
Yuval
49
Observe que, se você mantiver uma referência a uma coleção inicializada com esse idioma "chave dupla" (ou se a chamarmos por seu nome real - classe anônima com bloco inicializador), mantenha implicitamente uma referência ao objeto externo que pode causar memória desagradável vazamentos. Eu recomendo evitá-lo completamente.
Ddimitrov 05/10/08
51
"Inicialização de chaves duplas" é um nome muito eufemístico para criar uma classe interna anônima, encobrindo o que realmente está acontecendo e fazendo parecer que as classes internas deveriam ser usadas dessa maneira. Esse é um padrão que eu prefiro permanecer oculto.
22680
11
Quase, não é realmente um bloco estático, mas um "bloco inicializador" que é diferente, pois é executado em um horário diferente (veja o link que eu coloquei na resposta para obter mais detalhes)
Boris Terzic
279

União de junta na variação do parâmetro de tipo:

public class Baz<T extends Foo & Bar> {}

Por exemplo, se você quiser usar um parâmetro comparável e uma coleção:

public static <A, B extends Collection<A> & Comparable<B>>
boolean foo(B b1, B b2, A a) {
   return (b1.compareTo(b2) == 0) || b1.contains(a) || b2.contains(a);
}

Esse método artificial retorna true se as duas coleções fornecidas forem iguais ou se uma delas contiver o elemento especificado, caso contrário, false. O ponto a ser observado é que você pode invocar métodos de Comparable e Collection nos argumentos b1 e b2.

Apocalisp
fonte
Meu uso favorito para isso é quando você precisa de um método que aceite uma Carsequência Anexável.
30511 Neil Coffey
5
É possível ter um "OU" lá em vez do &?
mainstringargs
9
@Grasper: Não, OR (união desunida) não é fornecida nesse contexto. Mas você pode usar um tipo de dados de união separado como <A, B>. Este tipo é o duplo de um par <A, B>. Consulte a biblioteca Java Funcional ou as principais bibliotecas do Scala para obter um exemplo desse tipo de dados.
Apocalisp
5
Você deve dizer que você deve se estende apenas uma classe e várias interfaces -> public class Baz <T estende Clazz & Interface1 & InterfaceI ... e não class Baz <T estende Clazz1 & Clazzi>
JohnJohnGa
220

Fiquei surpreso com os inicializadores de instância outro dia. Eu estava excluindo alguns métodos dobrados em código e acabei criando vários inicializadores de instância:

public class App {
    public App(String name) { System.out.println(name + "'s constructor called"); }

    static { System.out.println("static initializer called"); }

    { System.out.println("instance initializer called"); }

    static { System.out.println("static initializer2 called"); }

    { System.out.println("instance initializer2 called"); }

    public static void main( String[] args ) {
        new App("one");
        new App("two");
  }
}

A execução do mainmétodo exibirá:

static initializer called
static initializer2 called
instance initializer called
instance initializer2 called
one's constructor called
instance initializer called
instance initializer2 called
two's constructor called

Eu acho que isso seria útil se você tivesse vários construtores e precisasse de código comum

Eles também fornecem açúcar sintático para inicializar suas aulas:

List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

Map<String,String> codes = new HashMap<String,String>(){{ 
  put("1","one"); 
  put("2","two");
}};
David Carlson
fonte
38
A vantagem disso sobre um método explícito que precisa ser chamado é que, se alguém adicionar um construtor posteriormente, não precisará se lembrar de chamar init (); isso será feito automaticamente. Isso pode evitar erros de futuros programadores.
Mr. Shiny and New # 10/1008
40
Além disso, diferente do método init (), ele pode inicializar os campos finais.
Darron
2
E se você estender a aula e instanciar vários filhos? Ainda vai se comportar da mesma maneira?
Kezzer
12
As pessoas geralmente desclassificam certificações (por exemplo, stackoverflow.com/questions/281100/281127#281127 ) e questionam especialmente seus méritos técnicos. Mas se mais programadores aqui estudassem para o seu SCJP, isso não seria considerado um "recurso oculto" por muitos. ;-)
Jonik 21/04/2009
12
Aposto que até o livro "java em 24 horas" tem esse "recurso óbvio". leia mais pessoal
:)
201

O JDK 1.6_07 + contém um aplicativo chamado VisualVM (bin / jvisualvm.exe) que é uma boa interface gráfica do usuário em cima de muitas das ferramentas. Parece mais abrangente que o JConsole.

Kevin Wong
fonte
E possui um plug-in (é uma coisa do netbeans) que permite usar plug-ins do Jconsole. Até legal.
Thorbjørn Ravn Andersen
VisualVM é a melhor coisa desde pão fatiado, realmente! Pena que não tem todas as características durante a execução contra JDK 1.5
Sandos
Acho o VisualVM lento ou inutilizável em algumas circunstâncias. O YourKit comercial não tem esse problema, mas infelizmente não é gratuito.
Roalt 23/09/10
As versões mais recentes do Visual VM, do JDK 1.6.0_22 e posterior, foram muito aprimoradas. Aposto que o JDK1.7 tem uma versão ainda melhor.
precisa saber é o seguinte
156

Para a maioria das pessoas que entrevisto para posições de desenvolvedor Java, os blocos rotulados são muito surpreendentes. Aqui está um exemplo:

// code goes here

getmeout:{
    for (int i = 0; i < N; ++i) {
        for (int j = i; j < N; ++j) {
            for (int k = j; k < N; ++k) {
                //do something here
                break getmeout;
            }
        }
    }
}

Quem disse gotoem java é apenas uma palavra-chave? :)

Georgy Bolyuba
fonte
2
Bem, prefiro ter a opção de fazer isso de várias maneiras. Por exemplo, vi pessoas usando System.exit (1); no código Servlet e EJB, mas isso não significa que devemos remover System.exit (); do JDK, certo?
Georgy Bolyuba 08/09/08
31
Sob algumas circunstâncias, dentro de uma construção de loop aninhado, pode ser útil continuar na próxima iteração de um loop externo. Este seria um uso razoável desse recurso.
Alasdairg
75
O que é especialmente desconhecido para muitos programadores (e provavelmente também) é que você pode rotular e sair de QUALQUER bloco antigo. Ele não precisa ser um loop - você pode apenas definir algum bloco arbitrário, dar um rótulo a ele e usar break com ele.
30511 Neil Coffey
27
Não é nada, apenas pode retornar a uma iteração anterior (ou seja: você não pode avançar). Este é o mesmo mecanismo que ocorre quando uma iteração retorna false. Dizer que java tem goto é como dizer que qualquer linguagem cujo compilador produz uma instrução JUMP possui uma instrução goto.
Zombies
4
Então você entrevista com base em curiosidades de Java, em vez de aptidão para resolver problemas e pensar em projetos. Vou me assegurar de nunca entrevistar sua empresa. :)
Javid Jamae
144

E quanto aos tipos de retorno covariantes existentes desde o JDK 1.5? É muito pouco divulgado, pois é uma adição pouco sexy, mas, pelo que entendi, é absolutamente necessário para os genéricos funcionarem.

Essencialmente, o compilador agora permite que uma subclasse restrinja o tipo de retorno de um método substituído a uma subclasse do tipo de retorno do método original. Portanto, isso é permitido:

class Souper {
    Collection<String> values() {
        ...
    }
}

class ThreadSafeSortedSub extends Souper {
    @Override
    ConcurrentSkipListSet<String> values() {
        ...
    }
}

Você pode chamar o valuesmétodo da subclasse e obter um thread classificado a salvo Setde Strings sem precisar converter para o ConcurrentSkipListSet.

serg10
fonte
Você pode fornecer um exemplo de uso?
Allain Lalonde
24
Eu uso muito isso. clone () é um ótimo exemplo. Ele deveria retornar Object, o que significa que você teria que dizer, por exemplo, (Lista) list.clone (). No entanto, se você declarar como clone da Lista () {...}, o elenco é desnecessário.
Jason Cohen
142

A transferência de controle em um bloco finalmente descarta qualquer exceção. O código a seguir não gera RuntimeException - ele está perdido.

public static void doSomething() {
    try {
      //Normally you would have code that doesn't explicitly appear 
      //to throw exceptions so it would be harder to see the problem.
      throw new RuntimeException();
    } finally {
      return;
    }
  }

From http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

James AN Stauffer
fonte
7
É desagradável, mas também é apenas uma consequência lógica de como finalmente funciona. O controle de fluxo try / catch / finalmente faz o que se pretende fazer, mas apenas dentro de certos limites. Da mesma forma, você deve ter cuidado para não causar uma exceção dentro de um bloco catch / finalmente, ou também descartará a exceção original. E se você fizer um System.exit () dentro do bloco try, o bloco final não será chamado. Se você quebrar o fluxo normal, você quebra o fluxo normal ...
Neil Coffey
Não use finalmente {return; } mas, finalmente, {código sem retorno}. Isso é lógico, pois, finalmente, também se destina a ser executado quando ocorrerem exceções, e o único significado possível de um retorno como manipulador de exceções deve ser ignorar a exceção e - de fato - retornar.
Extraneon
21
Isso parece mais uma "pegadinha" do que um recurso oculto, embora haja maneiras de usá-lo como um, usar esse método não seria uma boa idéia.
Davenpcj 06/06/09
O Eclipse emite um aviso se você fizer isso. Eu estou com o Eclipse. Se você deseja capturar uma exceção ... então pegue uma exceção.
helios 03/03
É o que você paga pelo código sujo que retorna do meio do método. Mas ainda é um bom exemplo.
precisa
141

Ninguém viu menção de instância de implementação, de forma que a verificação de nulo não é necessária.

Ao invés de:

if( null != aObject && aObject instanceof String )
{
    ...
}

Apenas use:

if( aObject instanceof String )
{
    ...
}
Cadet Pirx
fonte
9
É uma pena que esse seja um recurso tão pouco conhecido. Eu já vi muitos códigos semelhantes ao primeiro bloco de código.
22820 Peter Dolberg
4
Isso ocorre porque o Java tem um tipo nulo especial (oculto) que você não vê nem pode fazer referência.
Nick Hristov
O pior é verificar se há nulo antes de freeentrar ou deleteentrar em C / C ++. Um conceito tão fundamental.
Thomas Eding
134

Permitir métodos e construtores em enums me surpreendeu. Por exemplo:

enum Cats {
  FELIX(2), SHEEBA(3), RUFUS(7);

  private int mAge;
  Cats(int age) {
    mAge = age;
  }
  public int getAge() {
    return mAge;
   }
}

Você pode até ter um "corpo de classe específico constante" que permite que um valor de enum específico substitua métodos.

Mais documentação aqui .

Adrian Mouat
fonte
20
Recurso realmente incrível - cria enums OO e resolve muitos problemas de inicialização de uma maneira muito limpa.
Bill K
5
Enum como singleton? Enum com apenas um valor?
Georgy Bolyuba 13/11/2008
6
Georgy: Singleton é uma instância do objeto, não um objeto com um valor.
dshaw
20
@ Georgy: veja também o Item 3 no Java Efetivo de Joshua Bloch (2ª ed); "Embora essa abordagem ainda não tenha sido amplamente adotada, um tipo de enum de elemento único é a melhor maneira de implementar um singleton".
Jonik
3
Nitpick menor: mAgedeve ser final. Raramente existe uma razão para os campos não finais nas enumerações.
Joachim Sauer
121

Os parâmetros de tipo para métodos genéricos podem ser especificados explicitamente da seguinte maneira:

Collections.<String,Integer>emptyMap()
Kevin Wong
fonte
10
E por Deus é feio e confuso. E irrelevante para digitar segurança.
22420 Chris Broadfoot
8
Eu amo isto. Isso torna seu código um pouco mais explícito e, como tal, mais claro para os pobres que terão de mantê-lo em um ano ou dois.
extraneon
6
Isso é realmente muito útil em situações nas quais você declarou um método genérico estático, como public static <T> T foo(T t). Você pode fazer chamadas paraClass.<Type>foo(t);
Finbarr 13/05
Por alguma razão, isso não parece funcionar com métodos importados estaticamente. Gostaria de saber o porquê.
oksayt
Isso é especialmente útil ao usar ifs ternários com um retorno. Por exemplo return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList(). Também é útil para algumas invocações de métodos em que um simples Collections.emptyMap () causaria um erro de compilação.
Andreas Holstenson
112

Você pode usar enumerações para implementar uma interface.

public interface Room {
   public Room north();
   public Room south();
   public Room east();
   public Room west();
}

public enum Rooms implements Room {
   FIRST {
      public Room north() {
         return SECOND;
      }
   },
   SECOND {
      public Room south() {
         return FIRST;
      }
   }

   public Room north() { return null; }
   public Room south() { return null; }
   public Room east() { return null; }
   public Room west() { return null; }
}

EDIT: Anos depois ....

Eu uso esse recurso aqui

public enum AffinityStrategies implements AffinityStrategy {

https://github.com/peter-lawrey/Java-Thread-Affinity/blob/master/src/main/java/vanilla/java/affinity/AffinityStrategies.java

Usando uma interface, os desenvolvedores podem definir suas próprias estratégias. Usando um enummeio, posso definir uma coleção (de cinco) incorporada.

Peter Lawrey
fonte
27
Isso é loucura. (+1)
Cefalópode
12
@ Arian isso não é loucura. ISTO. É. JAVAAAAAAHHHH!
Slezica 13/10/11
1
WHAAAAAT não, eu estou com Adrian. Isto não é Java. Isso é loucura. Estou morrendo de vontade de usar isso.
slezica
104

A partir do Java 1.5, o Java agora possui uma sintaxe muito mais limpa para escrever funções de variável variável. Então, em vez de apenas passar uma matriz, agora você pode fazer o seguinte

public void foo(String... bars) {
   for (String bar: bars)
      System.out.println(bar);
}

barras é automaticamente convertida em matriz do tipo especificado. Não é uma vitória enorme, mas mesmo assim uma vitória.

Paul Wicks
fonte
23
A coisa importante sobre isso é quando chamar o método, você pode escrever: foo ( "primeiro", "segundo", "terceiro")
Steve Armstrong
9
para que o velho mundo olá possa ser reescrito; public static void main (String ... args) {System.out.println ("Olá, mundo!"); }
Karussell
@Karussell Talvez, mas ao que parece os argumentos são irrelevantes: p
Kelly Elton
93

Meu favorito: despejar todos os rastreamentos da pilha de threads para o padrão.

windows: CTRL- Breakna janela java cmd / console

unix: kill -3 PID

Chris Mazzola
fonte
15
Também pressione Ctrl- \ no Unix. Ou use o jstack do JDK.
Tom Hawtin - tackline 17/09/08
9
Obrigado, você acabou de me ensinar que meu teclado tem uma Breaktecla.
Amy B
2
No Windows, CTRL-BREAK funciona apenas se você tiver o processo em execução na janela atual do console. Você pode usar JAVA_HOME / bin / jstack.exe. Basta fornecer o ID do processo do Windows.
JavaScript é necessário
Eu pensei que era matar -SIGQUIT
Nick Hristov
@ Nick, sim, SIGQUIT é geralmente o sinal # 3.
31511 Chris Mazzola
89

Algumas pessoas postaram sobre inicializadores de instância, eis um bom uso para isso:

Map map = new HashMap() {{
    put("a key", "a value");
    put("another key", "another value");
}};

É uma maneira rápida de inicializar mapas se você estiver apenas fazendo algo rápido e simples.

Ou use-o para criar um protótipo de quadro de giro rápido:

JFrame frame = new JFrame();

JPanel panel = new JPanel(); 

panel.add( new JLabel("Hey there"){{ 
    setBackground(Color.black);
    setForeground( Color.white);
}});

panel.add( new JButton("Ok"){{
    addActionListener( new ActionListener(){
        public void actionPerformed( ActionEvent ae ){
            System.out.println("Button pushed");
        }
     });
 }});


 frame.add( panel );

Claro que pode ser abusado:

    JFrame frame = new JFrame(){{
         add( new JPanel(){{
               add( new JLabel("Hey there"){{ 
                    setBackground(Color.black);
                    setForeground( Color.white);
                }});

                add( new JButton("Ok"){{
                    addActionListener( new ActionListener(){
                        public void actionPerformed( ActionEvent ae ){
                            System.out.println("Button pushed");
                        }
                     });
                 }});
        }});
    }};
OscarRyz
fonte
De alguma forma, é um pouco como se a palavra-chave "with" (funcionalidade, na verdade) tivesse sido adicionada ao Java. Pode ser muito útil, recentemente resmunguei porque o init de matrizes não estava disponível para Coleções. Obrigado!
PhiLho
15
Há um efeito colateral de usar isso, no entanto. Objetos anônimos são criados, o que pode não ser bom sempre.
Amit
17
Embora, depois de analisar melhor, eu tenho que dizer que estou estranhamente atraído pelo ninho natural que isso fornece, mesmo a versão "Abusada".
Bill K
4
Sim - eu gosto bastante da versão 'abusada', acho que é realmente muito clara e legível, mas talvez seja apenas eu.
barryred
3
Concordo absolutamente, a hierarquia do código que reflete a hierarquia da GUI é uma grande melhoria em relação a uma sequência de chamadas de método.
Opsb #
88

Proxies dinâmicos (adicionados em 1.3) permitem definir um novo tipo em tempo de execução que esteja em conformidade com uma interface. É útil um número surpreendente de vezes.

jodonnell
fonte
10
Os proxies dinâmicos são um ótimo motivo para optar por escrever uma interface Foo e usá-la em qualquer lugar, com uma classe "FooImpl" padrão. Pode parecer feio a princípio ("Por que não ter apenas uma classe chamada Foo?"), Mas os benefícios em termos de flexibilidade futura e capacidade de simulação para testes de unidade são úteis. Embora existam maneiras de fazer isso também para não-interfaces, elas normalmente exigem coisas extras, como cblib.
21410 Darien
82

a inicialização final pode ser adiada.

Ele garante que mesmo com um fluxo complexo de valores de retorno lógicos sejam sempre definidos. É muito fácil perder um caso e retornar nulo por acidente. Não torna impossível retornar nulo, apenas óbvio que é de propósito:

public Object getElementAt(int index) {
    final Object element;
    if (index == 0) {
         element = "Result 1";
    } else if (index == 1) {
         element = "Result 2";
    } else {
         element = "Result 3";
    }
    return element;
}
Allain Lalonde
fonte
Isso é surpreendente. Pode-se dizer, "O valor de uma variável final pode ser definido uma vez", não importa onde o conjunto ocorra?
22430 David Koelle
29
Sim, mas com mais força: "O valor de uma variável final deve ser definido uma vez"
Allain Lalonde
6
+1 Concordo, essa é outra ferramenta valiosa para detectar erros em tempo de compilação e que os programadores parecem ter vergonha de usar por algum motivo. Observe que, a partir do Java 5 em diante, 'final' também tem implicações de segurança de encadeamento, sendo possível definir uma variável final durante o construtor.
30511 Neil Coffey
4
Embora para esse método específico, eu usaria apenas retornos múltiplos. De fato, na maioria dos casos em que isso é aplicável, eu provavelmente o refatoraria em um método separado e usaria vários retornos.
ripper234
Eu amo isto! Eu apaguei a palavra-chave final sempre porque pensei que ela falharia. obrigado!
KARASZI István
62

Eu acho que outro recurso "esquecido" do java é a própria JVM. É provavelmente a melhor VM disponível. E suporta muitas linguagens interessantes e úteis (Jython, JRuby, Scala, Groovy). Todos esses idiomas podem cooperar com facilidade e facilidade.

Se você cria um novo idioma (como no caso de scala), imediatamente tem todas as bibliotecas disponíveis e, portanto, seu idioma é "útil" desde o início.

Todos esses idiomas fazem uso das otimizações do HotSpot. A VM é muito bem monitorada e depurável.

Mo.
fonte
18
Não. Na verdade, não é uma VM muito boa. Foi projetado exclusivamente para executar o JAVA. Linguagens dinâmicas e funcionais sem tipo não funcionam bem com isso. De você deseja usar uma VM, você deve usar .NET / Mono. Que foi projetado para trabalho com a linguagem CADA ...
Hades32
14
Na verdade, a JVM foi projetada exclusivamente para executar Java Bytecodes. Você pode compilar as linguagens mais modernas no Java Bytecode. As únicas coisas que faltam ao Java Bytecode são suporte dinâmico à linguagem, ponteiros e suporte à recursão final.
mcjabberz
12
@ Hades32: na verdade, a VM do .NET é muito semelhante à JVM. Recentemente, ele recebeu suporte para linguagens dinâmicas recentemente (com o DLR) e o Java 7 também está prestes a obter esse suporte. E a clássica "CADA linguagem" do .NET (C #, Visual Basic.NET, ...) tem praticamente exatamente o mesmo conjunto de recursos.
Joachim Sauer
13
A JVM não suporta genéricos, enquanto a VM do .NET suporta. A JVM não é nem de longe a melhor.
Blindy
3
Para não desconsiderar as reclamações sobre recursos de idiomas específicos não suportados diretamente pela JVM ... mas eu costumo pensar que estabilidade, consistência entre plataformas e bom desempenho estão muito acima das razões pelas quais a JVM obtém pontos extras. Estou trabalhando com Java do lado do servidor há muitos anos em várias plataformas (incluindo AS / 400) e consegui esquecê-lo completamente - os bugs estão quase sempre no código que eu posso corrigir e simplesmente não trava.
precisa saber é o seguinte
58

Você pode definir uma subclasse anônima e chamar diretamente um método, mesmo que não implemente interfaces.

new Object() {
  void foo(String s) {
    System.out.println(s);
  }
}.foo("Hello");
Ron
fonte
@Vuntic - Permite definir uma classe simples dentro do contexto necessário.
ChaosPandion
1
@ Caos, mas por quê? Tem um exemplo real de onde é útil?
Thorbjørn Ravn Andersen
10
@Wouter - Nesse caso, o método que é chamado no objeto anônimo ( start()) não está realmente definido na subclasse ...
Axel
Na verdade, esse é um recurso muito útil se você estender uma classe base que faz algumas configurações necessárias, chamar o método que você escreve e desmontar. Comece bem chamando um método na classe base (que provavelmente não daria o mesmo nome). Há um exemplo de uso (não definição) aqui
AmigoNico
56

O método asList in java.util.Arrayspermite uma boa combinação de varargs, métodos genéricos e caixa automática:

List<Integer> ints = Arrays.asList(1,2,3);
Bruno De Fraine
fonte
15
Você quer quebrar a lista retornada com um construtor Lista tamanho de outra forma ints será fixa (uma vez que é apoiado pela matriz)
KitsuneYMG
2
O Arrays.asListtem o recurso incomum que você pode set()elementos, mas não add()ou remove(). Por isso, costumo envolvê-lo em um new ArrayList(...)ou em um Collections.unmodifiableList(...), dependendo se quero ou não a lista modificável.
Christian Semrau
53

Usando esta palavra - chave para acessar campos / métodos de conter classe de uma classe interna. No exemplo abaixo, bastante artificial, queremos usar o campo sortAscending da classe de contêiner da classe interna anônima. Usar ContainerClass.this.sortAscending em vez de this.sortAscending faz o truque.

import java.util.Comparator;

public class ContainerClass {
boolean sortAscending;
public Comparator createComparator(final boolean sortAscending){
    Comparator comparator = new Comparator<Integer>() {

        public int compare(Integer o1, Integer o2) {
            if (sortAscending || ContainerClass.this.sortAscending) {
                return o1 - o2;
            } else {
                return o2 - o1;
            }
        }

    };
    return comparator;
}
}
Tahir Akhtar
fonte
4
Isso é necessário apenas se você tiver sombreado o nome (no seu caso, com o nome do parâmetro do método). Se você tivesse chamado o argumento de outra coisa, poderia acessar diretamente a variável de membro sortAscending da classe Container sem usar 'this'.
sk.
7
Ainda é útil ter uma referência à classe anexa, por exemplo. se você precisar passá-lo para algum método ou construtor.
#
Geralmente usado no desenvolvimento de layout do Android, para obter o Contexto, por exemplo, do ouvinte de um botão, com MyActivity.this.
Espinchi 29/04
52

Não é realmente um recurso, mas um truque divertido que descobri recentemente em algumas páginas da Web:

class Example
{
  public static void main(String[] args)
  {
    System.out.println("Hello World!");
    http://Phi.Lho.free.fr

    System.exit(0);
  }
}

é um programa Java válido (embora gere um aviso). Se você não vê o porquê, veja a resposta de Gregory! ;-) Bem, o destaque da sintaxe aqui também dá uma dica!

PhiLho
fonte
15
puro, uma etiqueta com um comentário :)
Thorbjørn Ravn Andersen
46

Isso não é exatamente "recursos ocultos" e não é muito útil, mas pode ser extremamente interessante em alguns casos:
Classe sun.misc.Unsafe - permitirá implementar o gerenciamento direto de memória em Java (você pode até escrever código Java auto-modificável com isso se você tentar muito):

public class UnsafeUtil {

    public static Unsafe unsafe;
    private static long fieldOffset;
    private static UnsafeUtil instance = new UnsafeUtil();

    private Object obj;

    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);

            unsafe = (Unsafe)f.get(null);
            fieldOffset = unsafe.objectFieldOffset(UnsafeUtil.class.getDeclaredField("obj"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    };
}
Das
fonte
20
isso é um sol. * API que realmente não faz parte da linguagem Java em si
DW.
Existem vários outros métodos curiosos no Unsafe, como criar um objeto sem chamar um construtor, métodos de estilo malloc / realloc / free.
Peter Lawrey
Eu amo especialmente os getters e setters primitivos em locais de memória, como putDouble (endereço longo, duplo d).
Daniel
42

Ao trabalhar no Swing, eu gosto do oculto Ctrl- Shift-F1 recurso.

Despeja a árvore de componentes da janela atual.
(Supondo que você não tenha vinculado essa tecla a outra coisa.)

Devon_C_Miller
fonte
1
Muito provavelmente o seu gerenciador de janelas tem algo vinculado a essa chave. O Gnome não se liga a ele, então estou assumindo que você esteja executando o KDE, que o vincula a 'mudar para a área de trabalho 13'. Você pode alterá-lo, indo ao painel de controle, Regional, atalhos de teclado e remover o mapeamento para Shift-Ctrl-F1
Devon_C_Miller
40

Todo arquivo de classe começa com o valor hexadecimal 0xCAFEBABE para identificá-lo como bytecode válido da JVM.

( Explicação )

Dolph
fonte
38

Meu voto vai para java.util.concurrent, com suas coleções simultâneas e executores flexíveis, permitindo, entre outros, conjuntos de threads, tarefas agendadas e tarefas coordenadas. O DelayQueue é meu favorito pessoal, onde os elementos são disponibilizados após um atraso especificado.

java.util.Timer e TimerTask podem ser colocados com segurança em repouso.

Além disso, não exatamente oculto, mas em um pacote diferente das outras classes relacionadas à data e hora. java.util.concurrent.TimeUnit é útil ao converter entre nanossegundos, microssegundos, milissegundos e segundos.

Ele lê muito melhor que o usual someValue * 1000 ou someValue / 1000.

stili
fonte
Descoberto recentemente CountDownLatche CyclicBarrier- tão útil!
Raphael
37

Palavra- chave de afirmação no nível do idioma .

Mark Cidade
fonte
19
O problema com a afirmação é que ele precisa ser ativado durante o tempo de execução.
Extraneon
10
Mas se estiver desativado, é como se não estivesse lá. Você pode adicionar quantas declarações quiser no seu código e não terá nenhuma penalidade de desempenho se elas estiverem desativadas.
Ravi Wallau
5
Acredito que isso é bom em afirmar: pode ser desativado sem penalidade.
andref 11/07/10
O problema é que se você acidentalmente implementado um efeito colateral em uma declaração, você tem que ligar afirmação de ur programa de trabalho ...
Chii
Para detectar se as declarações estão ativadas, você pode usar {boolean assertsOn = false; assert assertsOn = true; if (assertsOn) {/ * verificação complexa * /}}. Isso também permite registrar ou lançar uma exceção se o estado de afirmação não for o esperado.
fernacolo
37

Não é realmente parte da linguagem Java, mas o desmontador javap que acompanha o JDK da Sun não é amplamente conhecido ou usado.

Binil Thomas
fonte
36

A adição da construção de loop for-each em 1.5. Eu <3.

// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
  System.out.println(foo.toString());
}

E pode ser usado em instâncias aninhadas:

for (Suit suit : suits)
  for (Rank rank : ranks)
    sortedDeck.add(new Card(suit, rank));

A construção for-each também é aplicável a matrizes, onde oculta a variável index em vez do iterador. O método a seguir retorna a soma dos valores em uma matriz int:

// Returns the sum of the elements of a
int sum(int[] a) {
  int result = 0;
  for (int i : a)
    result += i;
  return result;
}

Link para a documentação da Sun

18Coelho
fonte
30
Eu acho que usar iaqui é super confuso, pois a maioria das pessoas espera que eu seja um índice e não o elemento da matriz.
Cdmckay
Então ... int sum (matriz int []) {int resultado = 0; for (elemento int: matriz) {resultado + = elemento; } retornar resultado; }
Drew
28
A única coisa que me deixa maluco com isso é que parece realmente muito fácil criar uma palavra-chave para acessar o valor da contagem de loop, mas você não pode. Se eu quiser fazer um loop sobre duas matrizes e fazer alterações em um segundo com base nos valores da primeira, sou forçado a usar a sintaxe antiga porque não tenho deslocamento para a segunda matriz.
Jherico
6
É uma pena que também não funcione com enumerações, como as usadas no JNDI. Está de volta aos iteradores lá.
Extraneon
3
@extraneon: dê uma olhada em Collections.list (Enumeração <T> e). Isso deve ajudar a enumerar iterações no loop foreach.
Werner Lehmann
34

eu descobri pessoalmente java.lang.Voidmuito tarde - melhora a legibilidade do código em conjunto com os genéricos, por exemploCallable<Void>

Rahel Lüthy
fonte
2
não exatamente. em algum momento, você precisa ser específico: Executors.newSingleThreadExecutor (). submit (new Callable <Void> () {..}) - você não pode instanciar um novo Callable <?> (), precisa especificar um tipo explícito - portanto, é uma alternativa ao Callable <Object>.
Rahel Lüthy
4
Vazio é mais específico que Objeto, pois Vazio só pode ser nulo, Objeto pode ser qualquer coisa.
Peter Lawrey