Fonctions cachées de Java

295

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?

grom
la source
17
Notez que ce n'est pas toujours une bonne idée d'utiliser ces fonctionnalités cachées; souvent, ils sont surprenants et déroutants pour les autres qui lisent votre code.
Kevin Bourrillion
1
Vous (/ quelqu'un) devriez probablement résumer soigneusement les réponses dans le corps de la question, comme la question C #.
ripper234

Réponses:

432

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.

Boris Terzic
la source
40
Initialisation à double accolade ... bizarre ... Je me méfierais d'adopter trop largement cet idiome particulier, car il crée en fait une sous-classe anonyme de l'objet, ce qui pourrait causer des problèmes d'égalité / de hachage déroutants. java.util.concurrent est un package vraiment génial.
MB.
6
J'ai enseigné Java, et c'est la toute première fois que je rencontre cette syntaxe ... ce qui montre que vous n'arrêtez jamais d'apprendre = 8-)
Yuval
49
Notez que si vous conservez une référence à une collection initialisée avec cet idiome "double accolade" (ou si nous l'appelons par son vrai nom - classe annonymous avec bloc d'initialisation), vous détenez implicitement une référence à l'objet externe qui peut provoquer une mémoire désagréable fuit. Je recommanderais de l'éviter complètement.
ddimitrov
51
"Initialisation à double accolade" est un nom très euphémique pour créer une classe interne anonyme, masquer ce qui se passe réellement et donner l'impression que les classes internes étaient destinées à être utilisées de cette façon. C'est un modèle que je préfère rester caché.
erickson
11
Presque, ce n'est pas vraiment un bloc statique mais un "bloc d'initialisation" qui est différent car il est exécuté à un moment différent (voir le lien que j'ai mis dans la réponse pour plus de détails)
Boris Terzic
279

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.

Apocalisp
la source
Mon utilisation préférée pour cela est lorsque vous avez besoin d'une méthode qui accepte une séquence de caractères ajoutée.
Neil Coffey
5
Est-il possible d'avoir un "OU" à la place du &?
mainstringargs
9
@Grasper: Non, OR (union disjointe) n'est pas fourni dans ce contexte. Mais vous pouvez utiliser à la place un type de données d'union disjoint comme Soit <A, B>. Ce type est le double d'un type Pair <A, B>. Regardez la bibliothèque Java fonctionnelle ou les bibliothèques de base Scala pour un exemple d'un tel type de données.
Apocalisp
5
Vous devez dire que vous DEVEZ étendre une seule classe et plusieurs interfaces -> classe publique Baz <T étend Clazz & Interface1 & InterfaceI ... et non classe Baz <T étend Clazz1 & ClazzI>
JohnJohnGa
220

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 mainmé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");
}};
David Carlson
la source
38
L'avantage de ceci sur une méthode explicite qui doit être appelée est que si quelqu'un ajoute un constructeur plus tard, il n'a pas besoin de se rappeler d'appeler init (); cela se fera automatiquement. Cela peut empêcher les erreurs des futurs programmeurs.
M. Shiny et New 安 宇
40
De plus, contrairement à une méthode init (), elle peut initialiser les champs finaux.
Darron
2
Et si vous étendez la classe et instanciez divers enfants? Se comportera-t-il toujours de la même manière?
Kezzer
12
Les gens décident souvent des certifications (par exemple stackoverflow.com/questions/281100/281127#281127 ) et en particulier remettent en question leurs mérites techniques. Mais si plus de programmeurs ici avaient étudié leur SCJP, cela ne serait pas considéré comme une "fonctionnalité cachée" par tant de personnes. ;-)
Jonik
12
Je parie que même le livre "java en 24 heures" a cette "caractéristique évidente". lire la suite les gars
:)
201

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.

Kevin Wong
la source
Et il a un plugin (c'est un truc de netbeans) qui lui permet d'utiliser des plugins Jconsole. Plutôt sympa.
Thorbjørn Ravn Andersen
VisualVM est la meilleure chose depuis le pain en tranches, vraiment! Dommage qu'il n'ait pas toutes les fonctionnalités lors de l'exécution contre JDK 1.5
sandos
Je trouve VisualVM lent ou inutilisable dans certaines circonstances. Le commercial YourKit n'a pas ce problème, mais n'est malheureusement pas gratuit.
Roalt
Les versions les plus récentes de Visual VM, à partir de JDK 1.6.0_22 et versions ultérieures, sont bien améliorées. Je parierais que JDK1.7 en a une version encore meilleure.
djangofan
156

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 gotoen java n'est qu'un mot-clé? :)

Georgy Bolyuba
la source
2
Eh bien, je préférerais plutôt avoir une option pour le faire de plusieurs façons. Par exemple, j'ai vu des gens utiliser System.exit (1); dans le code Servlet et EJB, mais cela ne signifie pas que nous devons supprimer System.exit (); du JDK, non?
Georgy Bolyuba, le
31
Dans certaines circonstances, dans une construction de boucle imbriquée, il peut être utile de passer à l'itération suivante d'une boucle externe. Ce serait une utilisation raisonnable de cette fonctionnalité.
alasdairg
75
Ce qui est particulièrement inconnu de nombreux programmeurs (et probablement aussi bien), c'est que vous pouvez réellement étiqueter et sortir de N'IMPORTE QUEL vieux bloc. Il ne doit pas nécessairement s'agir d'une boucle - vous pouvez simplement définir un bloc arbitraire, lui donner une étiquette et utiliser la rupture avec.
Neil Coffey
27
Ce n'est pas du tout un goto, il ne peut que revenir à une itération précédente (c'est-à-dire: vous ne pouvez pas sauter en avant). Il s'agit du même mécanisme qui se produit lorsqu'une itération retourne false. Dire java has goto revient à dire que tout langage dont le compilateur produit une instruction JUMP a une instruction goto.
Zombies
4
Vous interviewez donc sur la base de trivia Java plutôt que sur l'aptitude à résoudre des problèmes et à réfléchir à des conceptions. Je m'assurerai de ne jamais interviewer votre entreprise. :)
Javid Jamae
144

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 valuesméthode de la sous-classe et obtenir un thread trié sûr Setde Strings sans avoir à effectuer de conversion vers le ConcurrentSkipListSet.

serg10
la source
Pouvez-vous fournir un exemple d'utilisation?
Allain Lalonde le
24
J'utilise beaucoup ça. clone () est un excellent exemple. Il est censé renvoyer Object, ce qui signifie que vous devez dire par exemple (List) list.clone (). Cependant, si vous déclarez comme List clone () {...}, la conversion n'est pas nécessaire.
Jason Cohen,
142

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

James AN Stauffer
la source
7
C'est méchant, mais c'est aussi une sorte de conséquence logique de la façon dont fonctionne finalement. Le contrôle de flux try / catch / finalement fait ce qu'il est censé faire, mais uniquement dans certaines limites. De même, vous devez faire attention à ne pas provoquer d'exception à l'intérieur d'un bloc catch / finally, sinon vous supprimerez également l'exception d'origine. Et si vous faites un System.exit () à l'intérieur du bloc try, le bloc finally ne sera pas appelé. Si vous cassez le flux normal, vous cassez le flux normal ...
Neil Coffey
N'utilisez pas enfin {return; } mais enfin {code sans retour}. Ceci est logique, car finalement est également destiné à être exécuté lorsque des exceptions se sont produites, et la seule signification possible d'un retour en tant que gestionnaire d'exceptions doit être d'ignorer l'exception et, en fait, de retourner.
extraneon
21
Cela ressemble plus à un "gotcha" qu'à une fonctionnalité cachée, bien qu'il puisse être utilisé comme tel, l'utilisation de cette méthode ne serait pas une bonne idée.
davenpcj
Eclipse émet un avertissement si vous procédez ainsi. Je suis avec Eclipse. Si vous voulez attraper une exception ... alors attrapez une exception.
helios
C'est ce que vous payez pour du code sale qui revient du milieu de la méthode. Mais toujours un bel exemple.
Rostislav Matl
141

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 )
{
    ...
}
Cadet Pirx
la source
9
Il est dommage que cette fonctionnalité soit si peu connue. J'ai vu beaucoup de code similaire au premier bloc de code.
Peter Dolberg
4
C'est parce que Java a un type nul spécial (caché) que vous ne voyez pas et que vous ne pouvez pas référencer.
Nick Hristov
Ce qui est pire, c'est de vérifier la valeur null avant freeing ou deleteing en C / C ++. Un tel concept fondamental.
Thomas Eding
134

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 .

Adrian Mouat
la source
20
Fonctionnalité vraiment géniale en fait - fait des énumérations OO et résout beaucoup de problèmes d'initialisation d'une manière très propre.
Bill K du
5
Enum en tant que singleton? Énumérer avec une seule valeur?
Georgy Bolyuba
6
Georgy: Singleton est une instance de l'objet, pas un objet avec une valeur.
dshaw
20
@Georgy: voir également le point 3 de Joshua Bloch's Effective Java (2nd ed); "Bien que cette approche n'ait pas encore été largement adoptée, un type d'énumération à élément unique est le meilleur moyen de mettre en œuvre un singleton."
Jonik
3
Petite piqûre: mAgedevrait être définitive. Il y a rarement une raison pour les champs non finaux dans les énumérations.
Joachim Sauer
121

Les paramètres de type pour les méthodes génériques peuvent être spécifiés explicitement comme ceci:

Collections.<String,Integer>emptyMap()
Kevin Wong
la source
10
Et par Dieu, c'est laid et déroutant. Et non pertinent pour taper la sécurité.
Chris Broadfoot
8
J'aime cela. Cela rend votre code un peu plus explicite et en tant que tel plus clair pour le pauvre gazon qui devra le maintenir dans un an ou deux.
extranéon
6
Ceci est en fait très utile dans les situations où vous avez déclaré une méthode générique statique telle que public static <T> T foo(T t). Vous pouvez ensuite téléphoner àClass.<Type>foo(t);
Finbarr
Pour une raison quelconque, cela ne semble pas fonctionner avec des méthodes importées statiquement. Je me demande pourquoi.
oksayt le
Ceci est particulièrement utile lorsque vous utilisez des ifs ternaires avec un retour. Par exemple 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.
Andreas Holstenson
112

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 {

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

En utilisant une interface, les développeurs peuvent définir leurs propres stratégies. En utilisant un enummoyen, je peux définir une collection (de cinq) intégrée.

Peter Lawrey
la source
27
C'est de la folie. (+1)
Céphalopode du
12
@Arian ce n'est pas de la folie. CE. EST. JAVAAAAAAHHHH!
slezica
1
WHAAAAAT non, je suis avec Adrian. Ce n'est pas Java. C'est de la folie. Je meurs d'envie de l'utiliser.
slezica
104

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.

Paul Wicks
la source
23
La chose importante à ce sujet est que lorsque vous appelez la méthode, vous pouvez écrire: foo ("premier", "deuxième", "troisième")
Steve Armstrong
9
afin que l'ancien monde bonjour puisse être réécrit; public static void main (String ... args) {System.out.println ("Bonjour tout le monde!"); }
Karussell
@Karussell Peut-être, mais il semblerait que les arguments ne soient pas pertinents: p
Kelly Elton
93

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

Chris Mazzola
la source
15
Aussi ctrl- \ sous Unix. Ou utilisez jstack du JDK.
Tom Hawtin - tackline
9
Merci, vous venez de m'apprendre que mon clavier a une Breaktouche.
Amy B
2
Sous Windows, CTRL-BREAK ne fonctionne que si le processus est en cours d'exécution dans la fenêtre de console actuelle. Vous pouvez utiliser JAVA_HOME / bin / jstack.exe à la place. Fournissez-lui simplement l'ID de processus Windows.
Javid Jamae
Je pensais que c'était tuer -SIGQUIT
Nick Hristov
@ Nick, oui SIGQUIT est généralement le signal n ° 3.
Chris Mazzola
89

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");
                        }
                     });
                 }});
        }});
    }};
OscarRyz
la source
D'une certaine manière, c'est un peu comme si le mot-clé "with" (fonctionnalité, en fait) avait été ajouté à Java. Peut être très pratique, récemment j'ai grogné parce que l'init des tableaux n'était pas disponible pour les collections. Merci!
PhiLho
15
Il y a cependant un effet secondaire. Des objets anonymes sont créés, ce qui peut ne pas toujours convenir.
Amit
17
Bien qu'après l'avoir regardé de plus près, je dois dire que je suis étrangement attiré par la nidification naturelle que cela fournit, même la version "Abused".
Bill K
4
Oui - j'aime bien la version «abusée», je pense que c'est vraiment très clair et lisible, mais c'est peut-être juste moi.
barryred
3
Tout à fait d'accord, la hiérarchie du code reflétant la hiérarchie de l'interface graphique est une énorme amélioration par rapport à une séquence d'appels de méthode.
opsb
88

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.

jodonnell
la source
10
Les proxys dynamiques sont une excellente raison de choisir d'écrire une interface Foo et de l'utiliser partout, avec une classe "FooImpl" par défaut. Cela peut sembler laid au premier abord ("Pourquoi ne pas simplement avoir une classe appelée Foo?"), Mais les avantages en termes de flexibilité future et de capacité de simulation pour les tests unitaires sont pratiques. Bien qu'il existe des moyens de le faire pour les non-interfaces, ils nécessitent généralement des éléments supplémentaires comme cblib.
Darien
82

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;
}
Allain Lalonde
la source
C'est surprenant. Peut-on raisonnablement dire: «La valeur d'une variable finale peut être définie une fois», peu importe où se produit l'ensemble?
David Koelle
29
Oui, mais plus fortement: "La valeur d'une variable finale doit être fixée une fois"
Allain Lalonde
6
+1 D'accord, c'est un autre outil précieux pour repérer les erreurs au moment de la compilation, et que les programmeurs semblent timides à utiliser pour une raison quelconque. Notez que, à partir de Java 5, «final» a également des implications sur la sécurité des threads, être en mesure de définir une variable finale pendant le constructeur est inestimable.
Neil Coffey
4
Bien que pour cette méthode spécifique, j'utiliserais simplement plusieurs retours. En fait, dans la plupart des cas où cela est applicable, je le remanierais probablement dans une méthode distincte et utiliserais plusieurs retours.
ripper234
J'aime cela! J'ai toujours supprimé le mot clé final car je pensais qu'il échouerait. Merci!
KARASZI István
62

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.

Mo.
la source
18
Non, ce n'est en fait pas une très bonne machine virtuelle. Il a été uniquement conçu pour exécuter JAVA. Les langages dynamiques et fonctionnels sans type ne fonctionnent pas bien avec lui. Si vous souhaitez utiliser une machine virtuelle, vous devez utiliser .NET / Mono. Cela a été conçu pour fonctionner avec CHAQUE langue ...
Hadès32
14
En fait, la JVM est uniquement conçue pour exécuter des Bytecodes Java. Vous pouvez compiler la plupart des langages modernes en Java Bytecode. À propos des seules choses qui manquent à Java Bytecode est le support de langage dynamique, les pointeurs et le support de récursivité de queue.
mcjabberz
12
@ Hades32: en fait, la VM .NET est assez similaire à la JVM. Il n'a obtenu la prise en charge des langages dynamiques que récemment (avec le DLR) et Java 7 est sur le point d'obtenir également cette prise en charge. Et le "langage CHAQUE" classique de .NET (C #, Visual Basic.NET, ...) ont tous à peu près exactement le même ensemble de fonctionnalités.
Joachim Sauer
13
JVM ne prend pas en charge les génériques, contrairement à la machine virtuelle .NET. JVM est loin d'être le meilleur.
Blindy
3
Sans négliger les plaintes concernant des fonctionnalités de langage spécifiques non directement prises en charge par la JVM ... mais j'ai tendance à penser que la stabilité, la cohérence multiplateforme et les bonnes performances sont de loin les raisons pour lesquelles la JVM obtient des points supplémentaires. Je travaille avec Java côté serveur depuis de nombreuses années maintenant sur de nombreuses plates-formes (y compris AS / 400) et j'ai réussi à l'oublier complètement - les bogues sont presque toujours dans le code que je peux corriger, et cela ne plante tout simplement pas.
Rob Whelan
58

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");
Ron
la source
@Vuntic - Il vous permet de définir une classe simple dans le contexte dont elle a besoin.
ChaosPandion
1
@Chaos, mais pourquoi? Vous avez un exemple réel où il est utile?
Thorbjørn Ravn Andersen
10
@Wouter - Dans ce cas, la méthode qui est appelée sur l'objet anonyme ( start()) n'est pas réellement définie dans la sous-classe ...
Axel
En fait, c'est une fonctionnalité très utile si vous étendez une classe de base qui effectue la configuration requise, appelle la méthode que vous écrivez, puis fait le démontage. Démarrez la chose en appelant une méthode dans la classe de base (que je ne donnerais probablement pas le même nom). Il y a un exemple d'utilisation (pas de définition) ici
AmigoNico
56

La méthode asList de java.util.Arrayspermet une belle combinaison de varargs, de méthodes génériques et d'autoboxing:

List<Integer> ints = Arrays.asList(1,2,3);
Bruno De Fraine
la source
15
vous voulez encapsuler la liste retournée avec un constructeur List sinon la taille des entiers sera fixe (car elle est soutenue par le tableau)
KitsuneYMG
2
Le Arrays.asLista 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.
Christian Semrau
53

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;
}
}
Tahir Akhtar
la source
4
Cela n'est nécessaire que si vous avez masqué le nom (dans votre cas, avec le nom du paramètre de méthode). Si vous aviez appelé l'argument autrement, vous pourriez accéder directement à la variable membre sortAscending de la classe Container sans utiliser 'this'.
sk.
7
Il est toujours utile d'avoir une référence à la classe englobante, par exemple. si vous devez le transmettre à une méthode ou à un constructeur.
PhiLho
Souvent utilisé dans le développement de mises en page Android, afin d'obtenir le contexte de, disons, l'auditeur d'un bouton, avec MyActivity.this.
espinchi
52

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!

PhiLho
la source
15
soigné, un label avec un commentaire :)
Thorbjørn Ravn Andersen
46

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);
        }
    };
}
Das
la source
20
c'est une API sun. * qui ne fait pas vraiment partie du langage Java en soi
DW.
Il existe un certain nombre d'autres méthodes curieuses sur Unsafe, comme la création d'un objet sans appeler de constructeur, les méthodes de style malloc / realloc / free.
Peter Lawrey
J'aime surtout les getters et setters primitifs sur les emplacements mémoire, comme putDouble (adresse longue, double d).
Daniel
42

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

Devon_C_Miller
la source
1
Votre gestionnaire de fenêtres a probablement quelque chose lié à cette clé. Gnome ne s'y lie pas, donc je suppose que vous exécutez KDE qui le lie à «basculer vers le bureau 13». Vous pouvez le changer en allant dans Panneau de configuration, Régional, Raccourcis clavier et en supprimant le mappage pour Shift-Ctrl-F1
Devon_C_Miller
40

Chaque fichier de classe commence par la valeur hexadécimale 0xCAFEBABE pour l'identifier en tant que bytecode JVM valide.

( Explication )

Dolph
la source
38

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.

stili
la source
Découvert récemment CountDownLatchet CyclicBarrier- si utile!
Raphael
37

Mot clé d' assertion au niveau de la langue .

Mark Cidade
la source
19
Le problème avec assert est qu'il doit être activé pendant l'exécution.
extraneon
10
Mais s'il est désactivé, c'est comme s'il n'était pas là. Vous pouvez ajouter autant d'assertions que vous le souhaitez dans votre code et vous n'aurez aucune pénalité de performance si elles sont désactivées.
Ravi Wallau
5
Je pense que c'est une bonne chose à propos de l'affirmation: elle peut être désactivée sans pénalité.
andref
le problème est, si vous avez accidentellement mis en œuvre un effet secondaire dans une assertion, vous devez activer l'assertion pour que votre programme fonctionne ...
Chii
Pour détecter si les assertions sont activées, vous pouvez utiliser {boolean assertsOn = false; assert assertsOn = true; if (assertsOn) {/ * vérification complexe * /}}. Cela permet également de consigner ou de lever une exception si l'état d'assertion n'est pas celui attendu.
fernacolo
37

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

Binil Thomas
la source
36

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

Lien vers la documentation Sun

18 Lapin
la source
30
Je pense que l'utilisation iici 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.
cdmckay
Donc ... int sum (int [] array) {int result = 0; for (int element: array) {result + = element; } retourne le résultat; }
Drew
28
La seule chose qui me rend fou à ce sujet, c'est qu'il semble qu'il serait vraiment très facile de créer un mot-clé pour accéder à la valeur du nombre de boucles, mais vous ne pouvez pas. Si je veux faire une boucle sur deux tableaux et apporter des modifications à un second en fonction des valeurs du premier, je suis obligé d'utiliser l'ancienne syntaxe car je n'ai pas de décalage dans le deuxième tableau.
Jherico
6
C'est dommage qu'il ne fonctionne pas également avec les énumérations, comme celles utilisées dans JNDI. C'est de retour aux itérateurs là-bas.
extraneon
3
@extraneon: jetez un œil à Collections.list (énumération <T> e). Cela devrait aider à itérer les énumérations dans la boucle foreach.
Werner Lehmann
34

personnellement, j'ai découvert java.lang.Voidtrès tard - améliore la lisibilité du code en conjonction avec les génériques, par exempleCallable<Void>

Rahel Lüthy
la source
2
pas assez. à un moment donné, vous devez être spécifique: Executors.newSingleThreadExecutor (). submit (new Callable <Void> () {..}) - vous ne pouvez pas instancier un nouveau Callable <?> (), vous devez spécifier un type explicite - c'est donc une alternative à Callable <Object>.
Rahel Lüthy
4
Void est plus spécifique que Object car Void ne peut être nul, l'objet peut être n'importe quoi.
Peter Lawrey