Caratteristiche nascoste di Java

Dopo aver letto le caratteristiche nascoste di C # mi sono chiesto: quali sono alcune delle funzionalità nascoste di Java?

Double Brace Initialization mi ha colto di sorpresa alcuni mesi fa, quando l’ho scoperto per la prima volta, non ne ho mai sentito parlare prima.

ThreadLocals in genere non è così ampiamente conosciuto come un modo per archiviare lo stato per thread.

Dal momento che JDK 1.5 Java ha avuto strumenti di concorrenza estremamente ben implementati e robusti oltre i soli blocchi, essi vivono in java.util.concurrent e un esempio particolarmente interessante è il sottopagatore java.util.concurrent.atomic che contiene le primitive thread-safe che implementano il confronto -and-swap operation e può associare a versioni native supportate da hardware di queste operazioni.

Unione unita nella varianza dei parametri di tipo:

public class Baz {} 

Ad esempio, se si desidera prendere un parametro che è sia comparabile sia una raccolta:

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

Questo metodo forzato restituisce true se le due raccolte date sono uguali o se una di esse contiene l’elemento dato, altrimenti false. Il punto da notare è che puoi invocare i metodi sia Comparable sia Collection sugli argomenti b1 e b2.

Sono rimasto sorpreso dagli inizializzatori di istanza l’altro giorno. Stavo cancellando alcuni metodi piegati al codice e ho finito per creare più inizializzatori di 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 metodo main mostrerà:

 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 sarebbe utile se tu avessi più costruttori e avessi bisogno di codice comune

Forniscono inoltre zucchero sintattico per inizializzare le tue lezioni:

 List numbers = new ArrayList(){{ add(1); add(2); }}; Map codes = new HashMap(){{ put("1","one"); put("2","two"); }}; 

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

Wildcard di Classpath da Java 6.

 java -classpath ./lib/* so.Main 

Invece di

 java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main 

Vedi http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html

Per la maggior parte delle persone che intervengo 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 goto in java è solo una parola chiave? 🙂

Che ne dici dei tipi di ritorno covarianti che sono stati in vigore dal JDK 1.5? È piuttosto poco pubblicizzato, in quanto è un’aggiunta non addossata, ma, a quanto ho capito, è assolutamente necessario che i generici funzionino.

In sostanza, il compilatore ora consente a una sottoclass di restringere il tipo di restituzione di un metodo sottoposto a override in modo che sia una sottoclass del tipo restituito del metodo originale. Quindi questo è permesso:

 class Souper { Collection values() { ... } } class ThreadSafeSortedSub extends Souper { @Override ConcurrentSkipListSet values() { ... } } 

È ansible chiamare il metodo dei values della sottoclass e ottenere un Set di String ordinato sicuro per thread senza dover eseguire il cast verso ConcurrentSkipListSet .

Non ho visto nessuno menzionare l’istanza di essere implementata in modo tale che il controllo di null non è necessario.

Invece di:

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

basta usare:

 if( aObject instanceof String ) { ... } 

Il trasferimento del controllo in un blocco finale elimina ogni eccezione. Il seguente codice non lancia RuntimeException: viene 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

Permettere metodi e costruttori in enigmi 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; } } 

È anche ansible avere un “corpo di class specifico costante” che consente a un valore enum specifico di sovrascrivere i metodi.

Più documentazione qui .

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

 Collections.emptyMap() 

È ansible utilizzare le enumerazioni 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 ….

Io 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. Usare un enum significa che posso definire una collezione (di cinque) incorporata in una.

A partire da Java 1.5, Java ora ha una syntax molto più pulita per scrivere funzioni di variabile arity. 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 automaticamente convertite in array del tipo specificato. Non una vittoria enorme, ma una vittoria comunque.

Il mio preferito: scarica tutte le tracce dello stack di thread in standard.

windows: CTRLInterruzione della finestra java cmd / console

unix: kill -3 PID

Un paio di persone hanno pubblicato su inizializzatori di istanza, 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 solo facendo qualcosa di veloce e semplice.

O usarlo per creare un prototipo di canvasio 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 actionPerformsd( ActionEvent ae ){ System.out.println("Button pushed"); } }); }}); frame.add( panel ); 

Certo che 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 actionPerformsd( ActionEvent ae ){ System.out.println("Button pushed"); } }); }}); }}); }}; 

I proxy dinamici (aggiunti in 1.3) consentono di definire un nuovo tipo in fase di runtime conforms a un’interfaccia. È tornato utile un numero sorprendente di volte.

l’inizializzazione finale può essere posticipata.

Si assicura che anche con un stream complesso di valori di ritorno logici sia sempre impostato. È troppo facile perdere un caso e restituire nulla per sbaglio. Non rende imansible il reso nullo, è 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; } 

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 quelle lingue possono cooperare facilmente e senza interruzioni.

Se progetti una nuova lingua (come nella scala-case) hai immediatamente tutte le librerie esistenti disponibili e la tua lingua è quindi “utile” fin dall’inizio.

Tutte quelle lingue utilizzano le ottimizzazioni di HotSpot. La VM è molto ben monitorata e debugabile.

È ansible definire una sottoclass anonima e chiamare direttamente un metodo su di esso anche se non implementa interfacce.

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

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

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

Usando questa parola chiave per accedere ai campi / metodi di contenere la class da una class interna. Di seguito, un esempio piuttosto forzato, vogliamo usare il campo sortAscending della class container dalla class interna anonima. Usare ContainerClass.this.sortAvending invece di this.sortAcending fa il trucco.

 import java.util.Comparator; public class ContainerClass { boolean sortAscending; public Comparator createComparator(final boolean sortAscending){ Comparator comparator = new Comparator() { public int compare(Integer o1, Integer o2) { if (sortAscending || ContainerClass.this.sortAscending) { return o1 - o2; } else { return o2 - o1; } } }; return comparator; } } 

Non proprio una caratteristica, 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 (sebbene generi un avvertimento). Se non vedi perché, vedi la risposta di Gregory! 😉 Beh, l’evidenziazione della syntax qui dà anche un suggerimento!

Questo non è esattamente “caratteristiche nascoste” e non è molto utile, ma può essere estremamente interessante in alcuni casi:
Classe sun.misc.Unsafe – ti permetterà di implementare la gestione diretta della memoria in Java (puoi anche scrivere codice Java auto-modificante con questo se 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); } }; } 

Lavorando in Swing mi piace la funzione CtrlShiftF1 nascosta.

Scarica l’albero dei componenti della finestra corrente.
(Supponendo che tu non abbia limitato quella sequenza di tasti a qualcos’altro).

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

( Spiegazione )

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, in cui gli elementi sono resi disponibili dopo un ritardo specificato.

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

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

Si legge molto meglio del solito qualcheValore * 1000 o qualcheValore / 1000.

Parola chiave di asserzione a livello di lingua.

Non fa realmente parte del linguaggio Java, ma il disassemblatore javap che viene fornito con il JDK di Sun non è molto conosciuto o utilizzato.

L’aggiunta del costrutto del ciclo for-each in 1.5. Io <3 it.

 // 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 agli array, dove nasconde la variabile index piuttosto che l’iteratore. Il seguente metodo restituisce la sum dei valori in un array 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 di Sun.

i personally discovered java.lang.Void very late — improves code readability in conjunction with generics, eg Callable