Nachdem ich die versteckten Funktionen von C # gelesen hatte, fragte ich mich: Was sind einige der versteckten Funktionen von Java?
Nachdem ich die versteckten Funktionen von C # gelesen hatte, fragte ich mich: Was sind einige der versteckten Funktionen von Java?
Antworten:
Die Doppelklammer-Initialisierung hat mich vor einigen Monaten überrascht, als ich sie zum ersten Mal entdeckte und noch nie davon gehört habe.
ThreadLocals sind normalerweise nicht so weit verbreitet, um den Status pro Thread zu speichern.
Da in JDK 1.5 Java äußerst gute und robuste Parallelitätstools vorhanden sind, die über Sperren hinausgehen, befinden sie sich in java.util.concurrent. Ein besonders interessantes Beispiel ist das Unterpaket java.util.concurrent.atomic , das thread-sichere Grundelemente enthält, die den Vergleich implementieren -und-Swap- Vorgang und kann tatsächlichen nativen hardwareunterstützten Versionen dieser Vorgänge zugeordnet werden.
Gemeinsame Vereinigung in der Varianz der Typparameter:
public class Baz<T extends Foo & Bar> {}
Wenn Sie beispielsweise einen Parameter verwenden möchten, der sowohl vergleichbar als auch eine Sammlung ist:
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);
}
Diese erfundene Methode gibt true zurück, wenn die beiden angegebenen Sammlungen gleich sind oder wenn eine von ihnen das angegebene Element enthält, andernfalls false. Beachten Sie, dass Sie für die Argumente b1 und b2 Methoden von Comparable und Collection aufrufen können.
Ich war neulich von Instanzinitialisierern überrascht. Ich habe einige Code-Folded-Methoden gelöscht und am Ende mehrere Instanzinitialisierer erstellt:
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");
}
}
Wenn Sie die main
Methode ausführen , wird Folgendes angezeigt:
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
Ich denke, diese wären nützlich, wenn Sie mehrere Konstruktoren hätten und gemeinsamen Code benötigen würden
Sie bieten auch syntaktischen Zucker zum Initialisieren Ihrer Klassen:
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 + enthält eine App namens VisualVM (bin / jvisualvm.exe), die eine nette GUI über vielen Tools ist. Es scheint umfassender als JConsole.
Platzhalter für Klassenpfade seit Java 6.
java -classpath ./lib/* so.Main
Anstatt
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Siehe http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Für die meisten Leute, die ich für Java-Entwicklerpositionen interviewe, sind mit Blöcken gekennzeichnete Blöcke sehr überraschend. Hier ist ein Beispiel:
// 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;
}
}
}
}
Wer hat goto
in Java gesagt, ist nur ein Schlüsselwort? :) :)
Wie wäre es mit kovarianten Rückgabetypen, die seit JDK 1.5 vorhanden sind? Es ist ziemlich schlecht bekannt, da es eine unsexy Ergänzung ist, aber wie ich es verstehe, ist es absolut notwendig, dass Generika funktionieren.
Im Wesentlichen erlaubt der Compiler jetzt einer Unterklasse, den Rückgabetyp einer überschriebenen Methode auf eine Unterklasse des Rückgabetyps der ursprünglichen Methode zu beschränken. Das ist also erlaubt:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Sie können die die Unterklasse aufrufen values
Verfahren und eine sortierte Thread - sicher erhalten Set
von String
s , ohne nach unten gegossen, die auf die ConcurrentSkipListSet
.
Die Übertragung der Kontrolle in einem finally-Block wirft jede Ausnahme weg. Der folgende Code löst keine RuntimeException aus - er geht verloren.
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;
}
}
Von http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Ich habe noch niemanden gesehen, der eine Instanz der Implementierung so erwähnt hat, dass eine Überprüfung auf Null nicht erforderlich ist.
Anstatt:
if( null != aObject && aObject instanceof String )
{
...
}
benutz einfach:
if( aObject instanceof String )
{
...
}
free
ing oder delete
ing in C / C ++. Solch ein grundlegendes Konzept.
Das Zulassen von Methoden und Konstruktoren in Aufzählungen hat mich überrascht. Zum Beispiel:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Sie können sogar einen "konstanten spezifischen Klassenkörper" haben, der es einem bestimmten Enum-Wert ermöglicht, Methoden zu überschreiben.
Weitere Dokumentation hier .
mAge
sollte endgültig sein. Es gibt selten einen Grund für nicht endgültige Felder in Aufzählungen.
Die Typparameter für generische Methoden können explizit wie folgt angegeben werden:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
. Sie können dann anrufenClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Dies ist auch nützlich für einige Methodenaufrufe, bei denen eine einfache Collections.emptyMap () einen Kompilierungsfehler ergibt.
Sie können Aufzählungen verwenden, um eine Schnittstelle zu implementieren.
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: Jahre später ....
Ich benutze diese Funktion hier
public enum AffinityStrategies implements AffinityStrategy {
Mithilfe einer Schnittstelle können Entwickler ihre eigenen Strategien definieren. Mit einem enum
Mittel kann ich eine Sammlung von fünf integrierten definieren.
Ab Java 1.5 verfügt Java nun über eine viel sauberere Syntax zum Schreiben von Funktionen mit variabler Arität. Anstatt nur ein Array zu übergeben, können Sie jetzt Folgendes tun
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
Balken werden automatisch in ein Array des angegebenen Typs konvertiert. Kein großer Gewinn, aber dennoch ein Gewinn.
Mein Favorit: Alle Thread-Stack-Traces auf Standard ausgeben.
Windows: CTRL- BreakIn Ihrem Java-Cmd / Konsolenfenster
Unix: kill -3 PID
Break
Taste hat.
Einige Leute haben über Instanzinitialisierer geschrieben. Hier ist eine gute Verwendung dafür:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
Ist eine schnelle Möglichkeit, Karten zu initialisieren, wenn Sie nur schnell und einfach etwas tun.
Oder verwenden Sie es, um einen schnellen Swing-Frame-Prototyp zu erstellen:
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 );
Natürlich kann es missbraucht werden:
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");
}
});
}});
}});
}};
Mit dynamischen Proxys (hinzugefügt in 1.3) können Sie zur Laufzeit einen neuen Typ definieren, der einer Schnittstelle entspricht. Es hat sich überraschend oft als nützlich erwiesen.
Die endgültige Initialisierung kann verschoben werden.
Es stellt sicher, dass auch bei einem komplexen Fluss logischer Rückgabewerte immer Werte festgelegt werden. Es ist zu leicht, einen Fall zu übersehen und versehentlich null zurückzugeben. Es macht es nicht unmöglich, null zurückzugeben, nur offensichtlich, dass es absichtlich ist:
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;
}
Ich denke, ein weiteres "übersehenes" Feature von Java ist die JVM selbst. Es ist wahrscheinlich die beste verfügbare VM. Und es unterstützt viele interessante und nützliche Sprachen (Jython, JRuby, Scala, Groovy). Alle diese Sprachen können einfach und nahtlos zusammenarbeiten.
Wenn Sie eine neue Sprache entwerfen (wie im Scala-Fall), stehen Ihnen sofort alle vorhandenen Bibliotheken zur Verfügung, und Ihre Sprache ist daher von Anfang an "nützlich".
Alle diese Sprachen nutzen die HotSpot-Optimierungen. Die VM ist sehr gut zu überwachen und zu debuggen.
Sie können eine anonyme Unterklasse definieren und direkt eine Methode darauf aufrufen, auch wenn keine Schnittstellen implementiert sind.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) aufgerufen wird, nicht in der Unterklasse definiert ...
Die asList- Methode in java.util.Arrays
ermöglicht eine schöne Kombination von Varargs, generischen Methoden und Autoboxing:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
hat die ungewöhnliche Funktion, dass Sie set()
Elemente aber nicht add()
oder können remove()
. Daher wickle ich es normalerweise in ein new ArrayList(...)
oder in ein Collections.unmodifiableList(...)
, je nachdem, ob die Liste geändert werden soll oder nicht.
Verwenden dieses Schlüsselworts für den Zugriff auf Felder / Methoden zum Enthalten von Klassen aus einer inneren Klasse. Im folgenden, eher konstruierten Beispiel möchten wir das sortAscending-Feld der Containerklasse aus der anonymen inneren Klasse verwenden. Die Verwendung von ContainerClass.this.sortAscending anstelle von this.sortAscending reicht aus.
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
.
Nicht wirklich eine Funktion, aber ein amüsanter Trick, den ich kürzlich auf einer Webseite entdeckt habe:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
ist ein gültiges Java-Programm (obwohl es eine Warnung generiert). Wenn Sie nicht verstehen, warum, lesen Sie Gregorys Antwort! ;-) Nun, die Syntaxhervorhebung hier gibt auch einen Hinweis!
Dies ist nicht gerade "versteckte Funktionen" und nicht sehr nützlich, kann aber in einigen Fällen äußerst interessant sein:
Klasse sun.misc.Unsafe - ermöglicht die Implementierung der direkten Speicherverwaltung in Java (Sie können sogar selbstmodifizierenden Java-Code mit schreiben dies, wenn Sie viel versuchen):
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);
}
};
}
Wenn ich in Swing arbeite, mag ich die versteckte Ctrl- Shift- F1Funktion.
Der Komponentenbaum des aktuellen Fensters wird ausgegeben.
(Angenommen, Sie haben diesen Tastendruck nicht an etwas anderes gebunden.)
Meine Stimme geht an java.util.concurrent mit seinen gleichzeitigen Sammlungen und flexiblen Ausführenden, die unter anderem Thread-Pools, geplante Aufgaben und koordinierte Aufgaben ermöglichen. Die DelayQueue ist mein persönlicher Favorit, bei dem Elemente nach einer bestimmten Verzögerung verfügbar gemacht werden.
java.util.Timer und TimerTask können sicher zur Ruhe gesetzt werden.
Auch nicht genau versteckt, sondern in einem anderen Paket als die anderen Klassen in Bezug auf Datum und Uhrzeit. java.util.concurrent.TimeUnit ist nützlich beim Konvertieren zwischen Nanosekunden, Mikrosekunden, Millisekunden und Sekunden.
Es liest sich viel besser als der übliche someValue * 1000 oder someValue / 1000.
CountDownLatch
und CyclicBarrier
- so nützlich!
Sprachebene assert Stichwort.
Nicht wirklich Teil der Java-Sprache, aber der Javap-Disassembler, der mit Suns JDK geliefert wird, ist nicht allgemein bekannt oder wird nicht verwendet.
Die Hinzufügung des for-each-Schleifenkonstrukts in 1.5. Ich <3 es.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
Und kann in verschachtelten Instanzen verwendet werden:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
Das for-each-Konstrukt gilt auch für Arrays, in denen die Indexvariable und nicht der Iterator ausgeblendet werden. Die folgende Methode gibt die Summe der Werte in einem int-Array zurück:
// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}
i
hier ist sehr verwirrend, da die meisten Leute erwarten, dass ich ein Index und nicht das Array-Element bin .
Ich persönlich habe es java.lang.Void
sehr spät entdeckt - verbessert die Lesbarkeit des Codes in Verbindung mit Generika, zCallable<Void>