Po przeczytaniu ukrytych funkcji języka C # zastanawiałem się, jakie są niektóre z ukrytych funkcji Java?
Po przeczytaniu ukrytych funkcji języka C # zastanawiałem się, jakie są niektóre z ukrytych funkcji Java?
Odpowiedzi:
Inicjacja Double Brace zaskoczyła mnie kilka miesięcy temu, kiedy ją odkryłem, nigdy wcześniej o niej nie słyszałem.
ThreadLocals zazwyczaj nie są tak powszechnie znane jako sposób przechowywania stanu poszczególnych wątków.
Ponieważ JDK 1.5 Java ma wyjątkowo dobrze zaimplementowane i niezawodne narzędzia do współbieżności poza blokadami, znajdują się one w java.util.concurrent, a szczególnie interesującym przykładem jest java.util.concurrent.atomic podpakiet zawierający bezpieczne dla wątków operacje podstawowe, które implementują porównanie -i-swap operacji i może mapować do rzeczywistych obsługiwanych sprzętowo wersji tych operacji.
Łączna zmienność parametru typu:
public class Baz<T extends Foo & Bar> {}
Na przykład, jeśli chcesz wziąć parametr, który jest zarówno Porównywalny, jak i Kolekcja:
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);
}
Ta wymyślona metoda zwraca wartość true, jeśli dwie podane kolekcje są równe lub jeśli jedna z nich zawiera dany element, w przeciwnym razie fałsz. Należy zauważyć, że można wywoływać metody zarówno Porównywalne, jak i Kolekcji na argumentach b1 i b2.
Byłem zaskoczony inicjatorami instancji innego dnia. Usunąłem niektóre złożone metody i ostatecznie utworzyłem wiele inicjatorów instancji:
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");
}
}
Wykonanie main
metody wyświetli:
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
Sądzę, że byłyby przydatne, gdybyś miał wiele konstruktorów i potrzebował wspólnego kodu
Zapewniają również cukier składniowy do inicjowania twoich zajęć:
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 + zawiera aplikację o nazwie VisualVM (bin / jvisualvm.exe), która jest przyjemnym GUI na wielu narzędziach. Wydaje się bardziej wszechstronny niż JConsole.
Dzikie karty Classpath od Java 6.
java -classpath ./lib/* so.Main
Zamiast
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Zobacz http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Dla większości osób, z którymi przeprowadzam wywiady dla stanowisk programistów Java, bloki oznaczone jako zaskakujące. Oto przykład:
// 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;
}
}
}
}
Kto powiedział, że goto
w java to tylko słowo kluczowe? :)
A co z typami zwrotów kowariantnych które obowiązywały od JDK 1.5? Jest dość słabo nagłośniony, ponieważ jest nieprzyzwoitym dodatkiem, ale jak rozumiem, jest absolutnie niezbędny do działania leków generycznych.
Zasadniczo kompilator pozwala teraz podklasie zawęzić typ zwracany przez przesłoniętą metodę, aby była podklasą typu zwracanego przez oryginalną metodę. Jest to dozwolone:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Możesz wywołać values
metodę podklasy i otrzymać posortowany wątek bezpieczny Set
od String
s bez konieczności rzutowania do ConcurrentSkipListSet
.
Przeniesienie kontroli w bloku ostatecznie odrzuca każdy wyjątek. Poniższy kod nie zgłasza wyjątku RuntimeException - został utracony.
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;
}
}
From http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Nie widziałem, żeby ktoś wspominał wystąpienie implementacji w taki sposób, że sprawdzanie wartości null nie jest konieczne.
Zamiast:
if( null != aObject && aObject instanceof String )
{
...
}
po prostu użyj:
if( aObject instanceof String )
{
...
}
free
ing lub delete
ing w C / C ++. Taka podstawowa koncepcja.
Zezwalanie na metody i konstruktorów w wyliczeniach zaskoczyło mnie. Na przykład:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Możesz nawet mieć „stałe określone ciało klasy”, które pozwala określonej wartości wyliczeniowej zastąpić metody.
Więcej dokumentacji tutaj .
mAge
powinien być ostateczny. Rzadko jest powód, dla którego nieumiejętności są w wyliczeniach.
Parametry typu dla metod ogólnych można jawnie określić w następujący sposób:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
. Możesz wtedy dzwonić doClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Przydaje się również w przypadku niektórych wywołań metod, w których prosta kolekcja.emptyMap () dawałaby błąd kompilacji.
Możesz użyć wyliczeń, aby zaimplementować interfejs.
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; }
}
EDYCJA: Lata później ....
Korzystam z tej funkcji tutaj
public enum AffinityStrategies implements AffinityStrategy {
Korzystając z interfejsu, programiści mogą definiować własne strategie. Za pomocą enum
środków mogę zdefiniować kolekcję (pięciu) wbudowanych.
Począwszy od Java 1.5, Java ma teraz znacznie bardziej przejrzystą składnię do pisania funkcji o różnym arity. Zamiast więc przekazywać tablicę, teraz możesz wykonać następujące czynności
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
słupki są automatycznie konwertowane na tablicę określonego typu. Nie jest to wielka wygrana, ale mimo to wygrana.
Moje ulubione: zrzuć wszystkie ślady stosu nici na standardowe wyjście.
windows: CTRL- Breakw twoim oknie Java CdD / konsoli
unix: kill -3 PID
Break
klawisz.
Kilka osób napisało o inicjatorach instancji, oto dobre zastosowanie:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
To szybki sposób na inicjalizację map, jeśli robisz coś szybko i prosto.
Lub używając go do stworzenia prototypu szybkiej ramy wychylnej:
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 );
Oczywiście można go nadużywać:
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");
}
});
}});
}});
}};
Dynamiczne proxy (dodane w 1.3) pozwalają zdefiniować nowy typ w czasie wykonywania, który jest zgodny z interfejsem. Przydaje się zaskakująco wiele razy.
ostateczna inicjalizacja może zostać odroczona.
Zapewnia to, że nawet przy złożonym przepływie logiki zwracane są zawsze wartości. Zbyt łatwo przeoczyć skrzynkę i przez przypadek zwrócić wartość zerową. Nie uniemożliwia powrotu wartości null, po prostu oczywiste, że jest to celowe:
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;
}
Myślę, że inną „przeoczoną” cechą Java jest sama JVM. Jest to prawdopodobnie najlepsza dostępna maszyna wirtualna. Obsługuje wiele interesujących i przydatnych języków (Jython, JRuby, Scala, Groovy). Wszystkie te języki mogą łatwo i bezproblemowo współpracować.
Jeśli projektujesz nowy język (jak w przypadku Scala), natychmiast dostępne są wszystkie istniejące biblioteki, a zatem Twój język jest „użyteczny” od samego początku.
Wszystkie te języki korzystają z optymalizacji HotSpot. Maszyna wirtualna jest bardzo dobrze monitorowana i debugowana.
Możesz zdefiniować anonimową podklasę i bezpośrednio wywołać na niej metodę, nawet jeśli nie implementuje ona żadnych interfejsów.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) nie jest tak naprawdę zdefiniowana w podklasie ...
AsList metoda java.util.Arrays
umożliwia połączenie miłe z varargs, metod generycznych i autoboxing:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
Ma niezwykłą cechę, że można set()
elementy, ale nie add()
bądź remove()
. Więc zwykle zawijam go w a new ArrayList(...)
lub a Collections.unmodifiableList(...)
, w zależności od tego, czy chcę modyfikować listę, czy nie.
Użycie tego słowa kluczowego do uzyskania dostępu do pól / metod zawierających klasę z klasy wewnętrznej. W poniższym, raczej wymyślonym przykładzie, chcemy użyć pola sortAscending klasy kontenera od anonimowej klasy wewnętrznej. Używanie ContainerClass.this.sortAscending zamiast this.sortAscending załatwia sprawę.
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
.
Nie jest to właściwie funkcja, ale zabawna sztuczka, którą odkryłem niedawno na jakiejś stronie internetowej:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
jest poprawnym programem Java (chociaż generuje ostrzeżenie). Jeśli nie rozumiesz dlaczego, zobacz odpowiedź Gregory'ego! ;-) Podświetlanie składni również daje wskazówkę!
Nie są to do końca „ukryte funkcje” i nie są bardzo przydatne, ale w niektórych przypadkach mogą być niezwykle interesujące:
Klasa sun.misc.Unsafe - pozwoli ci wdrożyć bezpośrednie zarządzanie pamięcią w Javie (możesz nawet napisać samomodyfikujący się kod Java za pomocą jeśli dużo próbujesz):
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);
}
};
}
Podczas pracy w Swing lubię ukryte Ctrl- Shift-F1 funkcja .
Zrzuca drzewo komponentów bieżącego okna.
(Zakładając, że nie związałeś tego naciśnięcia klawisza z czymś innym).
Każdy plik klasy zaczyna się od wartości szesnastkowej 0xCAFEBABE celu zidentyfikowania go jako prawidłowego kodu bajtowego JVM.
( Wyjaśnienie )
Głosuję na java.util.concurrent z jego równoległymi kolekcjami i elastycznymi programami wykonawczymi, umożliwiającymi między innymi pule wątków, zaplanowane zadania i skoordynowane zadania. DelayQueue jest moim osobistym ulubieńcem, w którym elementy są udostępniane po określonym czasie.
java.util.Timer i TimerTask można bezpiecznie zatrzymać.
Nie do końca ukryte, ale w innym pakiecie niż inne klasy związane z datą i godziną. java.util.concurrent.TimeUnit jest przydatny podczas konwersji między nanosekundami, mikrosekundami, milisekundami i sekundami.
Czyta o wiele lepiej niż zwykle someValue * 1000 lub someValue / 1000.
CountDownLatch
i CyclicBarrier
- bardzo przydatne!
Słowo kluczowe aser na poziomie języka .
W rzeczywistości nie jest częścią języka Java, ale dezasembler javap dostarczany z JDK firmy Sun nie jest powszechnie znany ani używany.
Dodanie konstrukcji pętli dla każdego w 1.5. <3 to.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
I może być używany w instancjach zagnieżdżonych:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
Konstrukcja for-each ma również zastosowanie do tablic, w których ukrywa zmienną indeksu zamiast iteratora. Poniższa metoda zwraca sumę wartości w tablicy 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
tutaj jest bardzo mylące, ponieważ większość ludzi oczekuje, że będę indeksem, a nie elementem tablicy.
osobiście odkryłem java.lang.Void
bardzo późno - poprawia czytelność kodu w połączeniu z generycznymi, npCallable<Void>