Après avoir lu les fonctionnalités cachées de C #, je me suis demandé, quelles sont certaines des fonctionnalités cachées de Java?
Après avoir lu les fonctionnalités cachées de C #, je me suis demandé, quelles sont certaines des fonctionnalités cachées de Java?
Réponses:
L'initialisation de Double Brace m'a pris par surprise il y a quelques mois lorsque je l'ai découvert pour la première fois, je n'en avais jamais entendu parler auparavant.
Les ThreadLocals ne sont généralement pas aussi largement connus comme moyen de stocker l'état par thread.
Étant donné que JDK 1.5 Java a eu des outils de concurrence extrêmement bien mis en œuvre et robustes au-delà des seuls verrous, ils vivent dans java.util.concurrent et un exemple particulièrement intéressant est le sous- package java.util.concurrent.atomic qui contient des primitives thread-safe qui implémentent la comparaison -et-swap opération et peut mapper vers des versions natives prises en charge par le matériel de ces opérations.
Union conjointe dans la variance des paramètres de type:
public class Baz<T extends Foo & Bar> {}
Par exemple, si vous vouliez prendre un paramètre à la fois comparable et 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);
}
Cette méthode artificielle renvoie vrai si les deux collections données sont égales ou si l'une d'entre elles contient l'élément donné, sinon false. Le point à noter est que vous pouvez invoquer les méthodes de Comparable et Collection sur les arguments b1 et b2.
L'autre jour, j'ai été surpris par les initialiseurs d'instance. Je supprimais certaines méthodes repliées dans le code et j'ai fini par créer plusieurs initialiseurs d'instance:
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'exécution de la main
méthode affichera:
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
Je suppose que cela serait utile si vous aviez plusieurs constructeurs et aviez besoin d'un code commun
Ils fournissent également du sucre syntaxique pour initialiser vos cours:
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};
Map<String,String> codes = new HashMap<String,String>(){{
put("1","one");
put("2","two");
}};
JDK 1.6_07 + contient une application appelée VisualVM (bin / jvisualvm.exe) qui est une belle interface graphique au-dessus de nombreux outils. Il semble plus complet que JConsole.
Caractères génériques Classpath depuis Java 6.
java -classpath ./lib/* so.Main
Au lieu de
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Voir http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Pour la plupart des gens que j'interviewe pour les postes de développeurs Java, les blocs étiquetés sont très surprenants. Voici un exemple:
// 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;
}
}
}
}
Qui a dit goto
en java n'est qu'un mot-clé? :)
Qu'en est-il des types de retour covariants qui sont en place depuis JDK 1.5? Il est assez mal publicisé, car il s'agit d'un ajout non sexy, mais si je comprends bien, il est absolument nécessaire que les génériques fonctionnent.
Essentiellement, le compilateur permet désormais à une sous-classe d'affiner le type de retour d'une méthode redéfinie pour être une sous-classe du type de retour de la méthode d'origine. Donc c'est permis:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Vous pouvez appeler la values
méthode de la sous-classe et obtenir un thread trié sûr Set
de String
s sans avoir à effectuer de conversion vers le ConcurrentSkipListSet
.
Le transfert de contrôle dans un bloc enfin annule toute exception. Le code suivant ne lève pas RuntimeException - il est perdu.
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;
}
}
Depuis http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Personne n'a mentionné l'instance de mise en œuvre de telle manière que la vérification de null n'est pas nécessaire.
Au lieu de:
if( null != aObject && aObject instanceof String )
{
...
}
utilisez simplement:
if( aObject instanceof String )
{
...
}
free
ing ou delete
ing en C / C ++. Un tel concept fondamental.
Autoriser les méthodes et les constructeurs dans les énumérations m'a surpris. Par exemple:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Vous pouvez même avoir un "corps de classe spécifique constant" qui permet à une valeur d'énumération spécifique de remplacer les méthodes.
Plus de documentation ici .
mAge
devrait être définitive. Il y a rarement une raison pour les champs non finaux dans les énumérations.
Les paramètres de type pour les méthodes génériques peuvent être spécifiés explicitement comme ceci:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
. Vous pouvez ensuite téléphoner àClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Il est également utile pour certaines invocations de méthodes où un simple Collections.emptyMap () donnerait une erreur de compilation.
Vous pouvez utiliser des énumérations pour implémenter une 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: Des années plus tard ....
J'utilise cette fonctionnalité ici
public enum AffinityStrategies implements AffinityStrategy {
En utilisant une interface, les développeurs peuvent définir leurs propres stratégies. En utilisant un enum
moyen, je peux définir une collection (de cinq) intégrée.
Depuis Java 1.5, Java a maintenant une syntaxe beaucoup plus propre pour écrire des fonctions d'arité variable. Donc, au lieu de simplement passer un tableau, vous pouvez maintenant faire ce qui suit
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
bars est automatiquement converti en tableau du type spécifié. Pas une énorme victoire, mais une victoire néanmoins.
Mon préféré: vider toutes les traces de pile de threads en sortie standard.
les fenêtres: CTRL - Breakdans votre fenêtre java cmd / console
unix: kill -3 PID
Break
touche.
Quelques personnes ont posté sur les initialiseurs d'instance, en voici une bonne utilisation:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
Est un moyen rapide d'initialiser des cartes si vous faites quelque chose de simple et rapide.
Ou en l'utilisant pour créer un prototype de cadre pivotant rapide:
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 );
Bien sûr, il peut être abusé:
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");
}
});
}});
}});
}};
Les proxys dynamiques (ajoutés en 1.3) vous permettent de définir un nouveau type lors de l'exécution qui soit conforme à une interface. C'est utile un nombre surprenant de fois.
l'initialisation finale peut être différée.
Il s'assure que même avec un flux complexe de valeurs de retour logiques sont toujours définies. Il est trop facile de rater un cas et de retourner nul par accident. Cela ne rend pas impossible le retour de null, juste évident que c'est intentionnel:
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;
}
Je pense qu'une autre caractéristique "négligée" de java est la JVM elle-même. C'est probablement la meilleure machine virtuelle disponible. Et il prend en charge de nombreux langages intéressants et utiles (Jython, JRuby, Scala, Groovy). Toutes ces langues peuvent coopérer facilement et de manière transparente.
Si vous concevez une nouvelle langue (comme dans le cas scala), vous avez immédiatement toutes les bibliothèques existantes disponibles et votre langue est donc "utile" dès le début.
Toutes ces langues utilisent les optimisations HotSpot. La VM est très bien surveillée et débogable.
Vous pouvez définir une sous-classe anonyme et appeler directement une méthode dessus, même si elle n'implémente aucune interface.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) n'est pas réellement définie dans la sous-classe ...
La méthode asList de java.util.Arrays
permet une belle combinaison de varargs, de méthodes génériques et d'autoboxing:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
a la particularité que vous pouvez set()
éléments mais pas add()
ou remove()
. Je l'enveloppe donc généralement dans un new ArrayList(...)
ou dans un Collections.unmodifiableList(...)
, selon que je souhaite que la liste soit modifiable ou non.
Utiliser ce mot - clé pour accéder aux champs / méthodes de confinement d'une classe à partir d'une classe interne. Dans l'exemple ci-dessous, plutôt artificiel, nous voulons utiliser le champ sortAscending de la classe de conteneur de la classe interne anonyme. L'utilisation de ContainerClass.this.sortAscending au lieu de this.sortAscending fait l'affaire.
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;
}
}
MyActivity.this
.
Pas vraiment une fonctionnalité, mais une astuce amusante que j'ai découverte récemment dans une page Web:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
est un programme Java valide (bien qu'il génère un avertissement). Si vous ne voyez pas pourquoi, voyez la réponse de Gregory! ;-) Eh bien, la mise en évidence de la syntaxe ici donne également un indice!
Ce ne sont pas exactement des "fonctionnalités cachées" et pas très utiles, mais cela peut être extrêmement intéressant dans certains cas:
Classe sun.misc.Unsafe - vous permettra d'implémenter une gestion directe de la mémoire en Java (vous pouvez même écrire du code Java auto-modifiable avec ceci si vous essayez beaucoup):
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);
}
};
}
Quand je travaille dans Swing, j'aime le caché Ctrl- Shift-F1 .
Il vide l'arborescence des composants de la fenêtre actuelle.
(En supposant que vous n'avez pas lié cette frappe à autre chose.)
Chaque fichier de classe commence par la valeur hexadécimale 0xCAFEBABE pour l'identifier en tant que bytecode JVM valide.
( Explication )
Mon vote va à java.util.concurrent avec ses collections simultanées et ses exécuteurs flexibles permettant entre autres des pools de threads, des tâches planifiées et des tâches coordonnées. Le DelayQueue est mon préféré, où les éléments sont mis à disposition après un délai spécifié.
java.util.Timer et TimerTask peuvent être arrêtés en toute sécurité.
En outre, pas exactement caché mais dans un package différent des autres classes liées à la date et à l'heure. java.util.concurrent.TimeUnit est utile lors de la conversion entre nanosecondes, microsecondes, millisecondes et secondes.
Il se lit beaucoup mieux que la valeur habituelle someValue * 1000 ou someValue / 1000.
CountDownLatch
et CyclicBarrier
- si utile!
Mot clé d' assertion au niveau de la langue .
Ne fait pas vraiment partie du langage Java, mais le désassembleur javap fourni avec le JDK de Sun n'est pas largement connu ou utilisé.
L'ajout de la construction de boucle for-each en 1.5. Je le <3.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
Et peut être utilisé dans des instances imbriquées:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
La construction for-each s'applique également aux tableaux, où elle masque la variable d'index plutôt que l'itérateur. La méthode suivante renvoie la somme des valeurs d'un tableau int:
// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}
i
ici est très déroutante, car la plupart des gens s'attendent à ce que je sois un index et non l'élément de tableau.
personnellement, j'ai découvert java.lang.Void
très tard - améliore la lisibilité du code en conjonction avec les génériques, par exempleCallable<Void>