Recursos ocultos do Java


295

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


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.


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.


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

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.


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? :)


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.


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


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 )
{
    ...
}

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 .


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()

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.


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.


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


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

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.


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

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.


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

@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);

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

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!


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

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.)


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 )


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.


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

37

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


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.


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


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>


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