Java'nın Gizli Özellikleri


295

C # Gizli Özellikleri okuduktan sonra merak ettim, Java gizli özellikleri nelerdir?


17
Bu gizli özellikleri kullanmak her zaman iyi bir fikir değildir; çoğu zaman şaşırtıcı ve kodunuzu okuyan başkaları için kafa karıştırıcı.
Kevin Bourrillion

1
Siz (/ birisi) muhtemelen C # sorusu gibi soru gövdesinde cevapları düzgün bir şekilde özetlemelidir.
ripper234

Yanıtlar:


432

Double Brace Başlatma , birkaç ay önce ilk keşfettiğimde, daha önce hiç duymadığım için beni şaşırttı.

ThreadLocals tipik olarak thread başına durumu depolamanın bir yolu olarak bilinmemektedir.

JDK 1.5 Java, kilitlerin ötesinde son derece iyi uygulanmış ve sağlam eşzamanlılık araçlarına sahip olduğundan, java.util.concurrent'ta yaşarlar ve özellikle ilginç bir örnek, karşılaştırmayı uygulayan iplik açısından güvenli ilkelleri içeren java.util.concurrent.atomic alt paketidir. -ve-takas işlemi ve bu işlemlerin yerel donanım destekli gerçek sürümleriyle eşleştirilebilir.


40
Çifte parantez başlatma ... tuhaf ... Aslında bu deyimi çok geniş bir şekilde benimsemeye dikkat ediyorum, çünkü aslında nesnenin anonim bir alt sınıfını yaratıyor, bu da kafa karıştırıcı eşit / hashcode sorunlarına neden olabilir. java.util.concurrent gerçekten harika bir paket.
MB.

6
Ben var öğretilen Java, ve bu öğrenme durdurmak asla göstermek için gider bu sözdizimi ... karşılaşanlar ilk defa = 8-)
Yuval

49
Bu "çift ayraç" deyimiyle başlatılan bir koleksiyona başvurunuzu (veya gerçek adı - başlatıcı bloğuyla anonim sınıf olarak adlandırırsak), gizli belleğe neden olabilecek dış nesneye dolaylı bir başvuruda bulunduğunuzu unutmayın. sızıntıları. Tamamen kaçınmayı tavsiye ederim.
ddimitrov

51
"İkili ayraç başlatma", anonim bir iç sınıf yaratmak, gerçekte neler olup bittiğini anlamak ve iç sınıfların bu şekilde kullanılması amaçlanmış gibi ses çıkarmak için çok örtülü bir isimdir. Bu gizli kalmayı tercih ettiğim bir model.
erickson

11
Neredeyse, gerçekten statik bir blok değil, farklı bir zamanda yürütüldüğünden farklı bir "başlatıcı bloğu" (daha fazla ayrıntı için cevaba koyduğum bağlantıya bakın)
Boris Terzic

279

Tür parametre varyansında ortak birleşim:

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

Örneğin, hem Karşılaştırılabilir hem de Koleksiyon olan bir parametre almak istiyorsanız:

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

Verilen bu iki koleksiyon eşitse veya bunlardan herhangi biri verilen öğeyi içeriyorsa, aksi halde yanlış olursa, bu yöntem doğru olarak döner. Dikkat edilmesi gereken nokta, b1 ve b2 argümanlarında hem Karşılaştırılabilir hem de Koleksiyon yöntemlerini çağırabileceğinizdir.


Bunun için en sevdiğim kullanım, Uzatılabilir Charsequence'ı kabul eden bir yönteme ihtiyacınız olduğunda.
Neil Coffey

5
Orada & yerine "VEYA" olabilir mi?
mainstringargs

9
@Grasper: Hayır, OR (ayrık birlik) bu bağlamda sağlanmamıştır. Ancak bunun yerine Ya <A, B> gibi ayrık birleşim veri türünü kullanabilirsiniz. Bu tür bir Pair <A, B> türünün ikiliidir. Böyle bir veri türüne örnek olarak, İşlevsel Java kitaplığına veya Scala çekirdek kitaplıklarına bakın.
Apocalisp

5
Sadece bir sınıfı ve birkaç arabirimi genişletmeniz ZORUNLUDUR -> ortak sınıf Baz <T, Clazz & Interface1 & InterfaceI ... 'yı genişletiyor ve Baz <T, Clazz1 & ClazzI>' yı genişletiyor
JohnJohnGa 17:11

220

Geçen gün örnek başlatıcılar tarafından şaşırdım. Bazı kod katlanmış yöntemleri siliyordu ve birden çok örnek başlatıcıları oluşturma sona erdi:

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

mainYöntemin yürütülmesi şunları görüntüler:

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

Birden fazla kurucuya sahipseniz ve ortak koda ihtiyacınız varsa bunlar yararlı olacaktır

Ayrıca sınıflarınızı başlatmak için sözdizimsel şeker sağlarlar:

List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

Map<String,String> codes = new HashMap<String,String>(){{ 
  put("1","one"); 
  put("2","two");
}};

38
Bunun çağrılması gereken açık bir yönteme göre avantajı, birisi daha sonra bir kurucu eklerse init () 'i çağırmayı hatırlamaları gerekmemesidir. otomatik olarak yapılacaktır. Bu, gelecekteki programcıların hatalarını önleyebilir.
Bay Parlak ve Yeni 宇 宇

40
Ayrıca, bir init () yönteminden farklı olarak, son alanları başlatabilir.
Darron

2
Sınıfı genişletir ve çeşitli çocukları başlatırsanız ne olur? Hala aynı şekilde mi davranacak?
Kezzer

12
İnsanlar genellikle sertifikaları reddeder (örn. Stackoverflow.com/questions/281100/281127#281127 ) ve özellikle teknik değerlerini sorgularlar. Fakat burada daha fazla programcı SCJP'leri için çalışmış olsaydı, bu pek çok kişi tarafından "gizli bir özellik" olarak kabul edilmezdi. ;-)
Jonik

12
Bahse girerim "24 saat içinde java" kitabında bu "bariz özellik" vardır. devamını oku guys
:)

201

JDK 1.6_07 +, birçok aracın üstünde güzel bir GUI olan VisualVM (bin / jvisualvm.exe) adlı bir uygulama içerir. JConsole'den daha kapsamlı görünüyor.


Ve Jconsole eklentilerini kullanmasına izin veren bir eklentiye (bir netbeans şeyidir) sahiptir. Gayet iyi.
Thorbjørn Ravn Andersen

VisualVM gerçekten dilimlenmiş ekmek beri en iyi şey! JDK 1.5
sandos

VisualVM'yi bazı durumlarda yavaş veya kullanılamaz buluyorum. Ticari YourKit'in bu sorunu yoktur, ancak maalesef ücretsiz değildir.
Roalt

JDK 1.6.0_22 ve sonrasındaki Visual VM'nin daha yeni sürümleri çok geliştirildi. Ben JDK1.7 daha iyi bir sürümü var bahis.
djangofan


156

Çoğu kişi için Java geliştirici pozisyonları için röportaj yaptığım bloklar çok şaşırtıcı. İşte bir örnek:

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

gotoJava'da sadece bir anahtar kelime olduğunu kim söyledi ? :)


2
Pekala, bunu birkaç şekilde yapma seçeneğine sahip olmayı tercih ederim. Örneğin, System.exit (1) kullanan insanları gördüm; Servlet ve EJB kodlarında, ancak bu System.exit () 'i kaldırmamız gerektiği anlamına gelmez; JDK'dan değil mi?
Georgy Bolyuba

31
Bazı durumlarda, iç içe bir döngü yapısı içinde, bir dış halkanın bir sonraki yinelemesine devam etmek yararlı olabilir. Bu, bu özelliğin makul bir kullanımı olacaktır.
alasdairg

75
Birçok programcı tarafından özellikle bilinmeyen şey (ve muhtemelen de), HERHANGİ BİR eski bloğu etiketleyebilmeniz ve bozabilmenizdir. Bir döngü olmak zorunda değildir - sadece rastgele bir blok tanımlayabilir, bir etiket verebilir ve onunla mola kullanabilirsiniz.
Neil Coffey

27
Bu bir goto değil, sadece önceki bir yinelemeye geri dönebilir (yani: ileri atlayamazsınız). Bu, bir yineleme yanlış döndürdüğünde oluşan mekanizmanın aynısıdır. Java'nın goto olduğunu söylemek, derleyicisi JUMP komutu üreten herhangi bir dilin bir goto ifadesine sahip olduğunu söylemek gibidir.
Zombies

4
Yani, problemleri çözme ve tasarımlar aracılığıyla düşünme yeteneğinden ziyade Java trivia'ya dayalı röportaj yapıyorsunuz. Asla şirketinizle röportaj yapmadığımdan emin olacağım. :)
Javid Jamae

144

JDK 1.5'ten beri yürürlükte olan kovaryant dönüş türlerine ne dersiniz ? Unsexy bir ekleme olduğu için oldukça zayıf bir şekilde duyuruluyor, ancak anladığım kadarıyla, jeneriklerin çalışması için kesinlikle gerekli.

Temel olarak, derleyici artık bir alt sınıfın geçersiz kılınmış bir yöntemin dönüş türünü orijinal yöntemin dönüş türünün bir alt sınıfı olması için daraltmasına izin vermektedir. Bu yüzden buna izin verilir:

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

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

Alt sınıfın valuesyöntemini çağırabilir ve aşağı döküm yapmak zorunda kalmadan güvenli Setbir Strings sıralaması elde edebilirsinizConcurrentSkipListSet .


Örnek bir kullanım sağlayabilir misiniz?
Allain Lalonde

24
Bunu çok kullanıyorum. klon () buna harika bir örnektir. Object'i döndürmesi gerekiyordu, yani (List) list.clone () demek zorunda kalacaksınız. Ancak Liste klonu () {...} olarak bildirirseniz, yayın gereksizdir.
Jason Cohen

142

Son olarak bir blokta kontrolün aktarılması herhangi bir istisnayı ortadan kaldırır. Aşağıdaki kod RuntimeException kuralını atmaz - kaybolur.

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

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


7
Bu kötü, ama aynı zamanda nihayet nasıl çalıştığının mantıklı bir sonucu. Deneme / yakalama / son olarak akış kontrolü yapmak istediklerini yapar, ancak sadece belirli sınırlar dahilinde. Benzer şekilde, bir catch / nihayet bloğu içinde istisna oluşturmamaya dikkat etmelisiniz, yoksa orijinal istisnayı da atacaksınız. Ve try bloğunun içinde bir System.exit () yaparsanız, sonunda blok çağrılmaz. Normal akışı keserseniz, normal akışı
kesersiniz

Sonunda {return; } ancak sonunda {dönüş olmadan kod}. Son olarak, istisnalar meydana geldiğinde de yürütülmesi amaçlandığı için bu mantıklıdır ve istisna işleyicisi olarak bir dönüşün tek olası anlamı istisna ve - aslında - dönüşü göz ardı etmek olmalıdır.
extraneon

21
Bu, gizli bir özellikten daha çok bir "gotcha" gibi görünüyor, ancak bir tane olarak kullanılabilecek yollar olsa da, bu yöntemi kullanmak iyi bir fikir olmaz.
davenpcj

Eclipse bunu yaparsanız bir uyarı verir. Eclipse ile birlikteyim. Bir istisna yakalamak istiyorsanız ... bir istisna yakalayın.
helios

Yöntemin ortasından dönen kirli kod için ödediğiniz şey budur. Ama yine de güzel bir örnek.
Rostislav Matl

141

Hiç kimsenin null olup olmadığını kontrol etmenin gerekli olmadığı bir şekilde uygulandığından bahsetmediğini görmedim.

Onun yerine:

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

sadece kullan:

if( aObject instanceof String )
{
    ...
}

9
Bunun çok az bilinen bir özellik olması utanç verici. İlk kod bloğuna benzer bir sürü kod gördüm.
Peter Dolberg

4
Bunun nedeni Java'nın görmediğiniz ya da başvuramayabileceği özel (gizli) bir boş türü olmasıdır.
Nick Hristov

Daha kötüsü, C / C ++ ' freeda deleteing veya ing önce null olup olmadığını kontrol etmektir . Böyle temel bir kavram.
Thomas Eding

134

Numaralandırmalarda yöntemlere ve kuruculara izin vermek beni şaşırttı. Örneğin:

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

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

Hatta, belirli bir enum değerinin yöntemleri geçersiz kılmasına izin veren bir "sabit özgül sınıf gövdesi" bile olabilir.

Daha fazla belge burada .


20
Gerçekten harika bir özellik aslında - numaralandırmalar OO yapar ve çok temiz bir şekilde başlatma sorunları çok çözer.
Bill K

5
Tekil sayım? Sadece bir değer ile numaralandırma?
Georgy Bolyuba

6
Georgy: Singleton, tek değerli bir nesne değil, nesnenin bir örneğidir.
dshaw

20
@Georgy: ayrıca Joshua Bloch'un Etkili Java'sında (2. Baskı) 3. Maddeye bakınız; "Bu yaklaşım henüz geniş çapta benimsenmese de, tek elemanlı bir enum tipi, bir singletonu uygulamanın en iyi yoludur."
Jonik

3
Küçük nitpick: mAgenihai olmalı. Sekmelerde nihai olmayan felds için nadiren bir neden vardır.
Joachim Sauer

121

Genel yöntemler için tip parametreleri açıkça şu şekilde belirtilebilir:

Collections.<String,Integer>emptyMap()

10
Ve tanrı tarafından çirkin ve kafa karıştırıcı. Ve tip güvenliği ile ilgisi yoktur.
Chris Broadfoot

8
Bunu seviyorum. Kodunuzu biraz daha açık ve bir veya iki yıl içinde korumak zorunda kalacak yoksul çim için daha açık hale getirir.
extraneon

6
Bu aslında gibi statik bir genel yöntem bildirdiğiniz durumlarda çok kullanışlıdır public static <T> T foo(T t). Daha sonraClass.<Type>foo(t);
Finbarr

Nedense bu statik olarak ithal yöntemlerle çalışmıyor gibi görünüyor .. Acaba neden.
oksayt

Bu özellikle üçlü bir ifs kullanıldığında yararlıdır. Örneğin return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList(). Basit bir Collections.emptyMap () yönteminin derleme hatası vereceği bazı yöntem çağrıları için de yararlıdır.
Andreas Holstenson

112

Bir arabirimi uygulamak için numaralandırmaları kullanabilirsiniz.

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: Yıllar sonra ....

Bu özelliği burada kullanıyorum

public enum AffinityStrategies implements AffinityStrategy {

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

Bir arayüz kullanarak, geliştiriciler kendi stratejilerini tanımlayabilirler. Bir enumaraç kullanarak, bunlardan inşa edilmiş (beş kişilik) bir koleksiyon tanımlayabilirim.


27
Bu delilik. (+1)
Cephalopod

12
@Arian bu delilik değil. BU. DIR-DİR. JAVAAAAAAHHHH!
slezica

1
WHAAAAAT hayır, Adrian ile birlikteyim. Bu Java değil. Bu delilik. Bunu kullanmak için ölüyorum.
slezica

104

Java 1.5'ten itibaren Java'nın değişken değişkenlik işlevleri yazmak için çok daha temiz bir sözdizimi vardır. Yani, sadece bir diziyi geçmek yerine, aşağıdakileri yapabilirsiniz

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

barlar otomatik olarak belirtilen türde diziye dönüştürülür. Büyük bir galibiyet değil, yine de bir galibiyet.


23
Bununla ilgili önemli olan yöntem çağrılırken yazabilirsiniz: foo ("first", "second", "third")
Steve Armstrong

9
böylece eski merhaba dünya yeniden yazılabilir; public static void main (Dize ... args) {System.out.println ("Merhaba Dünya!"); }
Karussell

@Karussell Belki, ama argümanlar ilgisiz görünüyor: p
Kelly Elton

93

En sevdiğim: tüm iş parçacığı yığın izlerini standart çıktıya dök.

windows: CTRL- Breakjava cmd / konsol pencerenizde

unix: kill -3 PID


15
Ayrıca Unix'te ctrl- \. Veya JDK'dan jstack kullanın.
Tom Hawtin - çakmak hattı

9
Teşekkürler, bana klavyemin bir Breakanahtarı olduğunu öğrettin .
Amy B

2
Windows'da, CTRL-BREAK yalnızca geçerli konsol penceresinde işlem çalışıyorsa çalışır. Bunun yerine JAVA_HOME / bin / jstack.exe dosyasını kullanabilirsiniz. Sadece Windows işlem kimliğini sağlayın.
Javid Jamae

Öldürmek sanıyordum -SIGQUIT
Nick Hristov

@Nick, evet SIGQUIT genellikle sinyal # 3.
Chris Mazzola

89

Birkaç kişi örnek başlatıcıları hakkında yayın yaptı, işte bunun için iyi bir kullanım:

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

Hızlı ve basit bir şey yapıyorsanız haritaları başlatmanın hızlı bir yoludur.

Veya hızlı bir salınım çerçevesi prototipi oluşturmak için kullanın:

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

Tabii ki istismar edilebilir:

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

Her nasılsa, "with" anahtar kelimesi (aslında işlevsellik) Java'ya eklenmiş gibi. Çok kullanışlı olabilir, yakın zamanda homurdandım çünkü diziler init Koleksiyonlar için mevcut değildi. Teşekkürler!
PhiLho

15
Ancak bunu kullanmanın bir yan etkisi vardır. Her zaman iyi olmayabilecek anonim nesneler oluşturulur.
09:14 tarihinde amit

17
Daha fazla baktıktan sonra, garip bir şekilde bu doğal yuvalama, hatta "Abused" versiyonu çekici olduğunu söylemek zorundayım.
Bill K

4
Evet - 'istismar edilmiş' sürümü oldukça beğendim, bence bu çok açık ve okunabilir, ama belki de sadece ben.
barryred

3
Kesinlikle katılıyorum, gui hiyerarşisini yansıtan kod hiyerarşisi, bir dizi yöntem çağrısı üzerinde büyük bir gelişmedir.
opSB

88

Dinamik proxy'ler (1.3'te eklenmiştir) çalışma zamanında bir arabirime uyan yeni bir tür tanımlamanıza olanak tanır. Şaşırtıcı sayıda kez kullanışlıdır.


10
Dinamik proxy'ler, bir Foo arabirimi yazmayı ve bunu varsayılan bir "FooImpl" sınıfıyla her yerde kullanmayı seçmenin harika bir nedenidir. İlk başta çirkin görünebilir ("Neden sadece Foo adında bir sınıfa sahip değilsiniz?") Ancak, birim testler için gelecekteki esneklik ve alay yeteneği açısından faydalar kullanışlıdır. Arayüzler için de bunu yapmanın yolları olsa da, genellikle cblib gibi ekstra şeyler gerektirirler.
Darien

82

son başlatma ertelenebilir.

Karmaşık bir mantık dönüş değerleri akışı ile bile her zaman ayarlanmış olmasını sağlar. Bir vakayı kaçırmak ve yanlışlıkla null döndürmek çok kolaydır. Null değerinin geri döndürülmesini imkansız kılmaz, sadece bilerek yapıldığı açıktır:

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

Bu şaşırtıcı. Küme nerede olursa olsun "Son değişkenin değeri bir kez ayarlanabilir" diyebilir mi?
David Koelle

29
Evet, ama daha kuvvetli: "Son değişkenin değeri bir kez ayarlanmalıdır"
Allain Lalonde

6
+1 Kabul ediyorum, bu derleme zamanında hataları tespit etmek için başka bir değerli araçtır ve programcıların bir nedenden dolayı kullanmaktan çekiniyorlar. Java 5'ten itibaren, 'final' ayrıca iş parçacığı güvenliği sonuçları içerdiğinden, yapıcı sırasında bir son değişken ayarlayabilmenin paha biçilmez olduğunu unutmayın.
Neil Coffey

4
Bu belirli yöntem için olsa da, sadece birden çok döndürme kullanmak istiyorum. Aslında, bunun geçerli olduğu çoğu durumda, muhtemelen ayrı bir yönteme yeniden yansıtır ve birden çok dönüş kullanırsınız.
ripper234

Bunu seviyorum! Son anahtar kelimeyi her zaman sildim çünkü başarısız olacağını düşündüm. Teşekkürler!
KARASZI István

62

Java'nın bir başka "gözden kaçan" özelliğinin JVM olduğunu düşünüyorum. Muhtemelen mevcut olan en iyi VM'dir. Ve birçok ilginç ve kullanışlı dili (Jython, JRuby, Scala, Groovy) destekler. Tüm bu diller kolayca ve sorunsuz bir şekilde işbirliği yapabilir.

Yeni bir dil tasarlarsanız (scala durumunda olduğu gibi) hemen mevcut tüm kütüphanelere sahip olursunuz ve bu nedenle diliniz en başından itibaren "yararlıdır".

Tüm bu diller HotSpot optimizasyonlarını kullanır. VM çok iyi izlenebilir ve hata ayıklanabilir.


18
Hayır. Aslında çok iyi bir sanal makine değil. Yalnızca JAVA'yı çalıştırmak için tasarlanmıştır. Tipik dinamik ve fonksiyonel diller onunla iyi çalışmaz. VM kullanmak istediğinizde .NET / Mono kullanmalısınız. Bu HER dil ile çalışmak için tasarlanmıştır ...
Hades32

14
Aslında JVM yalnızca Java Bytecodes'i çalıştırmak için tasarlanmıştır. Modern dillerin çoğunu Java Bytecode'a derleyebilirsiniz. Java Bytecode'un eksik olduğu tek şey hakkında dinamik dil desteği, işaretçiler ve kuyruk özyineleme desteği.
mcjabberz

12
@ Hades32: Aslında .NET VM JVM'ye oldukça benzer. Dinamik diller için nispeten yakın zamanda (DLR ile) destek aldı ve Java 7 de bu desteği almak üzere. Ve klasik "HER dil" .NET (C #, Visual Basic.NET, ...) hemen hemen aynı özellik kümesine sahiptir.
Joachim Sauer

13
.NET VM, JVM jenerikleri desteklemez. JVM en iyisine yakın değil.
Blindy

3
Doğrudan JVM tarafından desteklenmeyen belirli dil özellikleriyle ilgili şikayetleri iskonto etmek için değil ... ama istikrar, platformlar arası tutarlılık ve iyi performansın JVM'nin ekstra puan almasının nedenlerinin çok üzerinde olduğunu düşünüyorum. Sunucu tarafı Java ile yıllardır birçok platformda çalışıyorum (AS / 400 dahil) ve hemen hemen tamamen unutabildim - hatalar hemen hemen her zaman kodda düzeltebilirim ve sadece çökmez.
Rob Whelan

58

Anonim bir alt sınıf tanımlayabilir ve herhangi bir arabirim uygulamasa bile doğrudan bir yöntemi çağırabilirsiniz.

new Object() {
  void foo(String s) {
    System.out.println(s);
  }
}.foo("Hello");

@Vuntic - İhtiyaç duyulan bağlam içinde basit bir sınıf tanımlamanızı sağlar.
ChaosPandion

1
@Chaos, ama neden? Yararlı olduğu gerçek bir örnek var mı?
Thorbjørn Ravn Andersen

10
@Wouter - Bu durumda, anonim nesnede ( start()) çağrılan yöntem alt sınıfta tanımlanmamıştır ...
Axel

Aslında, bazı gerekli ayarları yapan, yazdığınız yöntemi çağıran ve sonra yıkılan bir temel sınıfı genişletirseniz, bu çok kullanışlı bir özelliktir. (Ben muhtemelen aynı adı vermek olmaz) temel sınıfta bir yöntemi çağırarak şey tekme. Örnek kullanım (tanıma değil) var burada
AmigoNico

56

AsList yöntem java.util.Arraysvarargs, jenerik yöntem ve Autoboxing güzel bir kombinasyonunu sağlar:

List<Integer> ints = Arrays.asList(1,2,3);

15
Döndürülen listeyi bir Liste yapıcısıyla sarmak istiyorsanız, aksi takdirde ints sabit boyutlu olacaktır (dizi tarafından desteklendiğinden)
KitsuneYMG

2
Arrays.asListOlabildiğince olağandışı özelliği vardır set()unsurları değil add()ya remove(). Bu yüzden , listenin değiştirilip değiştirilemeyeceğine bağlı olarak genellikle bir new ArrayList(...)veya Collections.unmodifiableList(...)a'ya sararım.
Christian Semrau

53

Kullanılması Bu bir iç sınıftan sınıfa içeren alanları / yöntemleri erişmek için anahtar kelime. Aşağıda, oldukça tutarlı bir örnek olarak, anonim iç sınıftan konteyner sınıfının sortAscending alanını kullanmak istiyoruz. Bunun yerine ContainerClass.this.sortAscending kullanmak hile yapar.

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

4
Bu yalnızca adı gölgelendirdiyseniz gereklidir (sizin durumunuzda, method parametresi adıyla). Argümanı başka bir şey olarak adlandırdıysanız, 'this' kullanmadan Container sınıfının sortAscending üye değişkenine doğrudan erişebilirsiniz.
sk.

7
Çevreleyen sınıfa, örneğin ör. bazı yöntemlere veya yorumculara iletmeniz gerekiyorsa.
PhiLho

Genellikle Android mizanpaj geliştirmede kullanılır, Bağlamı almak için diyelim ki, bir düğmenin dinleyicisiyle birlikte MyActivity.this.
espinchi

52

Gerçekten bir özellik değil, son zamanlarda bazı Web sayfalarında keşfettiğim eğlenceli bir numara:

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

    System.exit(0);
  }
}

geçerli bir Java programıdır (uyarı oluşturmasına rağmen). Nedenini göremiyorsanız Gregory'nin cevabına bakınız! ;-) Peki, burada vurgulanan sözdizimi de bir ipucu veriyor!


15
temiz, bir yorum ile bir etiket :)
Thorbjørn Ravn Andersen

46

Bu tam olarak "gizli özellikler" değildir ve çok kullanışlı değildir, ancak bazı durumlarda son derece ilginç olabilir:
Sınıf sun.misc.Unsafe - Java'da doğrudan bellek yönetimi uygulamanıza izin verir (hatta kendi kendini değiştiren Java kodu yazabilirsiniz) bu çok denerseniz):

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

20
Bu bir sun. * API aslında Java dilinin bir parçası değildir
DW.

Güvensiz bir yapıcı, malloc / realloc / free stil yöntemlerini çağırmadan nesne oluşturmak gibi güvenli olmayan başka yöntemler de vardır.
Peter Lawrey

Özellikle putDouble (uzun adres, çift d) gibi bellek konumlarındaki ilkel alıcıları ve ayarlayıcıları seviyorum.
Daniel

42

Gizli gibi Salıncak I çalışırken Ctrl- Shift- F1özellik.

Geçerli pencerenin bileşen ağacını döker.
(Bu tuş vuruşunu başka bir şeye bağlamadığınız varsayılarak.)


1
Büyük olasılıkla pencere yöneticinizde bu anahtara bağlı bir şey var. Gnome ona bağlanmaz, bu yüzden onu 'masaüstüne 13' bağlamaya bağlayan KDE çalıştırdığınızı varsayıyorum. Kontrol paneli, Bölgesel, Klavye Kısayolları'na gidip Shift-Ctrl-F1
Devon_C_Miller

40

Her sınıf dosyası , geçerli JVM bayt kodu olarak tanımlamak için hex değeri 0xCAFEBABE ile başlar .

( Açıklama )


38

Oyum , eşzamanlı koleksiyonları ve esnek yöneticileri ile java.util.concurrent'e gidiyor . DelayQueue, öğelerin belirli bir gecikmeden sonra kullanıma sunulduğu kişisel favorim.

java.util.Timer ve TimerTask güvenle durdurulabilir.

Ayrıca, tam olarak gizli değil, tarih ve saat ile ilgili diğer sınıflardan farklı bir pakette. java.util.concurrent.TimeUnit nanosaniye, mikrosaniye, milisaniye ve saniye arasında dönüştürme yaparken kullanışlıdır.

Normal bazı Değer 1 * 1000 veya Bazı Değer / 1000'den çok daha iyi okunur.


Son zamanlarda keşfedilen CountDownLatchve CyclicBarrier- çok yararlı!
Raphael

37

Dil düzeyinde onay anahtar kelimesi.


19
İddia ile ilgili sorun çalışma zamanı sırasında açılması gerektiğidir.
extraneon

10
Ancak devre dışı bırakılmışsa, sanki orada değil gibi. Kodunuza istediğiniz sayıda ek ekleyebilirsiniz ve devre dışı bırakıldıklarında herhangi bir performans cezasına sahip olmayacaksınız.
Ravi Wallau

5
Bunun iddia ile ilgili iyi bir şey olduğuna inanıyorum : penaltı olmadan kapatılabilir.
andref

sorun, yanlışlıkla bir iddiada bir yan etki uyguladıysanız, ur programının çalışması için iddiayı açmanız gerekir ...
Chii

Eklerin açık olup olmadığını tespit etmek için {boolean assertsOn = false; assert assertsOn = true; if (assertsOn) {/ * karmaşık doğrulama * /}}. Bu durum, eğer iddia edilen durum beklenmediyse günlüğe kaydetmeye veya istisna atmaya izin verir.
fernacolo

37

Java dilinin bir parçası değil, Sun'ın JDK'sı ile gelen javap sökücü yaygın olarak bilinmemekte veya kullanılmamaktadır.


36

1.5 için for-each döngü yapısının eklenmesi. Ben <3.

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

Yuvalanmış örneklerde kullanılabilir:

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

For-each yapısı, yineleyici yerine dizin değişkenini gizlediği diziler için de geçerlidir. Aşağıdaki yöntem, bir int dizisindeki değerlerin toplamını döndürür:

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

Sun belgelerine bağlantı


30
iÇoğu insan i bir dizi öğesi değil, bir dizin olmasını beklendiği gibi burada kullanarak süper kafa karıştırıcı olduğunu düşünüyorum .
cdmckay

Yani ... int sum (int [] dizi) {int sonuç = 0; for (int eleman: dizi) {sonuç + = eleman; } sonuç; }
Drew

28
Beni bu konuda çıldırtan tek şey, döngü sayısı değerine erişmek için bir anahtar kelime oluşturmanın gerçekten kolay olacağı gibi görünüyor, ancak yapamazsınız. Ben iki diziler üzerinde döngü ve ilk ikinci değerlere dayalı bir saniye değişiklikleri yapmak istiyorsanız ben ikinci dizinin hiçbir ofset var çünkü ben eski sözdizimini kullanmak zorundayım.
Jherico

6
JNDI'da kullanılanlar gibi Numaralandırmalarla da çalışmadığı bir utanç. Oradaki yineleyicilere geri döndü.
extraneon

3
@extraneon: Collections.list'e (Numaralandırma <T> e) bir göz atın. Bu, foreach döngüsündeki numaralandırmaların yinelenmesine yardımcı olmalıdır.
Werner Lehmann

34

kişisel olarak java.lang.Voidçok geç keşfedilen - jenerikler ile birlikte kod okunabilirliğini artırır, örn.Callable<Void>


2
tam olarak değil. bir noktada, spesifik olmanız gerekir: Executors.newSingleThreadExecutor (). Submit (yeni Callable <Void> () {..}) - yeni bir Callable <?> () başlatamazsınız, belirtmeniz gerekir açık bir tür - dolayısıyla Callable <Object> 'e bir alternatiftir.
Rahel Lüthy

4
Hiçlik sadece boş olabileceği için, Nesne herhangi bir şey olabilir.
Peter Lawrey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.