Fitur Tersembunyi di Jawa

295

Setelah membaca Fitur Tersembunyi C # Saya bertanya-tanya, Apa sajakah fitur tersembunyi Java?

grom
sumber
17
Perhatikan bahwa tidak selalu merupakan ide bagus untuk menggunakan fitur-fitur tersembunyi ini; sering kali mereka mengejutkan dan membingungkan orang lain yang membaca kode Anda.
Kevin Bourrillion
1
Anda (/ seseorang) harus meringkas jawaban dengan rapi di badan pertanyaan seperti pertanyaan C #.
ripper234

Jawaban:

432

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

Boris Terzic
sumber
40
Inisialisasi double-brace ... aneh ... Saya akan berhati-hati mengadopsi idiom khusus itu terlalu luas, karena sebenarnya menciptakan subclass anonim objek, yang dapat menyebabkan masalah equals / kode hash yang membingungkan. java.util.concurrent adalah paket yang sangat bagus.
MB.
6
Saya telah mengajar Java, dan ini adalah pertama kalinya saya menemukan sintaks ini ... yang menunjukkan Anda tidak pernah berhenti belajar = 8-)
Yuval
49
Perhatikan bahwa jika Anda mempertahankan referensi ke koleksi yang diinisialisasi dengan idiom "penjepit ganda" ini (atau jika kami menyebutnya dengan nama aslinya - kelas anonim dengan blok penginisialisasi), Anda secara implisit memegang referensi ke objek luar yang dapat menyebabkan memori tidak menyenangkan kebocoran. Saya akan merekomendasikan untuk menghindarinya sama sekali.
ddimitrov
51
"Inisialisasi double-brace" adalah nama yang sangat halus untuk menciptakan kelas batin anonim, menutupi apa yang sebenarnya terjadi dan membuatnya terdengar seolah-olah kelas dalam dimaksudkan untuk digunakan dengan cara ini. Ini adalah pola yang saya inginkan tetap tersembunyi.
erickson
11
Hampir, ini bukan benar-benar sebuah blok statis tetapi sebuah "blok penginisialisasi" yang berbeda karena dijalankan pada waktu yang berbeda (lihat tautan yang saya masukkan dalam jawaban untuk perincian lebih lanjut)
Boris Terzic
279

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.

Apocalisp
sumber
Penggunaan favorit saya untuk ini adalah ketika Anda membutuhkan metode yang menerima Charsequence yang dapat ditambahkan.
Neil Coffey
5
Apakah mungkin untuk memiliki "ATAU" di sana daripada &?
mainstringargs
9
@Grasper: Tidak, ATAU (disjoint union) tidak disediakan dalam konteks itu. Tapi Anda bisa menggunakan tipe data serikat terpisah seperti <A, B> sebagai gantinya. Tipe ini adalah ganda dari tipe Pair <A, B>. Lihatlah perpustakaan Java Fungsional atau perpustakaan inti Scala untuk contoh datatype tersebut.
Apocalisp
5
Anda harus mengatakan bahwa Anda HARUS memperluas hanya satu kelas dan beberapa antarmuka -> kelas publik Baz <T extends Clazz & Interface1 & InterfaceI ... dan bukan class Baz <T extends Clazz1 & ClazzI>
JohnJohnGa
220

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 mainmetode 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");
}};
David Carlson
sumber
38
Keuntungan dari ini daripada metode eksplisit yang perlu dipanggil adalah bahwa jika seseorang menambahkan konstruktor nanti mereka tidak perlu ingat untuk memanggil init (); itu akan dilakukan secara otomatis. Ini dapat mencegah kesalahan oleh programmer masa depan.
Tuan Shiny dan Baru New 宇
40
Juga, tidak seperti metode init (), ia dapat menginisialisasi bidang akhir.
Darron
2
Bagaimana jika Anda memperpanjang kelas dan membuat berbagai anak? Apakah masih akan berlaku sama?
Kezzer
12
Orang sering mengabaikan sertifikasi (mis. Stackoverflow.com/questions/281100/281127#281127 ) dan terutama mempertanyakan keunggulan teknis mereka. Tetapi jika lebih banyak programmer di sini telah belajar untuk SCJP mereka, ini tidak akan dianggap sebagai "fitur tersembunyi" oleh begitu banyak. ;-)
Jonik
12
Saya bertaruh bahkan buku "java in 24 hours" memiliki "fitur yang jelas" ini. baca lebih lanjut
kawan
201

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.

Kevin Wong
sumber
Dan ia memiliki plugin (ini adalah netbeans thingie) yang memungkinkannya untuk menggunakan plugin Jconsole. Cukup bagus.
Thorbjørn Ravn Andersen
VisualVM adalah yang terbaik sejak mengiris roti, sungguh! Sayang sekali itu tidak memiliki semua fitur ketika menjalankan melawan JDK 1.5
sandos
Saya menemukan VisualVM lambat atau tidak dapat digunakan dalam beberapa keadaan. Iklan YourKit tidak memiliki masalah ini, tetapi sayangnya tidak gratis.
Roalt
Versi Visual VM yang lebih baru, dari JDK 1.6.0_22 dan yang lebih baru, jauh lebih baik. Saya berani bertaruh JDK1.7 memiliki versi yang lebih baik lagi.
djangofan
156

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 gotodi java hanya kata kunci? :)

Georgy Bolyuba
sumber
2
Yah, saya lebih suka memiliki opsi untuk melakukannya beberapa cara. Sebagai contoh, saya melihat orang menggunakan System.exit (1); dalam Servlet dan kode EJB, tetapi itu tidak berarti bahwa kita harus menghapus System.exit (); dari JDK, kan?
Georgy Bolyuba
31
Dalam beberapa keadaan, dalam konstruk loop bersarang, dapat berguna untuk melanjutkan ke iterasi berikutnya dari loop luar. Ini akan menjadi penggunaan wajar fitur ini.
alasdairg
75
Apa yang terutama tidak diketahui oleh banyak programmer (dan mungkin juga) adalah bahwa Anda benar-benar dapat memberi label dan keluar dari blok lama APA PUN. Itu tidak harus menjadi sebuah loop - Anda hanya dapat mendefinisikan beberapa blok arbitrer, berikan label, dan gunakan break dengannya.
Neil Coffey
27
Sama sekali bukan goto, ia hanya dapat kembali ke iterasi sebelumnya (yaitu: Anda tidak dapat melompat maju). Ini adalah mekanisme yang sama yang terjadi ketika iterasi mengembalikan false. Mengatakan java memiliki goto seperti mengucapkan bahasa apa pun yang kompilernya menghasilkan instruksi JUMP memiliki pernyataan goto.
Zombies
4
Jadi Anda mewawancarai berdasarkan hal-hal sepele Java daripada pada bakat untuk memecahkan masalah dan memikirkan desain. Saya akan memastikan saya tidak pernah mewawancarai perusahaan Anda. :)
Javid Jamae
144

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 valuesdan mendapatkan thread yang diurutkan aman Setdari Strings tanpa harus membuang ke bawah ConcurrentSkipListSet.

serg10
sumber
Bisakah Anda memberikan contoh penggunaan?
Allain Lalonde
24
Saya sering menggunakan ini. clone () adalah contoh yang bagus. Seharusnya mengembalikan Object, yang berarti Anda harus mengatakan misalnya (Daftar) list.clone (). Namun jika Anda mendeklarasikan sebagai Daftar clone () {...}, maka para pemain tidak perlu.
Jason Cohen
142

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

James AN Stauffer
sumber
7
Ini jahat, tetapi itu juga semacam konsekuensi logis dari bagaimana akhirnya bekerja. Kontrol aliran mencoba / menangkap / akhirnya melakukan apa yang dimaksudkan untuk dilakukan, tetapi hanya dalam batas-batas tertentu. Demikian pula, Anda harus berhati-hati untuk tidak menyebabkan pengecualian di dalam blok tangkapan / akhirnya, atau Anda juga akan membuang pengecualian asli. Dan jika Anda melakukan System.exit () di dalam blok try, blok akhirnya tidak akan dipanggil. Jika Anda mematahkan aliran normal, Anda mematahkan aliran normal ...
Neil Coffey
Jangan gunakan akhirnya {return; } tetapi akhirnya {code tanpa pengembalian}. Ini logis, karena pada akhirnya juga dimaksudkan untuk dieksekusi ketika pengecualian terjadi, dan satu-satunya arti yang mungkin dari pengembalian sebagai pengendali pengecualian harus mengabaikan pengecualian dan - memang - kembali.
extraneon
21
Sepertinya ini lebih sebagai "gotcha" daripada fitur tersembunyi, meskipun ada beberapa cara untuk menggunakannya, menggunakan metode ini bukan ide yang baik.
davenpcj
Eclipse mengeluarkan peringatan jika Anda melakukan ini. Saya dengan Eclipse. Jika Anda ingin menangkap pengecualian ... maka tangkap pengecualian.
helios
Itu yang Anda bayar untuk kode kotor yang kembali dari tengah metode. Tapi masih contoh yang bagus.
Rostislav Matl
141

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 )
{
    ...
}
Kadet Pirx
sumber
9
Sangat disayangkan bahwa ini adalah fitur yang sedikit diketahui. Saya telah melihat banyak kode yang mirip dengan blok kode pertama.
Peter Dolberg
4
Itu karena Java memiliki tipe null khusus (tersembunyi) yang tidak Anda lihat, juga tidak dapat referensi.
Nick Hristov
Yang lebih buruk adalah memeriksa null sebelum freeatau deletedi C / C ++. Konsep yang fundamental.
Thomas Eding
134

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 .

Adrian Mouat
sumber
20
Fitur yang benar-benar luar biasa - membuat enum OO dan memecahkan banyak masalah inisialisasi dengan cara yang sangat bersih.
Bill K
5
Enum sebagai singleton? Enum dengan hanya satu nilai?
Georgy Bolyuba
6
Georgy: Singleton adalah salah satu instance dari objek, bukan objek dengan satu nilai.
dshaw
20
@ Georgy: lihat juga Item 3 di Java Efektif Joshua Bloch (edisi ke-2); "Meskipun pendekatan ini belum diadopsi secara luas, tipe enum elemen tunggal adalah cara terbaik untuk menerapkan singleton."
Jonik
3
Nitpick kecil: mAgeharus final. Jarang ada alasan untuk bidang non-final dalam enum.
Joachim Sauer
121

Jenis params untuk metode generik dapat ditentukan secara eksplisit seperti:

Collections.<String,Integer>emptyMap()
Kevin Wong
sumber
10
Dan demi Tuhan itu jelek dan membingungkan. Dan tidak relevan untuk mengetik keamanan.
Chris Broadfoot
8
Aku suka ini. Itu membuat kode Anda sedikit lebih eksplisit dan dengan demikian lebih jelas bagi keluarga miskin yang harus memeliharanya dalam satu atau dua tahun.
extraneon
6
Ini sebenarnya sangat berguna dalam situasi di mana Anda telah mendeklarasikan metode generik statis seperti public static <T> T foo(T t). Anda kemudian dapat membuat panggilan keClass.<Type>foo(t);
Finbarr
Untuk beberapa alasan ini sepertinya tidak bekerja dengan metode yang diimpor secara statis .. Saya ingin tahu mengapa.
oksayt
Ini sangat berguna saat menggunakan ifs ternary dengan pengembalian. Sebagai contoh 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.
Andreas Holstenson
112

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 {

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

Dengan menggunakan antarmuka, pengembang dapat menentukan strategi mereka sendiri. Menggunakan enumsarana saya bisa mendefinisikan koleksi (lima) yang dibangun di dalamnya.

Peter Lawrey
sumber
27
Ini adalah kegilaan. (+1)
Cephalopod
12
@Arian ini bukan kegilaan. INI. ADALAH. JAVAAAAAAHHHH!
slezica
1
WHAAAAAT tidak, saya dengan Adrian. Ini bukan Java. Ini adalah kegilaan. Saya sangat ingin menggunakan ini.
slezica
104

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.

Paul Wicks
sumber
23
Hal penting tentang ini adalah ketika memanggil metode, Anda dapat menulis: foo ("pertama", "kedua", "ketiga")
Steve Armstrong
9
sehingga dunia halo lama dapat ditulis ulang; public static void main (String ... args) {System.out.println ("Hello World!"); }
Karussell
@ Karussell Mungkin, tapi sepertinya argumen itu tidak relevan: p
Kelly Elton
93

Favorit saya: buang semua jejak tumpukan benang ke standar keluar.

windows: CTRL- Breakdi jendela java cmd / console Anda

unix: kill -3 PID

Chris Mazzola
sumber
15
Juga ctrl- \ di Unix. Atau gunakan jstack dari JDK.
Tom Hawtin - tackline
9
Terima kasih, Anda baru mengajari saya keyboard saya memiliki Breakkunci.
Amy B
2
Di windows, CTRL-BREAK hanya berfungsi jika Anda memiliki proses yang berjalan di jendela konsol saat ini. Anda dapat menggunakan JAVA_HOME / bin / jstack.exe. Cukup berikan dengan id proses Windows.
Javid Jamae
Saya pikir itu membunuh -SIGQUIT
Nick Hristov
@Nick, ya SIGQUIT biasanya sinyal # 3.
Chris Mazzola
89

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");
                        }
                     });
                 }});
        }});
    }};
OscarRyz
sumber
Entah bagaimana, ini sedikit seolah-olah "dengan" kata kunci (fungsionalitas, sebenarnya) telah ditambahkan ke Jawa. Bisa sangat berguna, baru-baru ini saya mendengus karena array init tidak tersedia untuk Koleksi. Terima kasih!
PhiLho
15
Namun, ada satu efek samping dari penggunaan ini. Objek anonim dibuat, yang mungkin tidak selalu baik-baik saja.
amit
17
Meskipun setelah melihatnya lebih lanjut, saya harus mengatakan saya anehnya tertarik pada persarangan alami yang disediakan ini, bahkan versi "Disalahgunakan".
Bill K
4
Yap - Saya sangat suka versi 'disalahgunakan', saya pikir itu sangat jelas dan mudah dibaca, tapi mungkin itu hanya saya.
barryred
3
Sepenuhnya setuju, hierarki kode yang mencerminkan hierarki gui adalah peningkatan besar atas urutan pemanggilan metode.
opsb
88

Proxy dinamis (ditambahkan dalam 1.3) memungkinkan Anda untuk menentukan tipe baru saat runtime yang sesuai dengan antarmuka. Ini berguna beberapa kali mengejutkan.

jodonnell
sumber
10
Proxy dinamis adalah alasan bagus untuk memilih untuk menulis antarmuka Foo dan menggunakannya di mana saja, dengan kelas "FooImpl" default. Ini mungkin tampak jelek pada awalnya ("Mengapa tidak hanya memiliki kelas yang disebut Foo?") Tetapi manfaat dalam hal fleksibilitas di masa depan dan kemampuan tiruan untuk tes unit sangat berguna. Meskipun ada cara untuk melakukannya juga untuk non-antarmuka, mereka biasanya memerlukan hal-hal tambahan seperti cblib.
Darien
82

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;
}
Allain Lalonde
sumber
Itu mengejutkan. Bisakah orang mengatakan, "Nilai variabel akhir dapat diset sekali", di mana pun himpunan terjadi?
David Koelle
29
Ya, tetapi lebih kuat: "Nilai dari variabel final harus ditetapkan satu kali"
Allain Lalonde
6
+1 Setuju, ini adalah alat lain yang berharga untuk menemukan kesalahan pada waktu kompilasi, dan salah satu yang pemrogram tampaknya malu untuk digunakan karena beberapa alasan. Perhatikan bahwa karena dari Java 5 dan seterusnya, 'final' juga memiliki implikasi keselamatan-ulir, karena dapat menetapkan variabel akhir selama konstruktor sangat berharga.
Neil Coffey
4
Meskipun untuk metode khusus ini, saya hanya menggunakan beberapa pengembalian. Bahkan, dalam banyak kasus di mana ini berlaku, saya mungkin akan refactor menjadi metode terpisah dan menggunakan beberapa pengembalian.
ripper234
Aku suka ini! Saya selalu menghapus kata kunci terakhir karena saya pikir itu akan gagal. Terima kasih!
KARASZI István
62

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.

Mo.
sumber
18
Tidak. Ini sebenarnya bukan VM yang sangat baik. Itu hanya dirancang untuk menjalankan JAWA. Bahasa dinamis dan fungsional yang tipikal tidak bekerja dengan baik dengannya. Jika Anda ingin menggunakan VM, Anda harus menggunakan .NET / Mono. Itu dirancang untuk bekerja dengan SETIAP bahasa ...
Hades32
14
Sebenarnya JVM semata-mata dirancang untuk menjalankan Java Bytecodes. Anda dapat mengkompilasi sebagian besar bahasa modern ke Java Bytecode. Tentang satu-satunya hal yang tidak dimiliki Java Bytecode adalah dukungan bahasa dinamis, pointer, dan dukungan rekursi ekor.
mcjabberz
12
@ Hades32: sebenarnya. NET VM sangat mirip dengan JVM. Itu hanya mendapat dukungan untuk bahasa dinamis yang relatif baru (dengan DLR) dan Java 7 akan mendapatkan dukungan itu juga. Dan klasik "SETIAP bahasa" dari .NET (C #, Visual Basic.NET, ...) semua memiliki set fitur yang persis sama.
Joachim Sauer
13
JVM tidak mendukung obat generik, sedangkan .NET VM tidak. JVM jauh dari yang terbaik.
Blindy
3
Tidak mengabaikan keluhan tentang fitur bahasa tertentu yang tidak secara langsung didukung oleh JVM ... tapi saya cenderung berpikir stabilitas, konsistensi lintas platform, dan kinerja yang baik adalah jauh dan di atas alasan JVM mendapatkan poin tambahan. Saya telah bekerja dengan Java di sisi server selama bertahun-tahun sekarang pada banyak platform (termasuk AS / 400) dan telah mampu melupakannya sepenuhnya - bug-bug tersebut hampir selalu dalam kode yang dapat saya perbaiki, dan itu sama sekali tidak crash.
Rob Whelan
58

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");
Ron
sumber
@ Vuntic - Ini memungkinkan Anda untuk mendefinisikan kelas sederhana dalam konteks yang diperlukan.
ChaosPandion
1
@Chaos, Tapi mengapa? Punya contoh aktual di mana itu berguna?
Thorbjørn Ravn Andersen
10
@Wouter - Dalam hal ini, metode yang disebut pada objek anonim ( start()) sebenarnya tidak didefinisikan dalam subkelas ...
Axel
Sebenarnya, ini adalah fitur yang sangat berguna jika Anda memperluas kelas dasar yang melakukan beberapa pengaturan yang diperlukan, memanggil metode yang Anda tulis, dan kemudian melakukan teardown. Mulailah masalahnya dengan memanggil metode di kelas dasar (yang saya mungkin tidak akan memberikan nama yang sama). Ada contoh penggunaan (bukan definisi) di sini
AmigoNico
56

The asList metode dalam java.util.Arraysmemungkinkan kombinasi bagus varargs, metode generik dan autoboxing:

List<Integer> ints = Arrays.asList(1,2,3);
Bruno De Fraine
sumber
15
Anda ingin membungkus daftar yang dikembalikan dengan konstruktor Daftar jika int akan ukuran tetap (karena didukung oleh array)
KitsuneYMG
2
The Arrays.asListmemiliki 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.
Christian Semrau
53

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;
}
}
Tahir Akhtar
sumber
4
Itu hanya diperlukan jika Anda telah membayangi nama (dalam kasus Anda, dengan nama parameter metode). Jika Anda menyebut argumen lain, maka Anda bisa langsung mengakses variabel anggota sortAscending kelas Container tanpa menggunakan 'ini'.
sk.
7
Masih bermanfaat untuk memiliki referensi ke kelas penutup, misalnya. jika Anda perlu meneruskannya ke beberapa metode atau konstruktor.
PhiLho
Sering digunakan dalam pengembangan tata letak Android, untuk mendapatkan Konteks dari, katakanlah, pendengar tombol, dengan MyActivity.this.
espinchi
52

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!

PhiLho
sumber
15
rapi, label dengan komentar :)
Thorbjørn Ravn Andersen
46

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);
        }
    };
}
Das
sumber
20
itu adalah matahari. * API yang tidak benar-benar bagian dari bahasa Java per se
DW.
Ada sejumlah metode aneh lainnya pada Unsafe seperti membuat objek tanpa memanggil konstruktor, malloc / realloc / metode gaya bebas.
Peter Lawrey
Saya terutama menyukai pengambil dan penyetel primitif di lokasi memori, seperti putDouble (alamat panjang, d ganda).
Daniel
42

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

Devon_C_Miller
sumber
1
Kemungkinan besar window manager Anda memiliki sesuatu yang terikat pada kunci itu. Gnome tidak mengikat itu, jadi saya berasumsi Anda menjalankan KDE yang mengikatnya ke 'beralih ke desktop 13'. Anda dapat mengubahnya dengan masuk ke Control panel, Regional, Shortcuts Keyboard dan menghapus pemetaan untuk Shift-Ctrl-F1
Devon_C_Miller
40

Setiap file kelas dimulai dengan nilai hex 0xCAFEBABE untuk mengidentifikasinya sebagai bytecode JVM yang valid.

( Penjelasan )

Dolph
sumber
38

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.

stili
sumber
Baru-baru ini ditemukan CountDownLatchdan CyclicBarrier- sangat berguna!
Raphael
37

Kata kunci yang menegaskan tingkat bahasa .

Mark Cidade
sumber
19
Masalah dengan menegaskan adalah bahwa itu harus diaktifkan selama runtime.
extraneon
10
Tetapi jika dinonaktifkan, rasanya tidak ada. Anda dapat menambahkan sebanyak yang Anda inginkan dalam kode Anda dan Anda tidak akan memiliki penalti kinerja jika dinonaktifkan.
Ravi Wallau
5
Saya percaya itu hal yang baik tentang penegasan: itu bisa dimatikan tanpa penalti.
andref
masalahnya adalah, jika Anda secara tidak sengaja menerapkan efek samping dalam suatu pernyataan, Anda harus mengaktifkan pernyataan agar program Anda berfungsi ...
Chii
Untuk mendeteksi jika assert aktif, Anda dapat menggunakan {boolean assertsOn = false; menegaskan assertsOn = true; if (assertsOn) {/ * verifikasi kompleks * /}}. Ini juga memungkinkan untuk log atau melempar pengecualian jika keadaan tegas bukan yang diharapkan.
fernacolo
37

Tidak benar-benar bagian dari bahasa Jawa, tetapi disassembler javap yang datang dengan JDK Sun tidak banyak dikenal atau digunakan.

Binil Thomas
sumber
36

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

Tautan ke dokumentasi Sun

18Rabbit
sumber
30
Saya pikir menggunakan di isini sangat membingungkan, karena kebanyakan orang berharap saya menjadi indeks dan bukan elemen array.
cdmckay
Jadi ... int sum (int [] array) {int result = 0; untuk (int element: array) {result + = elemen; } hasil pengembalian; }
Drew
28
Satu-satunya hal yang membuat saya gila tentang ini adalah sepertinya akan sangat mudah untuk membuat kata kunci untuk mengakses nilai jumlah loop, tetapi Anda tidak bisa. Jika saya ingin mengulang dua array dan membuat perubahan ke kedua berdasarkan nilai-nilai di pertama saya terpaksa menggunakan sintaks lama karena saya tidak memiliki offset ke array kedua.
Jherico
6
Sayang tidak juga bekerja dengan Enumerasi, seperti yang digunakan di JNDI. Kembali ke iterator di sana.
extraneon
3
@extraneon: lihat Collections.list (Enumeration <T> e). Itu akan membantu dengan iterasi enumerasi di loop foreach.
Werner Lehmann
34

Saya pribadi menemukan java.lang.Voidsangat terlambat - meningkatkan pembacaan kode dalam hubungannya dengan obat generik, misalnyaCallable<Void>

Rahel Lththy
sumber
2
tidak terlalu. pada titik tertentu, Anda harus spesifik: Executors.newSingleThreadExecutor (). kirim (Callable baru <Void> () {..}) - Anda tidak dapat membuat Instantiable Callable baru <?> (), Anda perlu menentukan tipe eksplisit - dengan demikian, ini merupakan alternatif untuk Callable <Object>.
Rahel Lüthy
4
Void lebih spesifik daripada Object karena Void hanya bisa null, Object bisa berupa apa saja.
Peter Lawrey