ProgramingTip

Runnable :: new 대 new Runnable ()

bestdevel 2020. 12. 1. 19:11
반응형

Runnable :: new 대 new Runnable ()


다음 예제 중 첫 번째 작동 작동하지 않는 이유는 무엇입니까?

  • run(R::new);메서드 R.run가 호출되지 않습니다.
  • run(new R());메서드 R.run 호출됩니다.

두 예제 모두 모두 가능합니다.

public class ConstructorRefVsNew {

  public static void main(String[] args) {
      new ConstructorRefVsNew().run(R::new);
      System.out.println("-----------------------");
      new ConstructorRefVsNew().run(new R());
  }

  void run(Runnable r) {
      r.run();
  }

  static class R implements Runnable {

      R() {
          System.out.println("R constructor runs");
      }

      @Override
      public void run() {
          System.out.println("R.run runs");
      }
  }
}

출력은 다음과 가변합니다.

  R constructor runs
  -----------------------
  R constructor runs
  R.run runs

첫 번째 예제에서는 R생성자가 호출되고 람다 (객체가 아님)를 반환합니다.

어떤 방법이 예제가 사용으로 있습니까?


귀하의 run메소드는 인스턴스를 취하며 구현 과 함께 작동하는 이유를 설명합니다 .Runnablerun(new R())R

R::new과 동일하지 않습니다 new R(). Supplier<Runnable>(또는 사용할 수없는 기능적 인터페이스) 의 서명에 함께 맞을 수 있고 클래스 와 구현 된 R::new사용할 수 있습니다 .RunnableR

run수 사용할 R::new있는 메서드 의 버전은 다음과 같을 수 있습니다 (하지만 불필요하게 복잡함).

void run(Supplier<Runnable> r) {
    r.get().run();
}

왜 선택?

컴파일러가 생성자 호출을 외부로 만들 수 있기 때문에 람다 식 버전과 동일합니다.Runnable

new ConstructorRefVsNew().run(() -> {
    new R(); //discarded result, but this is the run() body
});

다음 문에도 동일하게 적용됩니다.

Runnable runnable = () -> new R();
new ConstructorRefVsNew().run(runnable);
Runnable runnable2 = R::new;
new ConstructorRefVsNew().run(runnable2);

당신이 알 수 그러나,은으로 만든은 단지 전화 메소드 본문.RunnableR::newnew R()run


사용할 방법 참조의 유효한 사용은 다음 R#run과 같이 인스턴스를 사용할 수 있습니다 (그러나이 경우에는 r인스턴스를 직접 사용하는 것이 좋습니다 ).

R r = new R();
new ConstructorRefVsNew().run(r::run);

첫 번째 예 :

new ConstructorRefVsNew().run(R::new);

다음과 다소 동일합니다.

new ConstructorRefVsNew().run( () -> {new R();} );

결과는 R의 인스턴스를 생성하고 해당 run메서드를 호출하지 않는 것입니다.


두 호출 비교 :

((Runnable)() -> new R()).run();
new R().run();

으로 ((Runnable)() -> new R())또는 ((Runnable) R::new), 당신은 만들 새를Runnable 아무것도하지 않습니다 어떤 일을 .

으로는 new R(), 당신은 생성 의 인스턴스 R클래스run 방법은 잘 정의된다.


1 실제로 R실행에 영향을 미치지 않는 객체를 생성합니다 .


main방법 을 수정하지 않고 두 번의 호출을 동일하게 처리 할 생각이었습니다 . 우리는 오버로드 할 필요 run(Runnable)와 함께 run(Supplier<Runnable>).

class ConstructorRefVsNew {

    public static void main(String[] args) {
        new ConstructorRefVsNew().run(R::new);
        System.out.println("-----------------------");
        new ConstructorRefVsNew().run(new R());
    }

    void run(Runnable r) {
        r.run();
    }

    void run(Supplier<Runnable> s) {
        run(s.get());
    }

    static class R implements Runnable { ... }
}

run메서드는 Runnable.

쉬운 경우는 new R()입니다. 이 경우 결과가 유형의 객체임을 알고 있습니다 R. R그 자체는 실행 가능하고 run메소드 가 있으며 Java가 보는 방식입니다.

그러나 통과하면 R::new다른 일이 발생합니다. 당신이 말하는 것은 Runnable누구의 run메소드가 당신이 전달한 작업을 실행하는지 와 호환되는 익명의 객체를 만드는 것입니다.

전달한 작업은 Rrun방법 이 아닙니다 . 작업은의 공동 구조자입니다 R. 따라서 다음과 같은 익명 클래스를 전달한 것과 같습니다.

new Runnable() {

     public void run() {
         new R();
     }
}

(모든 세부 사항이 동일하지는 않지만 이것은 가장 가까운 "고전적인"Java 구조입니다).

R::new을 호출하면 new R(). 그 이상도 그 이하도 아닙니다.

참고 URL : https://stackoverflow.com/questions/54072359/runnablenew-vs-new-runnable

반응형