Setelah membaca Fitur Tersembunyi C # Saya bertanya-tanya, Apa sajakah fitur tersembunyi Java?
Setelah membaca Fitur Tersembunyi C # Saya bertanya-tanya, Apa sajakah fitur tersembunyi Java?
Jawaban:
Inisialisasi Double Brace mengejutkan saya beberapa bulan yang lalu ketika saya pertama kali menemukannya, tidak pernah mendengarnya sebelumnya.
ThreadLocals biasanya tidak begitu dikenal sebagai cara untuk menyimpan status per-utas.
Karena JDK 1.5 Java telah memiliki alat konkurensi yang sangat baik diimplementasikan dan kuat di luar hanya kunci, mereka hidup di java.util.concurrent dan contoh khusus yang menarik adalah subpackage java.util.concurrent.atomic yang berisi primitif thread-safe yang mengimplementasikan perbandingan. -dan-swap operasi dan dapat memetakan ke versi asli yang didukung perangkat keras asli dari operasi ini
Gabungan gabungan dalam varians parameter tipe:
public class Baz<T extends Foo & Bar> {}
Misalnya, jika Anda ingin mengambil parameter yang Sebanding dan Koleksi:
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);
}
Metode yang dibuat ini mengembalikan true jika dua koleksi yang diberikan sama atau jika salah satu dari mereka berisi elemen yang diberikan, jika tidak salah. Poin yang perlu diperhatikan adalah Anda dapat menggunakan metode Comparable and Collection pada argumen b1 dan b2.
Saya terkejut dengan contoh inisialisasi hari lain. Saya menghapus beberapa metode kode-lipat dan akhirnya membuat beberapa inisialisasi contoh:
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");
}
}
Menjalankan main
metode akan menampilkan:
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
Saya kira ini akan berguna jika Anda memiliki banyak konstruktor dan memerlukan kode umum
Mereka juga menyediakan gula sintaksis untuk menginisialisasi kelas Anda:
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 + berisi aplikasi yang disebut VisualVM (bin / jvisualvm.exe) yang merupakan GUI yang bagus di atas banyak alat. Tampaknya lebih komprehensif daripada JConsole.
Kartu liar Classpath sejak Java 6.
java -classpath ./lib/* so.Main
Dari pada
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Lihat http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Bagi kebanyakan orang, saya wawancarai untuk posisi pengembang Java yang diberi label blok sangat mengejutkan. Berikut ini sebuah contoh:
// 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;
}
}
}
}
Siapa bilang goto
di java hanya kata kunci? :)
Bagaimana dengan tipe pengembalian kovarian yang sudah ada sejak JDK 1.5? Ini cukup buruk dipublikasikan, karena merupakan tambahan yang tidak seksi, tapi seperti yang saya mengerti, sangat diperlukan bagi obat generik untuk bekerja.
Pada dasarnya, kompiler sekarang memungkinkan subclass untuk mempersempit tipe kembalinya metode overridden menjadi subkelas dari tipe kembalinya metode asli. Jadi ini diperbolehkan:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Anda dapat memanggil metode subclass values
dan mendapatkan thread yang diurutkan aman Set
dari String
s tanpa harus membuang ke bawah ConcurrentSkipListSet
.
Transfer kontrol di blok akhirnya membuang pengecualian. Kode berikut ini tidak membuang RuntimeException - itu hilang.
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;
}
}
Dari http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Belum pernah ada yang menyebutkan contoh implementasi yang sedemikian rupa sehingga memeriksa null tidak diperlukan.
Dari pada:
if( null != aObject && aObject instanceof String )
{
...
}
cukup gunakan:
if( aObject instanceof String )
{
...
}
free
atau delete
di C / C ++. Konsep yang fundamental.
Mengizinkan metode dan konstruktor dalam enum mengejutkan saya. Sebagai contoh:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Anda bahkan dapat memiliki "badan kelas spesifik konstan" yang memungkinkan nilai enum spesifik untuk mengganti metode.
Dokumentasi lebih lanjut di sini .
mAge
harus final. Jarang ada alasan untuk bidang non-final dalam enum.
Jenis params untuk metode generik dapat ditentukan secara eksplisit seperti:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
. Anda kemudian dapat membuat panggilan keClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Ini juga berguna untuk beberapa pemanggilan metode di mana Collections.emptyMap () sederhana akan memberikan kesalahan kompilasi.
Anda dapat menggunakan enums untuk mengimplementasikan antarmuka.
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: Bertahun-tahun kemudian ....
Saya menggunakan fitur ini di sini
public enum AffinityStrategies implements AffinityStrategy {
Dengan menggunakan antarmuka, pengembang dapat menentukan strategi mereka sendiri. Menggunakan enum
sarana saya bisa mendefinisikan koleksi (lima) yang dibangun di dalamnya.
Pada Java 1.5, Java sekarang memiliki sintaks yang lebih bersih untuk fungsi penulisan variabel arity. Jadi, alih-alih hanya meneruskan array, sekarang Anda dapat melakukan hal berikut
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
bilah secara otomatis dikonversi ke larik jenis yang ditentukan. Bukan kemenangan besar, tapi kemenangan.
Favorit saya: buang semua jejak tumpukan benang ke standar keluar.
windows: CTRL- Breakdi jendela java cmd / console Anda
unix: kill -3 PID
Break
kunci.
Beberapa orang telah memposting tentang inisialisasi instance, berikut ini manfaatnya:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
Merupakan cara cepat untuk menginisialisasi peta jika Anda hanya melakukan sesuatu yang cepat dan sederhana.
Atau menggunakannya untuk membuat prototipe bingkai ayunan cepat:
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 );
Tentu saja bisa disalahgunakan:
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");
}
});
}});
}});
}};
Proxy dinamis (ditambahkan dalam 1.3) memungkinkan Anda untuk menentukan tipe baru saat runtime yang sesuai dengan antarmuka. Ini berguna beberapa kali mengejutkan.
inisialisasi akhir dapat ditunda.
Itu memastikan bahwa bahkan dengan aliran logika, nilai-nilai pengembalian selalu ditetapkan. Terlalu mudah untuk melewatkan sebuah kasus dan mengembalikan nol secara tidak sengaja. Itu tidak membuat pengembalian nol menjadi tidak mungkin, hanya jelas bahwa itu sengaja:
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;
}
Saya pikir fitur "diabaikan" lain dari java adalah JVM itu sendiri. Ini mungkin VM terbaik yang tersedia. Dan itu mendukung banyak bahasa yang menarik dan berguna (Jython, JRuby, Scala, Groovy). Semua bahasa itu dapat dengan mudah dan lancar bekerja sama.
Jika Anda mendesain bahasa baru (seperti dalam scala-case), Anda segera memiliki semua perpustakaan yang ada dan bahasa Anda karenanya "berguna" sejak awal.
Semua bahasa itu menggunakan optimasi HotSpot. VM sangat baik dimonitor dan dapat di-debug.
Anda dapat mendefinisikan subkelas anonim dan secara langsung memanggil metode meskipun itu tidak mengimplementasikan antarmuka.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) sebenarnya tidak didefinisikan dalam subkelas ...
The asList metode dalam java.util.Arrays
memungkinkan kombinasi bagus varargs, metode generik dan autoboxing:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
memiliki fitur yang tidak biasa yang dapat Anda set()
elemen tetapi tidak add()
atau remove()
. Jadi saya biasanya membungkusnya dalam new ArrayList(...)
atau dalam Collections.unmodifiableList(...)
, tergantung pada apakah saya ingin daftar dimodifikasi atau tidak.
Menggunakan kata kunci ini untuk mengakses bidang / metode yang mengandung kelas dari kelas dalam. Di bawah, contoh yang agak dibuat-buat, kami ingin menggunakan bidang sortAscending kelas kontainer dari kelas dalam anonim. Menggunakan ContainerClass.this.sortAscending bukan ini.sortAscending melakukan trik.
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
.
Sebenarnya bukan fitur, tetapi trik lucu yang saya temukan baru-baru ini di beberapa halaman Web:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
adalah program Java yang valid (meskipun menghasilkan peringatan). Jika Anda tidak melihat alasannya, lihat jawaban Gregory! ;-) Nah, penyorotan sintaks di sini juga memberikan petunjuk!
Ini bukan "fitur tersembunyi" dan tidak terlalu berguna, tetapi bisa sangat menarik dalam beberapa kasus:
Kelas sun.misc.Unsafe - akan memungkinkan Anda untuk menerapkan manajemen memori langsung di Jawa (Anda bahkan dapat menulis kode Java modifikasi sendiri dengan ini jika Anda mencoba banyak):
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);
}
};
}
Ketika bekerja di Swing, saya suka fitur - Ctrl- tersembunyi .ShiftF1
Itu membuang pohon komponen dari jendela saat ini.
(Anggap saja kamu belum mengikat keystroke itu pada hal lain.)
Setiap file kelas dimulai dengan nilai hex 0xCAFEBABE untuk mengidentifikasinya sebagai bytecode JVM yang valid.
( Penjelasan )
Pilihan saya masuk ke java.util.concurrent dengan koleksi serentak dan pelaksana fleksibel yang memungkinkan antara lain kumpulan utas, tugas terjadwal, dan tugas terkoordinasi. DelayQueue adalah favorit pribadi saya, di mana elemen tersedia setelah penundaan yang ditentukan.
java.util.Timer dan TimerTask dapat dengan aman dimatikan.
Juga, tidak persis tersembunyi tetapi dalam paket yang berbeda dari kelas lain yang terkait dengan tanggal dan waktu. java.util.concurrent.TimeUnit berguna ketika mengkonversi antara nanodetik, mikrodetik, milidetik, dan detik.
Bunyinya jauh lebih baik daripada someValue * 1000 atau someValue / 1000.
CountDownLatch
dan CyclicBarrier
- sangat berguna!
Kata kunci yang menegaskan tingkat bahasa .
Tidak benar-benar bagian dari bahasa Jawa, tetapi disassembler javap yang datang dengan JDK Sun tidak banyak dikenal atau digunakan.
Penambahan konstruksi loop untuk-masing-masing dalam 1,5. Saya <3 itu.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
Dan dapat digunakan dalam instance bersarang:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
Konstruksi untuk-masing-masing juga berlaku untuk array, di mana ia menyembunyikan variabel indeks daripada iterator. Metode berikut mengembalikan jumlah nilai dalam array 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
sini sangat membingungkan, karena kebanyakan orang berharap saya menjadi indeks dan bukan elemen array.
Saya pribadi menemukan java.lang.Void
sangat terlambat - meningkatkan pembacaan kode dalam hubungannya dengan obat generik, misalnyaCallable<Void>