Características ocultas de Java

295

Después de leer las características ocultas de C #, me pregunté, ¿cuáles son algunas de las características ocultas de Java?

grom
fuente
17
Tenga en cuenta que no siempre es una buena idea usar estas funciones ocultas; muchas veces son sorprendentes y confusos para otros que leen su código.
Kevin Bourrillion el
1
Usted (/ alguien) probablemente debe resumir las respuestas ordenadamente en el cuerpo de la pregunta como la pregunta de C #.
ripper234

Respuestas:

432

La inicialización de Double Brace me tomó por sorpresa hace unos meses cuando lo descubrí, nunca antes había oído hablar de él.

Los ThreadLocals generalmente no son tan conocidos como una forma de almacenar el estado por hilo.

Dado que JDK 1.5 Java ha tenido herramientas de concurrencia extremadamente bien implementadas y robustas más allá de solo bloqueos, viven en java.util.concurrent y un ejemplo específicamente interesante es el subpaquete java.util.concurrent.atomic que contiene primitivas seguras para subprocesos que implementan la comparación -y-swap y puede correlacionarse con versiones reales de estas operaciones compatibles con hardware nativo.

Boris Terzic
fuente
40
Inicialización de doble paréntesis ... raro ... Sin embargo, me preocuparía adoptar ese modismo en particular, ya que en realidad crea una subclase anónima del objeto, lo que podría causar problemas confusos de igual / hashcode. java.util.concurrent es un paquete realmente genial.
MB.
66
He enseñado Java, y esta es la primera vez que me encuentro con esta sintaxis ... que demuestra que nunca dejas de aprender = 8-)
Yuval
49
Tenga en cuenta que si conserva una referencia a una colección inicializada con este modismo de "doble paréntesis" (o si la llamamos por su nombre real: clase anónima con bloque inicializador), implícitamente tiene una referencia al objeto externo que puede causar memoria desagradable fugas Recomiendo evitarlo por completo.
ddimitrov
51
La "inicialización de doble paréntesis" es un nombre muy eufemístico para crear una clase interna anónima, pasar por alto lo que realmente está sucediendo y hacer que suene como si las clases internas estuvieran destinadas a usarse de esta manera. Este es un patrón que preferiría permanecer oculto.
erickson
11
Casi, no es realmente un bloque estático sino un "bloque inicializador" que es diferente ya que se ejecuta en un momento diferente (vea el enlace que puse en la respuesta para más detalles)
Boris Terzic
279

Unión conjunta en la varianza del parámetro tipo:

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

Por ejemplo, si desea tomar un parámetro que sea Comparable y una Colección:

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

Este método artificial devuelve verdadero si las dos colecciones dadas son iguales o si alguna de ellas contiene el elemento dado, de lo contrario es falso. El punto a tener en cuenta es que puede invocar métodos de Comparable y Collection en los argumentos b1 y b2.

Apocalisp
fuente
Mi uso favorito para esto es cuando necesitas un método que acepte una secuencia adjunta.
Neil Coffey
55
¿Es posible tener un "OR" allí en lugar del &?
mainstringargs
99
@Grasper: No, OR (unión disjunta) no se proporciona en ese contexto. Pero puede utilizar un tipo de datos de unión disjunto como Either <A, B> en su lugar. Este tipo es el doble de un tipo Par <A, B>. Mire la biblioteca funcional de Java o las bibliotecas principales de Scala para ver un ejemplo de este tipo de datos.
Apocalisp
55
Debería decir que DEBE extender solo una clase y varias interfaces -> clase pública Baz <T extiende Clazz & Interface1 & InterfaceI ... y no la clase Baz <T extiende Clazz1 & ClazzI>
JohnJohnGa
220

Me sorprendieron los inicializadores de instancia el otro día. Estaba eliminando algunos métodos de código plegado y terminé creando múltiples inicializadores de instancia:

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

La ejecución del mainmétodo mostrará:

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

Supongo que esto sería útil si tuviera múltiples constructores y necesitara un código común

También proporcionan azúcar sintáctico para inicializar tus clases:

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
fuente
38
La ventaja de esto sobre un método explícito que necesita ser llamado es que si alguien agrega un constructor más tarde, no necesita recordar llamar a init (); Eso se hará automáticamente. Esto puede evitar errores por parte de futuros programadores.
Mr. Shiny and New 安 宇
40
Además, a diferencia de un método init (), puede inicializar los campos finales.
Darron
2
¿Qué pasa si extiendes la clase e instancias a varios niños? ¿Seguirá comportándose de la misma manera?
Kezzer
12
La gente a menudo des certificaciones (por ejemplo, stackoverflow.com/questions/281100/281127#281127 ) y cuestionan especialmente sus méritos técnicos. Pero si más programadores aquí hubieran estudiado para su SCJP, muchos no lo considerarían una "característica oculta". ;-)
Jonik
12
Apuesto a que incluso el libro "Java en 24 horas" tiene esta "característica obvia". leer más chicos
:)
201

JDK 1.6_07 + contiene una aplicación llamada VisualVM (bin / jvisualvm.exe) que es una buena GUI además de muchas de las herramientas. Parece más completo que JConsole.

Kevin Wong
fuente
Y tiene un complemento (es una cosa de netbeans) que le permite usar complementos de Jconsole. Muy agradable.
Thorbjørn Ravn Andersen
¡VisualVM es lo mejor desde el pan rebanado, de verdad! Lástima que no tenga todas las características cuando se ejecuta contra JDK 1.5
sandos
Encuentro VisualVM lento o inutilizable en algunas circunstancias. El YourKit comercial no tiene este problema, pero desafortunadamente no es gratuito.
Roalt
Las versiones más recientes de Visual VM, de JDK 1.6.0_22 y posteriores, se han mejorado mucho. Apuesto a que JDK1.7 tiene una versión aún mejor.
djangofan
156

Para la mayoría de las personas que entrevisto para puestos de desarrollador de Java, los bloques etiquetados son muy sorprendentes. Aquí hay un ejemplo:

// 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én dijo que gotoen java es solo una palabra clave? :)

Georgy Bolyuba
fuente
2
Bueno, preferiría tener una opción para hacerlo de varias maneras. Por ejemplo, vi personas usando System.exit (1); en Servlet y código EJB, pero eso no significa que debamos eliminar System.exit (); del JDK, ¿verdad?
Georgy Bolyuba
31
En algunas circunstancias, dentro de una construcción de bucle anidado, puede ser útil continuar con la siguiente iteración de un bucle externo. Este sería un uso razonable de esta función.
alasdairg
75
Lo que es especialmente desconocido para muchos programadores (y probablemente igual) es que puedes etiquetar y salir de CUALQUIER bloque antiguo. No tiene que ser un bucle: solo puede definir un bloque arbitrario, darle una etiqueta y usar romper con él.
Neil Coffey
27
No es un goto en absoluto, solo puede volver a una iteración previa (es decir: no puede saltar hacia adelante). Este es el mismo mecanismo que ocurre cuando una iteración devuelve falso. Decir que Java tiene goto es como decir que cualquier lenguaje cuyo compilador produce una instrucción JUMP tiene una declaración goto.
Zombies
44
Por lo tanto, la entrevista se basa en curiosidades de Java en lugar de en la capacidad para resolver problemas y pensar en los diseños. Me aseguraré de nunca entrevistarme con su compañía. :)
Javid Jamae
144

¿Qué hay de los tipos de retorno covariantes que han estado vigentes desde JDK 1.5? Está muy poco publicitado, ya que es una adición poco atractiva, pero, según tengo entendido, es absolutamente necesario para que funcionen los genéricos.

Esencialmente, el compilador ahora permite que una subclase limite el tipo de retorno de un método anulado para que sea una subclase del tipo de retorno del método original. Entonces esto está permitido:

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

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

Puede llamar al valuesmétodo de la subclase y obtener un subproceso ordenado a salvo Setde Strings sin tener que bajar la conversión al ConcurrentSkipListSet.

revs serg10
fuente
¿Puedes proporcionar un ejemplo de uso?
Allain Lalonde
24
Yo uso esto mucho. clone () es un gran ejemplo. Se supone que devuelve Object, lo que significa que tendría que decir, por ejemplo, (List) list.clone (). Sin embargo, si declaras como List clone () {...}, entonces el lanzamiento es innecesario.
Jason Cohen
142

La transferencia de control en un bloque finalmente descarta cualquier excepción. El siguiente código no arroja RuntimeException, se pierde.

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

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

James AN Stauffer
fuente
77
Es desagradable, pero también es una consecuencia lógica de cómo finalmente funciona. El control de flujo try / catch / finalmente hace lo que se pretende hacer, pero solo dentro de ciertos límites. Del mismo modo, debe tener cuidado de no causar una excepción dentro de un bloque catch / finally, o también descartará la excepción original. Y si haces un System.exit () dentro del bloque try, el bloque finalmente no será llamado. Si interrumpe el flujo normal, interrumpe el flujo normal ...
Neil Coffey
No use finalmente {return; } pero finalmente {código sin retorno}. Esto es lógico, ya que finalmente también se pretende ejecutar cuando se produjeron excepciones, y el único significado posible de un retorno como manejador de excepciones debe ser ignorar la excepción y, de hecho, el retorno.
extraneon
21
Esto parece más una "trampa" que una característica oculta, aunque hay formas en que podría usarse como una sola, usar este método no sería una buena idea.
davenpcj 03 de
Eclipse emite una advertencia si haces esto. Estoy con Eclipse Si quieres atrapar una excepción ... entonces atrapa una excepción.
helios
Eso es lo que paga por el código sucio que regresa de la mitad del método. Pero sigue siendo un buen ejemplo.
Rostislav Matl
141

No he visto a nadie mencionar la instancia de implementación de tal manera que no sea necesario verificar nulo.

En vez de:

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

Solo usa:

if( aObject instanceof String )
{
    ...
}
Cadet Pirx
fuente
99
Es una pena que esta sea una característica tan poco conocida. He visto mucho código similar al primer bloque de código.
Peter Dolberg
44
Esto se debe a que Java tiene un tipo nulo especial (oculto) que no ve ni puede hacer referencia.
Nick Hristov
Lo que es peor es buscar nulos antes freede deleteingresar en C / C ++. Un concepto tan fundamental.
Thomas Eding
134

Permitir métodos y constructores en enumeraciones me sorprendió. Por ejemplo:

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

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

Incluso puede tener un "cuerpo de clase específico constante" que permite que un valor enum específico anule los métodos.

Más documentación aquí .

Adrian Mouat
fuente
20
Realmente, una característica realmente impresionante: convierte las enumeraciones en OO y resuelve muchos problemas de inicialización de una manera muy limpia.
Bill K
55
Enum como singleton? Enum con un solo valor?
Georgy Bolyuba
66
Georgy: Singleton es una instancia del objeto, no un objeto con un valor.
dshaw
20
@Georgy: ver también el Artículo 3 en Joshua Bloch's Effective Java (2nd ed); "Si bien este enfoque aún no se ha adoptado ampliamente, un tipo de enumeración de un solo elemento es la mejor manera de implementar un singleton".
Jonik
3
Nitpick menor: mAgedebe ser final. Rara vez hay una razón para los tipos no finales en las enumeraciones.
Joachim Sauer el
121

Los parámetros de tipo para métodos genéricos se pueden especificar explícitamente de la siguiente manera:

Collections.<String,Integer>emptyMap()
Kevin Wong
fuente
10
Y por dios es feo y confuso. E irrelevante para escribir la seguridad.
Chris Broadfoot
8
Me encanta esto. Hace que su código sea un poco más explícito y, como tal, más claro para el pobre pobre que tendrá que mantenerlo en uno o dos años.
extraneon
66
Esto es realmente muy útil en situaciones en las que ha declarado un método genérico estático como public static <T> T foo(T t). Luego puede hacer llamadas aClass.<Type>foo(t);
Finbarr
Por alguna razón, esto no parece funcionar con métodos importados estáticamente. Me pregunto por qué.
oksayt
Esto es especialmente útil cuando se usan ifs ternarios con un retorno. Por ejemplo return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList(). También es útil para algunas invocaciones de métodos donde un simple Collections.emptyMap () daría un error de compilación.
Andreas Holstenson
112

Puede usar enumeraciones para implementar una interfaz.

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

EDITAR: Años después ...

Yo uso esta función aquí

public enum AffinityStrategies implements AffinityStrategy {

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

Al usar una interfaz, los desarrolladores pueden definir sus propias estrategias. Usando un enummedio, puedo definir una colección (de cinco) integradas.

rev. Peter Lawrey
fuente
27
Esto es una locura. (+1)
Cefalópodo
12
@Arian, esto no es una locura. ESTA. ES. JAVAAAAAAHHHH!
slezica
1
WHAAAAAT no, estoy con Adrian. Esto no es Java. Esto es una locura. Me muero por usar esto.
slezica
104

A partir de Java 1.5, Java ahora tiene una sintaxis mucho más limpia para escribir funciones de aridad variable. Entonces, en lugar de simplemente pasar una matriz, ahora puede hacer lo siguiente

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

bars se convierte automáticamente en una matriz del tipo especificado. No es una gran victoria, pero una victoria no obstante.

Paul Wicks
fuente
23
Lo importante de esto es cuando se llama al método, puede escribir: foo ("primero", "segundo", "tercero")
Steve Armstrong
99
para que el viejo mundo hola pueda ser reescrito; public static void main (String ... args) {System.out.println ("¡Hola Mundo!"); }
Karussell
@Karussell Quizás, pero parece que los argumentos son irrelevantes: p
Kelly Elton
93

Mi favorito: volcar todos los rastros de la pila de hilos a la salida estándar.

windows: CTRL- Breaken su ventana de cmd / consola java

unix: kill -3 PID

Chris Mazzola
fuente
15
También ctrl- \ en Unix. O use jstack del JDK.
Tom Hawtin - tackline
99
Gracias, me acabas de enseñar que mi teclado tiene una Breaktecla.
Amy B
2
En Windows, CTRL-BREAK solo funciona si tiene el proceso ejecutándose en la ventana actual de la consola. Puede usar JAVA_HOME / bin / jstack.exe en su lugar. Simplemente proporcione la identificación del proceso de Windows.
Javid Jamae
Pensé que era matar -SIGQUIT
Nick Hristov
@ Nick, sí, SIGQUIT suele ser la señal n. ° 3.
Chris Mazzola
89

Un par de personas han publicado sobre inicializadores de instancias, aquí hay un buen uso:

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

Es una forma rápida de inicializar mapas si solo está haciendo algo rápido y simple.

O usándolo para crear un prototipo de marco de giro rápido:

JFrame frame = new JFrame();

JPanel panel = new JPanel(); 

panel.add( new JLabel("Hey there"){{ 
    setBackground(Color.black);
    setForeground( Color.white);
}});

panel.add( new JButton("Ok"){{
    addActionListener( new ActionListener(){
        public void actionPerformed( ActionEvent ae ){
            System.out.println("Button pushed");
        }
     });
 }});


 frame.add( panel );

Por supuesto que se puede abusar de él:

    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
fuente
De alguna manera, es un poco como si se hubiera agregado a Java la palabra clave "con" (funcionalidad) Puede ser muy útil, recientemente gruñí porque el inicio de matrices no estaba disponible para Colecciones. ¡Gracias!
PhiLho
15
Sin embargo, hay un efecto secundario de usar esto. Se crean objetos anónimos, que pueden no estar bien siempre.
amit
17
Aunque después de mirarlo más, debo decir que me atrae extrañamente la anidación natural que esto proporciona, incluso la versión "Abusada".
Bill K
44
Sí, me gusta bastante la versión 'abusada', creo que es realmente muy clara y legible, pero tal vez solo soy yo.
Barryred
3
Absolutamente de acuerdo, la jerarquía del código que refleja la jerarquía de la interfaz gráfica de usuario es una gran mejora sobre una secuencia de llamadas a métodos.
opsb
88

Los proxys dinámicos (agregados en 1.3) le permiten definir un nuevo tipo en tiempo de ejecución que se ajusta a una interfaz. Ha sido útil una cantidad sorprendente de veces.

jodonnell
fuente
10
Los proxys dinámicos son una gran razón para elegir escribir una interfaz Foo y usarla en todas partes, con una clase predeterminada "FooImpl". Puede parecer feo al principio ("¿Por qué no solo tener una clase llamada Foo?") Pero los beneficios en términos de flexibilidad futura y capacidad de prueba para las pruebas unitarias son útiles. Si bien hay formas de hacerlo también sin interfaces, generalmente requieren cosas adicionales como cblib.
Darien
82

La inicialización final puede posponerse.

Se asegura de que, incluso con un flujo complejo de lógica, siempre se establezcan valores de retorno. Es demasiado fácil perder un caso y volver nulo por accidente. No hace que la devolución sea nula imposible, solo es obvio que es a propósito:

public Object getElementAt(int index) {
    final Object element;
    if (index == 0) {
         element = "Result 1";
    } else if (index == 1) {
         element = "Result 2";
    } else {
         element = "Result 3";
    }
    return element;
}
Allain Lalonde
fuente
Eso es sorprendente ¿Se puede decir con justicia: "El valor de una variable final se puede establecer una vez", sin importar dónde ocurra el conjunto?
David Koelle
29
Sí, pero más fuertemente: "El valor de una variable final debe establecerse una vez"
Allain Lalonde
66
+1 De acuerdo, esta es otra herramienta valiosa para detectar errores en tiempo de compilación, y una que los programadores parecen tímidos de usar por alguna razón. Tenga en cuenta que debido a que desde Java 5 en adelante, 'final' también tiene implicaciones de seguridad de subprocesos, poder establecer una variable final durante el constructor es invaluable.
Neil Coffey
44
Aunque para este método específico, solo usaría múltiples retornos. De hecho, en la mayoría de los casos donde esto es aplicable, probablemente lo refactorizaría en un método separado y usaría múltiples retornos.
ripper234
¡Me encanta esto! Eliminé la palabra clave final siempre porque pensé que fallaría. ¡Gracias!
KARASZI István
62

Creo que otra característica "pasada por alto" de Java es la propia JVM. Es probablemente la mejor máquina virtual disponible. Y es compatible con muchos idiomas interesantes y útiles (Jython, JRuby, Scala, Groovy). Todos esos idiomas pueden cooperar fácilmente y sin problemas.

Si diseña un nuevo idioma (como en el caso scala), inmediatamente tiene todas las bibliotecas existentes disponibles y, por lo tanto, su idioma es "útil" desde el principio.

Todos esos idiomas hacen uso de las optimizaciones de HotSpot. La VM está muy bien supervisada y puede depurarse.

Mes.
fuente
18
No. En realidad no es una muy buena VM. Fue diseñado exclusivamente para ejecutar JAVA. Los lenguajes dinámicos y funcionales sin tipo no funcionan bien con él. Si desea usar una VM, debe usar .NET / Mono. Que fue diseñado para trabajar con el lenguaje CADA ...
Hades32
14
En realidad, la JVM está diseñada exclusivamente para ejecutar códigos de bytes Java. Puede compilar la mayoría de los lenguajes modernos a Java Bytecode. Casi lo único que le falta a Java Bytecode es el soporte de lenguaje dinámico, punteros y soporte de recursión de cola.
mcjabberz
12
@ Hades32: en realidad .NET VM es bastante similar a la JVM. Solo recibió soporte para lenguajes dinámicos relativamente recientemente (con el DLR) y Java 7 está a punto de obtener ese soporte también. Y el clásico "CADA lenguaje" de .NET (C #, Visual Basic.NET, ...) tienen casi exactamente el mismo conjunto de características.
Joachim Sauer el
13
JVM no admite genéricos, mientras que .NET VM sí. JVM no está cerca de lo mejor.
Blindy el
3
No descarto las quejas sobre características de lenguaje específicas que no son compatibles directamente con la JVM ... pero tiendo a pensar que la estabilidad, la coherencia multiplataforma y el buen rendimiento son muy superiores a las razones por las que la JVM obtiene puntos adicionales. He estado trabajando con Java del lado del servidor durante muchos años en muchas plataformas (incluido AS / 400) y he podido olvidarlo por completo: los errores están casi siempre en el código que puedo solucionar, y simplemente no se bloquea.
Rob Whelan
58

Puede definir una subclase anónima y llamar directamente a un método incluso si no implementa interfaces.

new Object() {
  void foo(String s) {
    System.out.println(s);
  }
}.foo("Hello");
Ron
fuente
@Vuntic: le permite definir una clase simple dentro del contexto que se necesita.
ChaosPandion
1
@Chaos, pero ¿por qué? ¿Tienes un ejemplo real donde es útil?
Thorbjørn Ravn Andersen
10
@Wouter: en ese caso, el método que se invoca en el objeto anónimo ( start()) no está realmente definido en la subclase ...
Axel
En realidad, esta es una característica muy útil si extiende una clase base que realiza la configuración necesaria, llama al método que escribe y luego desmonta. Comienza el proceso llamando a un método en la clase base (que probablemente no daría el mismo nombre). Hay un ejemplo de uso (no definición) aquí
AmigoNico
56

El método asListjava.util.Arrays permite una buena combinación de varargs, métodos genéricos y autoboxing:

List<Integer> ints = Arrays.asList(1,2,3);
Bruno De Fraine
fuente
15
desea envolver la lista devuelta con un constructor de lista Tamaño de otro modo enteros serán fijos (ya que está respaldado por la matriz)
KitsuneYMG
2
El Arrays.asListtiene la característica inusual que pueda set()elementos, pero no add()o remove(). Por lo tanto, generalmente lo envuelvo en un new ArrayList(...)o en un Collections.unmodifiableList(...), dependiendo de si quiero que la lista sea modificable o no.
Christian Semrau
53

Usar esta palabra clave para acceder a los campos / métodos de contener la clase desde una clase interna. En el ejemplo siguiente, más bien artificial, queremos usar el campo sortAscending de la clase contenedor de la clase interna anónima. Usar ContainerClass.this.sortAscending en lugar de this.sortAscending hace el truco.

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
fuente
44
Eso solo es necesario si ha sombreado el nombre (en su caso, con el nombre del parámetro del método). Si hubiera llamado al argumento de otra manera, podría acceder directamente a la variable de miembro sortAscending de la clase Container sin usar 'this'.
sk.
77
Todavía es útil tener una referencia a la clase adjunta, por ejemplo. si necesita pasarlo a algún método o constructor.
PhiLho
A menudo se usa en el desarrollo de diseño de Android, para obtener el Contexto de, digamos, el oyente de un botón, con MyActivity.this.
espinchi
52

No es realmente una característica, sino un truco divertido que descubrí recientemente en alguna página web:

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

    System.exit(0);
  }
}

es un programa Java válido (aunque genera una advertencia). Si no ves por qué, ¡mira la respuesta de Gregory! ;-) Bueno, el resaltado de sintaxis aquí también da una pista.

PhiLho
fuente
15
ordenado, una etiqueta con un comentario :)
Thorbjørn Ravn Andersen
46

Esto no es exactamente "características ocultas" y no es muy útil, pero puede ser extremadamente interesante en algunos casos:
Clase sun.misc.Unsafe - le permitirá implementar la administración directa de memoria en Java (incluso puede escribir código Java auto modificable con esto si intentas mucho):

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
fuente
20
esa es una API sun. * que no es realmente parte del lenguaje Java per se
DW.
Hay una serie de otros métodos curiosos en Inseguro, como crear un objeto sin llamar a un constructor, métodos de estilo malloc / realloc / free.
Peter Lawrey
Me encantan especialmente los captadores y establecedores primitivos en ubicaciones de memoria, como putDouble (dirección larga, doble d).
Daniel
42

Cuando se trabaja en oscilación me gusta la escondida Ctrl- Shift- F1función.

Vuelca el árbol de componentes de la ventana actual.
(Suponiendo que no ha vinculado esa pulsación de tecla a otra cosa).

Devon_C_Miller
fuente
1
Lo más probable es que su administrador de ventanas tenga algo relacionado con esa clave. Gnome no se une a él, así que supongo que está ejecutando KDE, que lo vincula para 'cambiar al escritorio 13'. Puede cambiarlo yendo al Panel de control, Regional, Atajos de teclado y eliminando la asignación para Shift-Ctrl-F1
Devon_C_Miller
40

Cada archivo de clase comienza con el valor hexadecimal 0xCAFEBABE para identificarlo como código de bytes JVM válido.

( Explicación )

Dolph
fuente
38

Mi voto va a java.util.concurrent con sus colecciones concurrentes y ejecutores flexibles que permiten, entre otros, grupos de subprocesos, tareas programadas y tareas coordinadas. El DelayQueue es mi favorito personal, donde los elementos están disponibles después de un retraso específico.

java.util.Timer y TimerTask se pueden poner en reposo de forma segura.

Además, no está exactamente oculto sino en un paquete diferente de las otras clases relacionadas con la fecha y la hora. java.util.concurrent.TimeUnit es útil al convertir entre nanosegundos, microsegundos, milisegundos y segundos.

Se lee mucho mejor que el habitual someValue * 1000 o someValue / 1000.

stili
fuente
Recientemente descubierto CountDownLatchy CyclicBarrier- por lo útil!
Raphael
37

Palabra clave de afirmación a nivel de idioma .

Mark Cidade
fuente
19
El problema con afirmar es que debe activarse durante el tiempo de ejecución.
extraneon
10
Pero si está desactivado, es como si no estuviera allí. Puede agregar tantas afirmaciones como desee en su código y no tendrá ninguna penalización de rendimiento si están deshabilitadas.
Ravi Wallau
55
Creo que eso es bueno acerca de afirmar: se puede desactivar sin penalización.
andref
el problema es que si accidentalmente implementó un efecto secundario en una afirmación, debe activar la afirmación para que su programa funcione ...
Chii
Para detectar si las afirmaciones están activadas, puede usar {boolean assertsOn = false; afirmar asertacionesEn = verdadero; if (assertsOn) {/ * verificación compleja * /}}. Esto también permite registrar o lanzar una excepción si el estado de aserción no es el esperado.
fernacolo
37

No es realmente parte del lenguaje Java, pero el desensamblador de Java que viene con JDK de Sun no es ampliamente conocido ni utilizado.

Binil Thomas
fuente
36

La adición de la construcción de bucle for-each en 1.5. Yo <3 lo.

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

Y se puede usar en instancias anidadas:

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

La construcción para cada también es aplicable a las matrices, donde oculta la variable de índice en lugar del iterador. El siguiente método devuelve la suma de los valores en una matriz int:

// Returns the sum of the elements of a
int sum(int[] a) {
  int result = 0;
  for (int i : a)
    result += i;
  return result;
}

Enlace a la documentación de Sun

18 Conejo
fuente
30
Creo que usar iaquí es muy confuso, ya que la mayoría de la gente espera que yo sea un índice y no el elemento de matriz.
cdmckay
Entonces ... int sum (int [] array) {int result = 0; for (int element: array) {result + = element; } resultado devuelto; }
Drew
28
Lo único que me vuelve loco es que parece que sería realmente fácil crear una palabra clave para acceder al valor de conteo de bucles, pero no puede. Si quiero recorrer dos matrices y hacer cambios a una segunda en función de los valores de la primera, me veo obligado a usar la sintaxis anterior porque no tengo compensación en la segunda matriz.
Jherico
66
Es una pena que no funcione también con Enumeraciones, como las que se usan en JNDI. Está de vuelta a los iteradores allí.
extraneon
3
@extraneon: eche un vistazo a Collections.list (Enumeración <T> e). Eso debería ayudar con las enumeraciones iterativas en el bucle foreach.
Werner Lehmann
34

Descubrí personalmente java.lang.Voidmuy tarde: mejora la legibilidad del código junto con los genéricos, p. ej.Callable<Void>

Rahel Lüthy
fuente
2
no exactamente. en algún momento, debe ser específico: Executors.newSingleThreadExecutor (). submit (new Callable <Void> () {..}) - no puede crear una instancia de Callable <?> (), debe especificar un tipo explícito, por lo tanto, es una alternativa a Callable <Object>.
Rahel Lüthy
44
Void es más específico que Object ya que Void solo puede ser nulo, Object puede ser cualquier cosa.
Peter Lawrey