Funzionalità nascoste di Java


295

Dopo aver letto Hidden Features of C #, mi chiedevo, quali sono alcune delle funzionalità nascoste di Java?


17
Si noti che non è sempre un'ottima idea utilizzare queste funzionalità nascoste; spesso sono sorprendenti e confusi per gli altri che leggono il tuo codice.
Kevin Bourrillion,

1
Tu (/ qualcuno) dovresti probabilmente riassumere ordinatamente le risposte nel corpo della domanda come la domanda C #.
Ripper234,

Risposte:


432

Inizializzazione doppia parentesi graffa mi ha sorpreso alcuni mesi fa quando l'ho scoperto per la prima volta, non ne avevo mai sentito parlare prima.

ThreadLocals è in genere così ampiamente noto come un modo per memorizzare lo stato per thread.

Dato che JDK 1.5 Java ha implementato strumenti di concorrenza estremamente ben implementati e robusti oltre ai semplici blocchi, vive in java.util.concurrent e un esempio particolarmente interessante è il subpackage java.util.concurrent.atomic che contiene primitive thread-safe che implementano il confronto -e scambiare operazioni e può mappare alle versioni supportate dall'hardware nativo di queste operazioni.


40
Inizializzazione a doppia parentesi ... strano ... Sarei diffidente nell'adottare quel particolare idioma troppo ampiamente, dato che in realtà crea una sottoclasse anonima dell'oggetto, che potrebbe causare problemi di uguaglianza / hashcode. java.util.concurrent è un pacchetto davvero eccezionale.
MB.

6
Ho insegnato a Java, e questa è la prima volta che mi imbatto in questa sintassi ... che dimostra che non smetti mai di imparare = Cool
Yuval

49
Si noti che se si mantiene un riferimento a una raccolta inizializzata con questo linguaggio "doppio controvento" (o se lo chiamiamo con il suo vero nome - classe anonima con blocco di inizializzatore), si tiene implicitamente un riferimento all'oggetto esterno che può causare cattiva memoria perdite. Consiglierei di evitarlo del tutto.
ddimitrov,

51
"Inizializzazione a doppia parentesi" è un nome molto eufemistico per la creazione di una classe interna anonima, che analizza ciò che sta realmente accadendo e lo fa sembrare come se le classi interne fossero destinate a essere utilizzate in questo modo. Questo è uno schema che preferirei rimanere nascosto.
Erickson,

11
Quasi, non si tratta in realtà di un blocco statico ma di un "blocco di inizializzazione" che è diverso poiché viene eseguito in un altro momento (vedere il link che ho inserito nella risposta per maggiori dettagli)
Boris Terzic,

279

Unione unita nella varianza dei parametri di tipo:

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

Ad esempio, se vuoi prendere un parametro che è sia Comparable che una Collection:

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

Questo metodo inventato restituisce true se le due raccolte indicate sono uguali o se una di esse contiene l'elemento dato, altrimenti false. Il punto da notare è che è possibile richiamare metodi di Comparable e Collection sugli argomenti b1 e b2.


Il mio uso preferito per questo è quando hai bisogno di un metodo che accetti una conseguenza appendibile.
Neil Coffey,

5
È possibile avere un "OR" lì invece del &?
mainstringargs

9
@Grasper: No, OR (unione disgiunta) non viene fornito in quel contesto. Puoi invece utilizzare un tipo di dati unione disgiunto come <A, B>. Questo tipo è il doppio di un tipo Pair <A, B>. Guarda la libreria Java funzionale o le librerie core di Scala per un esempio di tale tipo di dati.
Apocalisp,

5
Dovresti dire che DEVI estendere solo una classe e diverse interfacce -> classe pubblica Baz <T estende Clazz & Interface1 & InterfaceI ... e non classe Baz <T estende Clazz1 & ClazzI>
JohnJohnGa

220

Sono stato sorpreso dagli inizializzatori dell'istanza l'altro giorno. Stavo eliminando alcuni metodi piegati a codice e ho finito per creare inizializzatori a più istanze:

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

L'esecuzione del mainmetodo visualizzerà:

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

Immagino che questi sarebbero utili se avessi più costruttori e avessi bisogno di un codice comune

Forniscono anche zucchero sintattico per inizializzare le tue classi:

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
Il vantaggio di questo rispetto a un metodo esplicito che deve essere chiamato è che se qualcuno aggiunge un costruttore in un secondo momento non ha bisogno di ricordare di chiamare init (); quello sarà fatto automaticamente. Questo può prevenire errori da futuri programmatori.
Mr. Shiny e New

40
Inoltre, a differenza di un metodo init (), può inizializzare i campi finali.
Darron,

2
E se estendi la lezione e crei un'istanza di vari bambini? Si comporterà comunque allo stesso modo?
Kezzer,

12
Le persone spesso non certificano (ad esempio stackoverflow.com/questions/281100/281127#281127 ) e mettono in dubbio soprattutto i loro meriti tecnici. Ma se più programmatori qui avessero studiato per il loro SCJP, questo non sarebbe considerato una "caratteristica nascosta" da così tanti. ;-)
Jonik,

12
Scommetto che anche il libro "Java in 24 ore" ha questa "caratteristica ovvia". leggi altri ragazzi
:)

201

JDK 1.6_07 + contiene un'app chiamata VisualVM (bin / jvisualvm.exe) che è una bella GUI su molti degli strumenti. Sembra più completo di JConsole.


E ha un plugin (è un oggetto netbeans) che gli consente di utilizzare i plugin Jconsole. Piuttosto bella.
Thorbjørn Ravn Andersen,

VisualVM è la cosa migliore dopo il pane a fette, davvero! Peccato che non abbia tutte le funzionalità quando si esegue contro JDK 1.5
sandos,

Trovo VisualVM lento o inutilizzabile in alcune circostanze. YourKit commerciale non ha questo problema, ma purtroppo non è gratuito.
Roalt,

Le versioni più recenti di Visual VM, da JDK 1.6.0_22 e successive, sono molto migliorate. Scommetto che JDK1.7 ne ha una versione ancora migliore.
Djangofan,


156

Per la maggior parte delle persone che intervisto per le posizioni degli sviluppatori Java, i blocchi etichettati sono molto sorprendenti. Ecco un esempio:

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

Chi ha detto che gotoJava è solo una parola chiave? :)


2
Bene, preferirei avere un'opzione per farlo in diversi modi. Ad esempio, ho visto persone usare System.exit (1); nel codice Servlet ed EJB, ma ciò non significa che dovremmo rimuovere System.exit (); dal JDK, giusto?
Georgy Bolyuba,

31
In alcune circostanze, all'interno di un costrutto di ciclo nidificato, può essere utile continuare alla successiva iterazione di un ciclo esterno. Questo sarebbe un uso ragionevole di questa funzione.
alasdairg,

75
Ciò che è particolarmente sconosciuto a molti programmatori (e probabilmente anche allo stesso modo) è che puoi effettivamente etichettare ed uscire da QUALSIASI vecchio blocco. Non deve essere un loop: puoi semplicemente definire un blocco arbitrario, dargli un'etichetta e usare break con esso.
Neil Coffey,

27
Non è affatto un goto, può solo tornare a un'iterazione precedente (cioè: non puoi saltare in avanti). Questo è lo stesso meccanismo che si verifica quando un'iterazione restituisce false. Dire che java ha goto è come dire qualsiasi linguaggio il cui compilatore produce un'istruzione JUMP ha un'istruzione goto.
Zombi,

4
Quindi intervista sulla base di curiosità Java piuttosto che sull'attitudine a risolvere i problemi e pensare attraverso i progetti. Mi assicurerò di non intervistare mai la tua azienda. :)
Javid Jamae,

144

Che ne dite di tipi di ritorno covarianti che sono stati in atto dal JDK 1.5? È scarsamente pubblicizzato, in quanto è un'aggiunta nonxy, ma a quanto ho capito, è assolutamente necessario per far funzionare i generici.

In sostanza, il compilatore ora consente a una sottoclasse di restringere il tipo restituito di un metodo sostituito per essere una sottoclasse del tipo restituito del metodo originale. Quindi questo è permesso:

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

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

È possibile chiamare il valuesmetodo della sottoclasse e ottenere un thread ordinato sicuro Setdi Strings senza dover eseguire il down cast del ConcurrentSkipListSet.


Potete fornire un esempio di utilizzo?
Allain Lalonde,

24
Lo uso molto. clone () è un ottimo esempio. Dovrebbe restituire Object, il che significa che dovresti dire ad esempio (List) list.clone (). Tuttavia, se dichiari come Elenco clone () {...}, il cast non è necessario.
Jason Cohen,

142

Il trasferimento del controllo in un blocco finalmente elimina qualsiasi eccezione. Il seguente codice non genera RuntimeException - è perso.

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

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


7
È brutto, ma è anche una conseguenza logica di come funziona finalmente. Il controllo del flusso try / catch / finally fa quello che deve fare, ma solo entro certi limiti. Allo stesso modo, devi stare attento a non provocare un'eccezione all'interno di un blocco catch / finally, altrimenti eliminerai anche l'eccezione originale. E se si esegue un System.exit () all'interno del blocco try, il blocco finally non verrà chiamato. Se interrompi il flusso normale, interrompi il flusso normale ...
Neil Coffey,

Non usare finalmente {return; } ma alla fine {codice senza ritorno}. Questo è logico, poiché alla fine è previsto che venga eseguito anche quando si sono verificate eccezioni, e l'unico significato possibile di un ritorno come gestore di eccezioni deve essere ignorare l'eccezione e, in effetti, restituire.
extraneon,

21
Questo sembra più un "gotcha" che una funzione nascosta, anche se ci sono modi in cui potrebbe essere usato come uno, usando questo metodo non sarebbe una buona idea.
davenpcj

Eclipse emette un avviso se lo fai. Sono con Eclipse. Se vuoi prendere un'eccezione ... allora prendi un'eccezione.
helios

Questo è ciò che si paga per il codice sporco che ritorna dalla metà del metodo. Ma comunque un bell'esempio.
Rostislav Matl,

141

Non ho mai visto nessuno menzionare l'istanza di essere implementata in modo tale da non essere necessario controllare null.

Invece di:

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

basta usare:

if( aObject instanceof String )
{
    ...
}

9
È un peccato che questa sia una caratteristica così poco conosciuta. Ho visto un sacco di codice simile al primo blocco di codice.
Peter Dolberg,

4
Questo perché Java ha un tipo nullo (nascosto) speciale che non vedi, né a cui puoi fare riferimento.
Nick Hristov,

Quel che è peggio è il controllo di null prima di freeinserire o deleteinserire in C / C ++. Un concetto così fondamentale.
Thomas Eding,

134

Consentire metodi e costruttori negli enum mi ha sorpreso. Per esempio:

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

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

Puoi anche avere un "corpo di classe specifico costante" che consente a un valore enum specifico di sovrascrivere i metodi.

Più documentazione qui .


20
Funzionalità davvero fantastica in realtà - rende eno OO e risolve molti problemi di inizializzazione in un modo molto pulito.
Bill K,

5
Enum come singleton? Enum con un solo valore?
Georgy Bolyuba,

6
Georgy: Singleton è un'istanza dell'oggetto, non un oggetto con un valore.
dshaw,

20
@Georgy: vedi anche l'articolo 3 in Effective Java di Joshua Bloch (2a edizione); "Mentre questo approccio deve ancora essere ampiamente adottato, un tipo enum a elemento singolo è il modo migliore per implementare un singleton."
Jonik,

3
Minore nitpick: mAgedovrebbe essere definitivo. Raramente c'è un motivo per feld non definitivi negli enum.
Joachim Sauer,

121

I parametri di tipo per metodi generici possono essere specificati in modo esplicito in questo modo:

Collections.<String,Integer>emptyMap()

10
E per dio è brutto e confuso. E irrilevante per digitare sicurezza.
Chris Broadfoot,

8
Amo questo. Rende il tuo codice un po 'più esplicito e come tale più chiaro per la povera zolla che dovrà mantenerlo tra un anno o due.
extraneon,

6
Questo è in realtà molto utile in situazioni in cui è stato dichiarato un metodo generico statico come public static <T> T foo(T t). È quindi possibile effettuare chiamate aClass.<Type>foo(t);
Finbarr

Per qualche motivo questo non sembra funzionare con metodi importati staticamente .. Mi chiedo perché.
Oksayt,

Ciò è particolarmente utile quando si usano if ternari con un ritorno. Per esempio return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList(). È utile anche per alcune invocazioni di metodi in cui un semplice Collections.emptyMap () darebbe un errore di compilazione.
Andreas Holstenson,

112

Puoi usare enum per implementare un'interfaccia.

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: anni dopo ....

Uso questa funzione qui

public enum AffinityStrategies implements AffinityStrategy {

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

Utilizzando un'interfaccia, gli sviluppatori possono definire le proprie strategie. Usando un enummezzo posso definire una raccolta (di cinque) incorporata in quelle.


27
Questa è una follia. (+1)
Cefalopode

12
@Arian non è una follia. QUESTO. È. JAVAAAAAAHHHH!
slezica,

1
WHAAAAAT no, sono con Adrian. Questo non è Java. Questa è una follia. Sto morendo per usare questo.
slezica,

104

A partire da Java 1.5, Java ora ha una sintassi molto più pulita per la scrittura di funzioni di arity variabile. Quindi, invece di passare semplicemente un array, ora puoi fare quanto segue

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

le barre vengono convertite automaticamente in array del tipo specificato. Non una vittoria enorme, ma comunque una vittoria.


23
L'importante è che quando chiami il metodo, puoi scrivere: foo ("primo", "secondo", "terzo")
Steve Armstrong

9
così il vecchio mondo ciao può essere riscritto; public static void main (String ... args) {System.out.println ("Ciao mondo!"); }
Karussell,

@Karussell Forse, ma sembrerebbe che gli argomenti siano irrilevanti: p
Kelly Elton,

93

Il mio preferito: eseguire il dump di tutte le tracce dello stack di thread allo standard out.

windows: CTRL- Breaknella finestra java cmd / console

unix: kill -3 PID


15
Anche ctrl- \ in Unix. Oppure usa jstack dal JDK.
Tom Hawtin - tackline il

9
Grazie, mi hai appena insegnato che la mia tastiera ha una Breakchiave.
Amy B,

2
Su Windows, CTRL-BREAK funziona solo se il processo è in esecuzione nella finestra della console corrente. È possibile utilizzare JAVA_HOME / bin / jstack.exe invece. Forniscilo con l'ID del processo di Windows.
Javid Jamae,

Ho pensato che fosse uccisione -SIGQUIT
Nick Hristov

@Nick, sì SIGQUIT è di solito il segnale # 3.
Chris Mazzola,

89

Un paio di persone hanno pubblicato degli inizializzatori di istanze, ecco un buon uso per questo:

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

È un modo rapido per inizializzare le mappe se stai semplicemente facendo qualcosa di semplice e veloce.

O utilizzandolo per creare un prototipo di telaio a battente rapido:

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

Naturalmente può essere abusato:

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

In qualche modo, è un po 'come se la parola chiave "with" (funzionalità, in realtà) fosse stata aggiunta a Java. Può essere molto utile, recentemente ho grugnito perché init of array non era disponibile per le Collezioni. Grazie!
PhiLho,

15
Tuttavia, c'è un effetto collaterale dell'utilizzo di questo. Vengono creati oggetti anonimi, il che potrebbe non andare sempre bene.
Amit

17
Anche se dopo averlo guardato di più, devo dire che sono stranamente attratto dalla nidificazione naturale che questo fornisce, anche la versione "Abusata".
Bill K,

4
Sì - Mi piace molto la versione "abusata", penso che sia davvero molto chiara e leggibile, ma forse sono solo io.
Barryred

3
Assolutamente d'accordo, la gerarchia del codice che riflette la gerarchia della GUI è un enorme miglioramento rispetto a una sequenza di chiamate di metodo.
opsb,

88

I proxy dinamici (aggiunti in 1.3) consentono di definire un nuovo tipo in fase di esecuzione conforme a un'interfaccia. È utile un numero sorprendente di volte.


10
I proxy dinamici sono un'ottima ragione per scegliere di scrivere un'interfaccia Foo e usarla ovunque, con una classe "FooImpl" predefinita. All'inizio può sembrare brutto ("Perché non avere solo una classe chiamata Foo?") Ma i vantaggi in termini di flessibilità futura e finta capacità per i test unitari sono utili. Mentre ci sono modi per farlo anche per le non-interfacce, in genere richiedono cose extra come cblib.
Darien,

82

l'inizializzazione finale può essere posticipata.

Si assicura che anche con un flusso complesso di valori di ritorno logici siano sempre impostati. È troppo facile perdere un caso e restituire null per caso. Non rende impossibile il ritorno null, solo ovvio che è apposta:

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

È sorprendente. Si può abbastanza dire "Il valore di una variabile finale può essere impostato una volta", indipendentemente da dove si trova l'insieme?
David Koelle,

29
Sì, ma più fortemente: "Il valore di una variabile finale deve essere impostato una volta"
Allain Lalonde

6
+1 Accetto, questo è un altro strumento prezioso per individuare gli errori in fase di compilazione e uno che i programmatori sembrano timidi da usare per qualche motivo. Si noti che poiché da Java 5 in poi, 'final' ha anche implicazioni per la sicurezza dei thread, essere in grado di impostare una variabile finale durante il costruttore è inestimabile.
Neil Coffey,

4
Sebbene per questo metodo specifico, utilizzerei solo più resi. In effetti, nella maggior parte dei casi in cui ciò è applicabile, probabilmente lo trasformerei in un metodo separato e utilizzerei rendimenti multipli.
ripper234

Amo questo! Ho eliminato la parola chiave finale sempre perché pensavo che avrebbe fallito. Grazie!
KARASZI István,

62

Penso che un'altra caratteristica "trascurata" di Java sia la stessa JVM. È probabilmente la migliore VM disponibile. E supporta molte lingue interessanti e utili (Jython, JRuby, Scala, Groovy). Tutte queste lingue possono cooperare facilmente e senza soluzione di continuità.

Se si progetta una nuova lingua (come nello scala-case), si dispone immediatamente di tutte le librerie esistenti e la lingua è quindi "utile" sin dall'inizio.

Tutte queste lingue utilizzano le ottimizzazioni di HotSpot. La VM è molto ben monitorata e debuggabile.


18
No. In realtà non è una VM molto buona. È stato progettato esclusivamente per eseguire JAVA. I linguaggi dinamici e funzionali senza nome non funzionano bene con esso. Di voi volete usare una VM dovreste usare .NET / Mono. È stato progettato per funzionare con OGNI linguaggio ...
Hades32,

14
In realtà il JVM è progettato esclusivamente per eseguire Java Bytecodes. È possibile compilare le lingue più moderne in Bytecode Java. Le uniche cose che mancano in Java Bytecode sono il supporto dinamico del linguaggio, i puntatori e il supporto della ricorsione della coda.
Mcjabberz,

12
@ Hades32: attualmente la VM .NET è abbastanza simile alla JVM. Recentemente ha ottenuto il supporto per linguaggi dinamici (con il DLR) e anche Java 7 sta per ottenere quel supporto. E il classico "OGNI linguaggio" di .NET (C #, Visual Basic.NET, ...) hanno praticamente esattamente lo stesso set di funzionalità.
Joachim Sauer

13
JVM non supporta generici, mentre .NET VM lo fa. JVM non è affatto il migliore.
Blindy,

3
Non per scartare i reclami su funzioni linguistiche specifiche non direttamente supportate da JVM ... ma tendo a pensare che stabilità, coerenza multipiattaforma e buone prestazioni siano di gran lunga superiori ai motivi per cui la JVM ottiene punti extra. Lavoro con Java lato server ormai da molti anni su molte piattaforme (incluso AS / 400) e sono stato in grado di dimenticarmene del tutto - i bug sono praticamente sempre nel codice che posso sistemare, ed è semplicemente non va in crash.
Rob Whelan,

58

È possibile definire una sottoclasse anonima e chiamare direttamente un metodo su di essa anche se non implementa interfacce.

new Object() {
  void foo(String s) {
    System.out.println(s);
  }
}.foo("Hello");

@Vuntic: ti consente di definire una classe semplice nel contesto in cui è necessaria.
ChaosPandion,

1
@ Caos, ma perché? Hai un esempio reale in cui è utile?
Thorbjørn Ravn Andersen,

10
@Wouter - In tal caso, il metodo chiamato sull'oggetto anonimo ( start()) non è in realtà definito nella sottoclasse ...
Axel

In realtà, questa è una funzione molto utile se estendi una classe di base che esegue alcune impostazioni necessarie, chiama il metodo che scrivi e quindi esegue lo smontaggio. Dai il via alla cosa chiamando un metodo nella classe base (che probabilmente non darei lo stesso nome). C'è un esempio di utilizzo (non definizione) qui
AmigoNico

56

Il metodo asList in java.util.Arraysconsente una buona combinazione di vararg, metodi generici e autoboxing:

List<Integer> ints = Arrays.asList(1,2,3);

15
vuoi racchiudere la lista restituita con un costruttore List altrimenti gli ints avranno dimensioni fisse (dato che è supportato dall'array)
KitsuneYMG

2
L' Arrays.asListha la particolarità che si può set()elementi, ma non add()o remove(). Quindi di solito lo avvolgo in a new ArrayList(...)o in a Collections.unmodifiableList(...), a seconda che si desideri modificare l'elenco o meno.
Christian Semrau,

53

Utilizzo di questa parola chiave per accedere a campi / metodi per contenere la classe da una classe interna. Nell'esempio che segue, piuttosto ingegnoso, vogliamo usare il campo sortAscending della classe container dalla classe interna anonima. L'uso di ContainerClass.this.sortAscending invece di this.sortAscending fa il trucco.

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
Questo è necessario solo se hai ombreggiato il nome (nel tuo caso, con il nome del parametro del metodo). Se avessi chiamato l'argomento qualcos'altro, allora potresti accedere direttamente alla variabile membro sortAscending della classe Container senza usare 'this'.
sk.

7
È ancora utile avere un riferimento alla classe che lo racchiude, ad es. se è necessario passarlo a qualche metodo o costruttore.
PhiLho,

Spesso utilizzato nello sviluppo di layout Android, al fine di ottenere il contesto, per esempio, dall'ascoltatore di un pulsante, con MyActivity.this.
espinchi,

52

Non proprio una funzionalità, ma un trucco divertente che ho scoperto di recente in alcune pagine Web:

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

    System.exit(0);
  }
}

è un programma Java valido (anche se genera un avviso). Se non vedi il perché, vedi la risposta di Gregory! ;-) Bene, l'evidenziazione della sintassi qui dà anche un suggerimento!


15
pulito, un'etichetta con un commento :)
Thorbjørn Ravn Andersen,

46

Non si tratta esattamente di "funzioni nascoste" e non molto utili, ma in alcuni casi può essere estremamente interessante:
Class sun.misc.Unsafe - ti permetterà di implementare la gestione diretta della memoria in Java (puoi persino scrivere codice Java auto-modificante con questo se ci provi molto):

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
quello è un sole. * API che in realtà non fa parte del linguaggio Java di per sé
DW.

Ci sono molti altri metodi curiosi su Unsafe come la creazione di un oggetto senza chiamare un costruttore, metodi di stile malloc / realloc / free.
Peter Lawrey,

Adoro soprattutto i getter e i setter primitivi nelle posizioni di memoria, come putDouble (long address, double d).
Daniel,

42

Quando lavoro in Swing mi piace il nascosto Ctrl- Shift-F1 funzione.

Scarica l'albero dei componenti della finestra corrente.
(Supponendo di non aver vincolato la sequenza di tasti a qualcos'altro.)


1
Molto probabilmente il tuo gestore di finestre ha qualcosa legato a quella chiave. Gnome non si lega ad esso, quindi presumo che tu stia eseguendo KDE che lo lega a "passare al desktop 13". Puoi cambiarlo andando su Pannello di controllo, Regionale, Tasti di scelta rapida e rimuovendo la mappatura per Shift-Ctrl-F1
Devon_C_Miller

40

Ogni file di classe inizia con il valore esadecimale 0xCAFEBABE per identificarlo come bytecode JVM valido.

( Spiegazione )


38

Il mio voto va a java.util.concurrent con le sue raccolte simultanee e gli esecutori flessibili che consentono tra l'altro pool di thread, attività pianificate e attività coordinate. Il DelayQueue è il mio preferito personale, in cui gli elementi vengono resi disponibili dopo un determinato ritardo.

java.util.Timer e TimerTask possono essere tranquillamente messi a riposo.

Inoltre, non esattamente nascosto ma in un pacchetto diverso dalle altre classi relative a data e ora. java.util.concurrent.TimeUnit è utile per la conversione tra nanosecondi, microsecondi, millisecondi e secondi.

Legge molto meglio del solito someValue * 1000 o someValue / 1000.


Recentemente scoperto CountDownLatche CyclicBarrier- così utile!
Raffaello

37

Parola chiave di asserzione a livello di lingua .


19
Il problema con assert è che deve essere acceso durante il runtime.
extraneon,

10
Ma se è disabilitato è come se non ci fosse. Puoi aggiungere tutte le affermazioni che desideri nel tuo codice e non avrai alcuna penalità di prestazione se sono disabilitate.
Ravi Wallau,

5
Credo che sia una buona cosa affermare: può essere disattivato senza penalità.
andref,

il problema è che se hai accidentalmente implementato un effetto collaterale in un'asserzione, devi attivare l'asserzione affinché il tuo programma funzioni ...
Chii,

Per rilevare se gli assert sono attivi, puoi usare {boolean assertsOn = false; assert assertsOn = true; if (assertsOn) {/ * verifica complessa * /}}. Ciò consente anche di registrare o generare un'eccezione se lo stato di asserzione non è previsto.
fernacolo,

37

In realtà non fa parte del linguaggio Java, ma il disassemblatore javap fornito con il JDK di Sun non è ampiamente conosciuto o utilizzato.


36

L'aggiunta del costrutto loop for-each in 1.5. I <3 esso.

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

E può essere utilizzato in istanze nidificate:

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

Il costrutto for-each è applicabile anche alle matrici, in cui nasconde la variabile indice anziché l'iteratore. Il seguente metodo restituisce la somma dei valori in una matrice 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 alla documentazione Sun


30
Penso che usare iqui sia molto confuso, poiché la maggior parte delle persone si aspetta che io sia un indice e non l'elemento array.
cdmckay,

Quindi ... int sum (int [] array) {int result = 0; per (int element: array) {risultato + = elemento; } risultato di ritorno; }
Estratto il

28
L'unica cosa che mi fa impazzire è che sembra davvero molto semplice creare una parola chiave per accedere al valore del conteggio dei loop, ma non è possibile. Se voglio eseguire il loop su due array e apportare modifiche a un secondo in base ai valori nel primo, sono costretto a utilizzare la vecchia sintassi perché non ho offset nel secondo array.
Jherico,

6
È un peccato che non funzioni anche con le enumerazioni, come quelle utilizzate in JNDI. È tornato agli iteratori lì.
extraneon,

3
@extraneon: dai un'occhiata a Collections.list (Enumeration <T> e). Ciò dovrebbe aiutare con iterare le enumerazioni nel ciclo foreach.
Werner Lehmann,

34

l'ho scoperto personalmente java.lang.Voidmolto tardi - migliora la leggibilità del codice insieme ai generici, ad esCallable<Void>


2
non proprio. a un certo punto, devi essere specifico: Executors.newSingleThreadExecutor (). submit (new Callable <Void> () {..}) - non puoi istanziare un nuovo Callable <?> (), devi specificare un tipo esplicito, quindi è un'alternativa a Callable <Oggetto>.
Rahel Lüthy,

4
Void è più specifico di Object poiché Void può essere solo null, Object può essere qualsiasi cosa.
Peter Lawrey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.