자바의 숨겨진 기능


295

C #의 숨겨진 기능을 읽은 후 Java의 숨겨진 기능은 무엇입니까?


17
이러한 숨겨진 기능을 사용하는 것이 항상 좋은 생각은 아닙니다. 종종 그들은 코드를 읽는 사람들에게 놀라고 혼란스러워합니다.
Kevin Bourrillion

1
C # 질문과 같이 질문 본문에서 답변을 깔끔하게 정리해야합니다.
ripper234

답변:


432

Double Brace Initialization 은 몇 달 전에 처음 발견했을 때 놀랐습니다.

ThreadLocals 는 일반적으로 스레드 별 상태를 저장하는 방법으로 널리 알려져 있지 않습니다.

JDK 1.5 Java는 잠금을 뛰어 넘어 매우 잘 구현되고 강력한 동시성 도구를 가지고 있기 때문에 java.util.concurrent에 있으며 특히 흥미로운 예는 비교 를 구현하는 스레드 안전 기본 요소를 포함 하는 java.util.concurrent.atomic 서브 패키지입니다. 스왑 작업을 수행하고 이러한 작업의 실제 기본 하드웨어 지원 버전에 매핑 할 수 있습니다.


40
이중 괄호 초기화 ... 이상하다 ... 특정 관용구를 너무 광범위하게 채택하는 것에주의해야한다. 왜냐하면 실제로 객체의 익명 서브 클래스를 생성하기 때문이다. java.util.concurrent는 정말 훌륭한 패키지입니다.
MB.

6
나는 자바 를 가르쳤다 . 그리고 이것은 내가이 문법을 처음
접했을

49
이 "이중 괄호"관용구로 초기화 된 컬렉션에 대한 참조를 유지하거나 실제 이름-이니셜 라이저 블록이있는 익명 클래스로 호출하는 경우 암시 적으로 외부 객체에 대한 참조를 보유하여 불쾌한 메모리가 발생할 수 있습니다. 누출. 나는 그것을 피하는 것이 좋습니다.
ddimitrov

51
"이중 괄호 초기화"는 익명의 내부 클래스를 생성하여 실제로 발생하는 상황을 파악하고 내부 클래스가 이러한 방식으로 사용되는 것처럼 들리게하는 매우 완고한 이름입니다. 이것은 내가 숨겨져있는 것을 선호하는 패턴입니다.
erickson

11
거의 실제로는 정적 블록이 아니라 다른 시간에 실행되기 때문에 다른 "초기화 기 블록"입니다 (자세한 내용은 답변에 포함 된 링크 참조)
Boris Terzic

279

유형 모수 분산의 합집합 :

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

예를 들어 Comparable과 Collection 모두의 매개 변수를 사용하려는 경우 :

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

이 고려 된 메소드는 주어진 두 컬렉션이 같거나 그 중 하나에 주어진 요소가 포함되어 있으면 true를, 그렇지 않으면 false를 반환합니다. 주목할 점은 인수 b1 및 b2에 대해 Comparable 및 Collection의 메소드를 호출 할 수 있다는 것입니다.


내가 가장 좋아하는 것은 Appendable Charsequence를 허용하는 메소드가 필요할 때입니다.
Neil Coffey

5
& 대신 "OR"을 가질 수 있습니까?
mainstringargs 2016 년

9
@Grasper : 아니요, 해당 컨텍스트에는 OR (비 연합)이 제공되지 않습니다. 그러나 Either <A, B>와 같은 분리 된 공용체 데이터 유형을 대신 사용할 수 있습니다. 이 유형은 Pair <A, B> 유형의 이중입니다. 그러한 데이터 유형의 예는 Functional Java 라이브러리 또는 Scala 코어 라이브러리를 참조하십시오.
Apocalisp 2016 년

5
당신은 MUST 하나 개의 클래스와 여러 인터페이스를 확장했다한다 -> 공용 클래스 바즈는 <T는 clazz에 & 인터페이스 1 & InterfaceI ... 그리고 클래스가 아닌 바즈가 확장 <T는 Clazz1 & 클래지 확장>
JohnJohnGa

220

다른 날 인스턴스 초기화 프로그램에 놀랐습니다. 코드 접힌 메소드를 삭제하고 여러 인스턴스 이니셜 라이저를 만들었습니다.

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

main메소드를 실행하면 다음 이 표시됩니다.

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

여러 생성자가 있고 공통 코드가 필요한 경우 유용 할 것입니다.

또한 수업 초기화를 위해 구문 설탕을 제공합니다.

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
호출해야하는 명시 적 메소드에 비해이 방법의 장점은 누군가가 생성자를 나중에 추가하는 경우 init ()를 호출하는 것을 기억할 필요가 없다는 것입니다. 자동으로 수행됩니다. 이것은 미래의 프로그래머에 의한 오류를 방지 할 수 있습니다.
Mr. Shiny and New 安 宇

40
또한 init () 메소드와 달리 최종 필드를 초기화 할 수 있습니다.
Darron

2
클래스를 확장하고 다양한 어린이를 인스턴스화하면 어떻게 되나요? 여전히 같은 방식으로 작동합니까?
Kezzer

12
사람들은 종종 인증을 거부하고 (예 : stackoverflow.com/questions/281100/281127#281127 ) 특히 기술적 장점에 의문을 갖습니다. 그러나 더 많은 프로그래머가 SCJP를 위해 공부했다면, 이것이 많은 사람들에게 "숨겨진 기능"으로 간주되지는 않을 것입니다. ;-)
Jonik

12
"24 시간 자바"책에도이 "분명한 기능"이 있다고 생각합니다. 많은 사람들 읽기 :) (
오즈

201

JDK 1.6_07 +에는 VisualVM (bin / jvisualvm.exe)이라는 앱이 포함되어 있습니다.이 도구는 많은 도구 위에있는 멋진 GUI입니다. JConsole보다 포괄적 인 것 같습니다.


그리고 Jconsole 플러그인을 사용할 수있는 플러그인 (netbeans thingie)이 있습니다. 아주 좋아요
Thorbjørn Ravn Andersen 님이

VisualVM은 얇게 썬 빵 이후 가장 좋습니다. 너무 나쁘다 JDK 1.5에 대해 실행할 때 모든 기능을 갖추고 있지는 않습니다.
sandos

어떤 상황에서는 VisualVM이 느리거나 사용할 수 없습니다. 상업용 YourKit에는이 문제가 없지만 불행히도 무료는 아닙니다.
Roalt

JDK 1.6.0_22 이상의 최신 버전의 Visual VM이 훨씬 향상되었습니다. JDK1.7이 더 나은 버전을 가지고 있다고 확신합니다.
djangofan


156

대부분의 사람들에게 Java 개발자 입장에서 인터뷰 한 블록은 매우 놀랍습니다. 예를 들면 다음과 같습니다.

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

goto자바에서 누가 키워드라고 했습니까? :)


2
글쎄, 나는 여러 가지 방법으로 할 수있는 옵션을 선호합니다. 예를 들어 System.exit (1); 서블릿과 EJB 코드에서 System.exit ()를 제거해야한다는 의미는 아닙니다. JDK에서?
Georgy Bolyuba

31
경우에 따라 중첩 루프 구조 내에서 외부 루프의 다음 반복을 계속하는 것이 유용 할 수 있습니다. 이것은이 기능을 합리적으로 사용하는 것입니다.
alasdairg

75
많은 프로그래머들에게 (아마도 마찬가지로) 알려지지 않은 것은 실제로 모든 오래된 블록에서 레이블을 지정하고 벗어날 수 있다는 것입니다. 루프 일 필요는 없습니다. 임의의 블록을 정의하고 레이블을 지정하고 break를 사용할 수 있습니다.
Neil Coffey

27
전혀 진행되지 않으며 이전 반복으로 만 돌아갈 수 있습니다 (즉 : 앞으로 이동할 수 없음). 이는 반복이 false를 리턴 할 때 발생하는 메커니즘과 동일합니다. java가 goto라고 말하는 것은 컴파일러가 JUMP 명령어를 생성하는 모든 언어에 goto 문이 있다고 말하는 것과 같습니다.
좀비

4
따라서 문제를 해결하고 디자인을 통해 생각하는 적성보다는 Java 퀴즈를 기반으로 인터뷰합니다. 나는 당신의 회사와 절대 인터뷰하지 않을 것입니다. :)
Javid Jamae

144

방법에 대한 공변 반환 형식 JDK 1.5부터 장소에왔다? 그것은 섹시하지 않은 추가이기 때문에 꽤 잘 알려지지 않았지만, 이해하기 때문에 제네릭이 작동하려면 절대적으로 필요합니다.

본질적으로, 컴파일러는 이제 서브 클래스가 재정의 된 메소드의 리턴 유형을 원래 메소드의 리턴 유형의 서브 클래스로 좁힐 수있게합니다. 따라서 이것은 허용됩니다.

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

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

당신은 서브 클래스의 호출 할 수있는 values방법 및 정렬 된 스레드 안전 확보 SetString의를 다운 캐스트하지 않고도 받는 사람 ConcurrentSkipListSet.


사용 예를 제공 할 수 있습니까?
Allain Lalonde

24
나는 이것을 많이 사용합니다. clone ()이 좋은 예입니다. Object를 반환해야합니다. 즉 (List) list.clone ()과 같이 말해야합니다. 그러나 List clone () {...}으로 선언하면 캐스트가 필요하지 않습니다.
Jason Cohen

142

finally 블록에서 제어를 전송하면 예외가 발생하지 않습니다. 다음 코드는 RuntimeException을 발생시키지 않으며 손실됩니다.

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

에서 http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html


7
불쾌하지만 최종적으로 작동하는 방식의 논리적 결과이기도합니다. try / catch / finally flow control은 의도 한대로 작동하지만 특정 한계 내에서만 작동합니다. 마찬가지로 catch / finally 블록 내에서 예외가 발생하지 않도록주의해야합니다. 그렇지 않으면 원래 예외도 버려집니다. try 블록 내에서 System.exit ()를 수행하면 finally 블록이 호출되지 않습니다. 정상 흐름을
끊으면

마지막으로 {return; } 그러나 마지막으로 {return without code}. 이것은 예외가 발생할 때 실행되도록 의도 된 논리적 인 것이며, 예외 처리기로서의 리턴의 유일한 의미는 예외를 무시하고 실제로 리턴하는 것입니다.
extraneon

21
이것은 숨겨진 기능보다 더 많은 "gotcha"처럼 보이지만이 방법을 사용하는 방법은 있지만이 방법을 사용하는 것은 좋지 않습니다.
davenpcj 2016 년

이 작업을 수행하면 Eclipse에서 경고가 표시됩니다. 저는 이클립스에 있습니다. 예외를 잡으려면 예외를 잡으십시오.
helios

그것은 메소드 중간에서 리턴되는 더티 코드에 대해 지불하는 것입니다. 그러나 여전히 좋은 예입니다.
Rostislav Matl

141

아무도 null 검사가 필요하지 않은 방식으로 구현 된 인스턴스를 언급 한 적이 없습니다.

대신에:

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

그냥 사용하십시오 :

if( aObject instanceof String )
{
    ...
}

9
이것이 거의 알려지지 않은 기능이라는 것은 부끄러운 일입니다. 첫 번째 코드 블록과 비슷한 많은 코드를 보았습니다.
Peter Dolberg 2009

4
Java에는 보지 못하거나 참조 할 수없는 특수 (숨겨진) null 유형이 있기 때문입니다.
Nick Hristov

더 나쁜 것은 C / C ++에서 freeing 또는 deleteing 하기 전에 null을 확인 하는 것입니다. 이러한 기본 개념.
Thomas Eding

134

열거 형의 메소드와 생성자를 허용하면 나를 놀라게했습니다. 예를 들면 다음과 같습니다.

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

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

특정 열거 형 값이 메서드를 재정의 할 수 있도록하는 "일정한 특정 클래스 본문"을 가질 수도 있습니다.

더 많은 문서는 여기에 있습니다 .


20
실제로 굉장한 기능-열거를 OO로 만들고 많은 초기화 문제를 매우 깨끗한 방식으로 해결합니다.
Bill K

5
싱글 톤으로 열거? 값이 하나 뿐인 열거 형?
Georgy Bolyuba

6
조지 : 싱글 톤은 하나의 값을 가진 객체가 아니라 객체의 한 인스턴스입니다.
dshaw

20
@Georgy : Joshua Bloch의 Effective Java (제 2 판)의 항목 3도 참조하십시오. "이 접근 방식이 아직 널리 채택되지는 않았지만 단일 요소 열거 형 유형이 싱글 톤을 구현하는 가장 좋은 방법입니다."
Jonik

3
작은 nitpick : mAge최종적이어야합니다. 열거 형이 아닌 최종 필드의 이유는 거의 없습니다.
Joachim Sauer

121

제네릭 메서드의 형식 매개 변수는 다음과 같이 명시 적으로 지정할 수 있습니다.

Collections.<String,Integer>emptyMap()

10
그리고 신에 의해 그것은 추악하고 혼란입니다. 그리고 타입 안전과 관련이 없습니다.
Chris Broadfoot

8
나는 이것을 좋아한다. 1 년에서 2 년 안에 코드를 유지해야하는 빈곤층에게는 코드를 좀 더 명확하고 명확하게 만듭니다.
extraneon

6
이것은 당신이 같은 정적 제네릭 메소드를 선언 한 상황에서 실제로 매우 유용합니다 public static <T> T foo(T t). 그런 다음 전화를 걸 수 있습니다Class.<Type>foo(t);
Finbarr

어떤 이유로 이것은 정적으로 가져온 메소드에서 작동하지 않는 것 같습니다. 왜 그런지 궁금합니다.
oksayt

이것은 삼항 if를 리턴과 함께 사용할 때 특히 유용합니다. 예를 들면 return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList(). 간단한 Collections.emptyMap ()이 컴파일 오류를 발생시키는 일부 메소드 호출에도 유용합니다.
Andreas Holstenson 2016 년

112

열거 형을 사용하여 인터페이스를 구현할 수 있습니다.

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

편집 : 몇 년 후 ....

이 기능을 여기에 사용합니다

public enum AffinityStrategies implements AffinityStrategy {

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

인터페이스를 사용하여 개발자는 자신의 전략을 정의 할 수 있습니다. enum수단을 사용하여 내장 컬렉션 (5 개)을 정의 할 수 있습니다.


27
이건 광기 야 (+1)
Cephalopod

12
@Arian 이것은 광기가 아닙니다. 이. 입니다. JAVAAAAAAHHHH!
slezica

1
WHAAAAAT 아니요, Adrian과 함께 있습니다. 이것은 Java가 아닙니다. 이건 광기 야 나는 이것을 사용하기 위해 죽어 가고있다.
slezica

104

Java 1.5부터 Java는 이제 가변 arity의 함수를 작성하기 위해 훨씬 더 깔끔한 구문을 갖습니다. 따라서 배열을 전달하는 대신 다음을 수행 할 수 있습니다.

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

막대는 자동으로 지정된 유형의 배열로 변환됩니다. 큰 승리는 아니지만 그럼에도 불구하고 승리.


23
이것에 대한 중요한 점은 메소드를 호출 할 때 다음과 같이 작성할 수 있다는 것입니다. foo ( "first", "second", "third")
Steve Armstrong

9
옛 헬로우 월드를 다시 쓸 수 있습니다. public static void main (String ... args) {System.out.println ( "Hello World!"); }
Karussell

@Karussell 아마도, 그러나 논쟁은 관련이없는 것처럼 보일 것입니다 : p
Kelly Elton

93

내가 가장 좋아하는 것 : 모든 스레드 스택 추적을 표준 출력으로 덤프하십시오.

창 : CTRL- Break자바 cmd를 / 콘솔 창에

유닉스 : kill -3 PID


15
유닉스에서도 ctrl- \. 또는 JDK에서 jstack을 사용하십시오.
Tom Hawtin-tackline

9
고마워, 당신은 내 키보드에 Break열쇠 가 있다고 나에게 가르쳤다 .
Amy B

2
창에서 CTRL-BREAK는 현재 콘솔 창에서 프로세스를 실행중인 경우에만 작동합니다. JAVA_HOME / bin / jstack.exe를 대신 사용할 수 있습니다. Windows 프로세스 ID를 제공하십시오.
Javid Jamae

나는 그것이 죽었다고 생각 -SIGQUIT
Nick Hristov

@Nick, 예 SIGQUIT는 일반적으로 신호 # 3입니다.
Chris Mazzola

89

두 사람이 인스턴스 이니셜 라이저에 대해 게시했으며 다음과 같이 유용합니다.

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

빠르고 간단한 작업을 수행하는 경우지도를 빠르게 초기화 할 수 있습니다.

또는이를 사용하여 빠른 스윙 프레임 프로토 타입을 만듭니다.

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

물론 남용 될 수 있습니다 :

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

어떻게 든 "with"키워드 (실제로 기능성)가 Java에 추가 된 것처럼 보입니다. 배열의 init을 컬렉션에 사용할 수 없기 때문에 최근에 매우 유용했습니다. 감사!
PhiLho

15
그러나 이것을 사용하면 부작용이 있습니다. 익명 개체가 만들어 지는데 항상 좋은 것은 아닙니다.
amit

17
더 자세히 살펴본 후에는 "Abused"버전조차도 자연스럽게 중첩되어 있다는 사실에 이상하게 끌리고 있습니다.
Bill K

4
그렇습니다-나는 '거품이있는'버전을 아주 좋아합니다. 매우 명확하고 읽기 쉽다고 생각하지만 아마도 나뿐입니다.
barryred

3
GUI의 계층 구조를 반영하는 코드의 계층 구조는 일련의 메소드 호출에 비해 크게 개선되었습니다.
opsb

88

동적 프록시 (1.3에 추가)를 사용하면 런타임에 인터페이스에 맞는 새 유형을 정의 할 수 있습니다. 놀랍도록 여러 번 유용합니다.


10
동적 프록시는 Foo 인터페이스를 작성하고 기본 "FooImpl"클래스를 사용하여 어디서나 사용할 수있는 좋은 이유입니다. 처음에는 추악한 것처럼 보일 수 있지만 ( "Foo라는 클래스 만있는 이유는 무엇입니까?") 단위 테스트를위한 미래의 유연성과 모의 능력 측면에서 이점은 유용합니다. 비 인터페이스에도 적용 할 수있는 방법이 있지만 일반적으로 cblib와 같은 추가 항목이 필요합니다.
Darien

82

최종 초기화는 연기 될 수 있습니다.

복잡한 논리 리턴 값이 있더라도 항상 설정됩니다. 케이스를 놓치고 실수로 null을 반환하는 것은 너무 쉽습니다. null을 반환하는 것을 불가능하게하지는 않지만 의도적으로 있음을 분명히합니다.

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

놀랍습니다. 집합이 어디에서 발생하더라도 "최종 변수의 값을 한 번 설정할 수 있습니다"라고 말할 수 있습니까?
David Koelle

29
네,하지만 더 강하게 "최종 변수의 값은 한 번 설정해야합니다"
Allain이 Lalonde

6
+1 동의, 이것은 컴파일 타임에 오류를 발견하는 데 유용한 또 다른 도구이며, 프로그래머가 어떤 이유로 사용하기에 부끄러워하는 것입니다. Java 5부터는 'final'에도 스레드 안전성이 영향을 미치므로 생성자 중에 최종 변수를 설정할 수 있다는 점은 매우 중요합니다.
Neil Coffey

4
이 특정 방법의 경우 여러 반환을 사용합니다. 실제로 이것이 적용 가능한 대부분의 경우 아마도 별도의 메소드로 리팩터링하고 여러 개의 리턴을 사용합니다.
ripper234

나는 이것을 좋아한다! 나는 실패 할 것이라고 생각했기 때문에 항상 최종 키워드를 삭제했습니다. 감사!
KARASZI István

62

자바의 또 다른 "간과 된"기능은 JVM 그 자체라고 생각합니다. 아마도 가장 좋은 VM 일 것입니다. 또한 재미 있고 유용한 언어 (Jython, JRuby, Scala, Groovy)를 지원합니다. 이러한 모든 언어는 쉽고 완벽하게 협력 할 수 있습니다.

스칼라 케이스와 같이 새 언어를 디자인하면 기존의 모든 라이브러리를 즉시 사용할 수 있으므로 언어는 처음부터 "유용합니다".

이러한 모든 언어는 HotSpot 최적화를 사용합니다. VM은 매우 잘 모니터링되고 디버깅 가능합니다.


18
아니요. 실제로는 매우 좋은 VM이 아닙니다. JAVA를 실행하도록 설계되었습니다. 유형이없는 동적 및 기능적 언어는 제대로 작동하지 않습니다. VM을 사용하려면 .NET / Mono를 사용해야합니다. 그것은 모든 언어와 함께 작동하도록 설계되었습니다 ...
Hades32

14
실제로 JVM은 Java 바이트 코드를 실행하도록 설계되었습니다. 대부분의 최신 언어를 Java 바이트 코드로 컴파일 할 수 있습니다. Java Bytecode에서 부족한 사항은 동적 언어 지원, 포인터 및 꼬리 재귀 지원입니다.
mcjabberz

12
@ Hades32 : 실제로 .NET VM은 JVM과 매우 비슷합니다. 상대적으로 최근에 (DLR 사용) 동적 언어 만 지원했으며 Java 7도 그 지원을 받고 있습니다. 그리고 .NET의 고전적인 "모든 언어"(C #, Visual Basic.NET 등)는 모두 거의 동일한 기능 세트를 가지고 있습니다.
Joachim Sauer

13
JVM은 제네릭을 지원하지 않지만 .NET VM은 제네릭을 지원하지 않습니다. JVM이 가장 좋은 곳은 없습니다.
Blindy

3
JVM이 직접 지원하지 않는 특정 언어 기능에 대한 불만을 할인하지는 않지만 안정성, 플랫폼 간 일관성 및 우수한 성능이 JVM이 추가 포인트를 얻는 이유보다 훨씬 높다고 생각하는 경향이 있습니다. AS / 400을 포함한 많은 플랫폼에서 수년 동안 서버 측 Java로 작업 해 왔으며 완전히 잊어 버릴 수있었습니다. 버그는 항상 수정할 수있는 코드에 있습니다. 단순히 충돌하지 않습니다.
Rob Whelan

58

인터페이스를 구현하지 않더라도 익명 서브 클래스를 정의하고 직접 메소드를 호출 할 수 있습니다.

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

@Vuntic-필요한 컨텍스트 내에서 간단한 클래스를 정의 할 수 있습니다.
ChaosPandion

1
@ 카오스, 그런데 왜? 유용한 실제 사례가 있습니까?
Thorbjørn Ravn Andersen '12

10
@Wouter-이 경우 익명 객체 ( start()) 에서 호출 된 메소드 는 실제로 서브 클래스에 정의되어 있지 않습니다 ...
Axel

실제로 이것은 필요한 설정을 수행하고 작성한 메소드를 호출 한 다음 분류를 수행하는 기본 클래스를 확장하는 경우 매우 유용한 기능입니다. 기본 클래스에서 메소드를 호출하여 일을 시작하십시오 (아마도 같은 이름을 지정하지 않을 것입니다). 예를 들어 사용 (하지 정의)이있다 여기에
AmigoNico

56

asList의 의 방법은 java.util.Arrays가변 인자, 일반적인 방법과 오토 박싱의 좋은 조합을 할 수 있습니다 :

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

15
반환 된 목록을 List 생성자로 감싸고 싶다면 그렇지 않으면 int의 크기가 고정됩니다 (배열에 의해 지원되므로)
KitsuneYMG

2
Arrays.asList당신이 할 수있는 특별한 기능이 set()요소가 아닌 add()이상 remove(). 따라서 일반적으로 목록을 수정할 수 있는지 여부에 따라 a new ArrayList(...)또는로 Collections.unmodifiableList(...)묶습니다.
Christian Semrau

53

키워드를 사용 하여 내부 클래스에서 클래스를 포함하는 필드 / 방법에 액세스합니다. 아래에서 다소 고안된 예에서는 익명 내부 클래스의 컨테이너 클래스의 sortAscending 필드를 사용하려고합니다. this.sortAscending 대신 ContainerClass.this.sortAscending을 사용하면 트릭을 수행합니다.

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
이름을 섀도 잉 한 경우 (필요한 경우 메소드 매개 변수 이름으로)에만 필요합니다. 다른 인수를 호출 한 경우 'this'를 사용하지 않고 Container 클래스의 sortAscending 멤버 변수에 직접 액세스 할 수 있습니다.
sk.

7
예를 들어, 둘러싸는 클래스에 대한 참조를 갖는 것이 여전히 유용합니다. 당신이 어떤 방법이나 해석기에 전달 해야하는 경우.
PhiLho

와 같은 버튼 리스너로부터 컨텍스트를 얻기 위해 종종 안드로이드 레이아웃 개발에 사용됩니다 MyActivity.this.
espinchi

52

실제로 기능은 아니지만 일부 웹 페이지에서 최근에 발견 한 재미있는 트릭입니다.

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

    System.exit(0);
  }
}

유효한 Java 프로그램입니다 (경고를 생성하더라도). 이유를 모르면 Gregory의 답변을 참조하십시오! ;-) 글쎄, 여기에 구문 강조 표시도 힌트를줍니다!


15
:) 코멘트와 깔끔한, 라벨
Thorbjørn Ravn 안데르센

46

이것은 "숨겨진 기능"이 아니며 유용하지는 않지만 다음과 같은 경우에는 매우 흥미로울 수 있습니다.
Class sun.misc.Unsafe- Java에서 직접 메모리 관리 를 구현할 수 있습니다. 당신이 많이 시도한다면 이것은)

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
그는 일입니다 * 정말 그 자체로 자바 언어의 일부가 아닌 API.
DW.

Unsafe에는 생성자 malloc / realloc / free 스타일 메소드를 호출하지 않고 객체를 생성하는 것과 같은 여러 가지 흥미로운 방법이 있습니다.
피터로 레이

특히 putDouble (long address, double d)과 같은 메모리 위치의 원시 getter 및 setter를 좋아합니다.
다니엘

42

숨겨진처럼 스윙 I에서 작업 할 때 Ctrl- Shift-F1 기능입니다.

현재 창의 구성 요소 트리를 덤프합니다.
(키 입력을 다른 것으로 바인딩하지 않았다고 가정합니다.)


1
창 관리자가 해당 키에 바인딩 된 것이있을 가능성이 높습니다. 그놈은 바인딩하지 않으므로 KDE를 실행하여 '데스크탑 13으로 전환'한다고 가정합니다. 제어판, 지역, 키보드 바로 가기로 이동하여 Shift-Ctrl-F1
Devon_C_Miller

40

모든 클래스 파일은 16 진 값 0xCAFEBABE로 시작합니다. 로 유효한 JVM 바이트 코드로 식별합니다.

( 설명 )


38

내 투표는 java.util.concurrent 로 이동합니다 동시 수집 및 유연한 실행 프로그램 되며 다른 스레드 풀, 예약 된 작업 및 조정 된 작업이 가능합니다. DelayQueue는 내가 개인적으로 좋아하는 것으로 지정된 지연 후에 요소를 사용할 수 있습니다.

java.util.Timer 및 TimerTask를 안전하게 놓을 수 있습니다.

또한 정확하게 숨겨져 있지는 않지만 날짜 및 시간과 관련된 다른 클래스와 다른 패키지로 제공됩니다. java.util.concurrent.TimeUnit은 나노초, 마이크로 초, 밀리 초 및 초 사이를 변환 할 때 유용합니다.

일반적인 someValue * 1000 또는 someValue / 1000보다 훨씬 잘 읽습니다.


최근에 발견 CountDownLatch하고 CyclicBarrier- 그래서 유용합니다!
Raphael

37

언어 수준의 어설 션 키워드


19
assert의 문제점은 런타임 중에 스위치를 켜야한다는 것입니다.
extraneon

10
그러나 비활성화되어 있으면 마치없는 것 같습니다. 코드에 원하는만큼의 어설 션을 추가 할 수 있으며 비활성화 된 경우 성능 저하가 없습니다.
라비 왈라 우

5
나는 그것이 주장에 대해 좋은 것이라고 믿는다 : 그것은 페널티없이 끌 수있다.
andref

문제는 당신이 실수로 assert에서 부작용을 구현했다면, ur 프로그램이 작동하기 위해 assertion을 설정해야한다는 것입니다.
Chii

어설 션이 켜져 있는지 감지하려면 {boolean assertsOn = false; assert assertsOn = true; if (assertsOn) {/ * 복잡한 검증 * /}}. 또한 assert 상태가 예상되지 않은 경우 예외를 기록하거나 발생시킬 수 있습니다.
페라 콜로

37

실제로 Java 언어의 일부는 아니지만 Sun의 JDK와 함께 제공되는 javap 디스어셈블러는 널리 알려 지거나 사용되지 않습니다.


36

1.5에 for-each 루프 구성이 추가되었습니다. 나는 <3이다.

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

중첩 인스턴스에서 사용할 수 있습니다.

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

for-each 구문은 반복자보다는 색인 변수를 숨기는 배열에도 적용 할 수 있습니다. 다음 메소드는 int 배열의 값 합계를 리턴합니다.

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

Sun 설명서에 링크


30
i대부분의 사람들이 내가 배열 요소가 아닌 색인이되기를 기대하기 때문에 여기에 사용하는 것이 혼란 스럽다고 생각 합니다.
cdmckay

그래서 ... int sum (int [] array) {int result = 0; for (int element : array) {result + = 요소; } 결과 반환; }
Drew

28
이것에 대해 나를 미치게하는 유일한 것은 실제로 루프 카운트 값에 액세스하기위한 키워드를 만드는 것이 쉽지만 보이지는 않는다는 것입니다. 두 배열을 반복하고 첫 번째 값을 기반으로 두 번째를 변경하려면 두 번째 배열에 오프셋이 없으므로 이전 구문을 사용해야합니다.
Jherico

6
JNDI에서 사용되는 것과 같은 열거 형에서도 작동하지 않는 것은 부끄러운 일입니다. 다시 이터레이터로 돌아 왔습니다.
extraneon

3
@extraneon : Collections.list (Enumeration <T> e)를보십시오. foreach 루프에서 열거를 반복하는 데 도움이됩니다.
베르너 레만

34

나는 개인적으로 java.lang.Void매우 늦게 발견했습니다 -예를 들어 제네릭과 함께 코드 가독성을 향상시킵니다.Callable<Void>


2
좀 빠지는. 특정 시점에서 Executors.newSingleThreadExecutor (). submit (new Callable <Void> () {..})-새 Callable <?> ()을 인스턴스화 할 수 없습니다. 명시 적 형식이므로 Callable <Object>의 대안입니다.
Rahel Lüthy 2016 년

4
Void는 null 일 수 있고 Object는 무엇이든 될 수 있으므로 Void는 Object보다 더 구체적입니다.
피터로 레이
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.