지연 초기화를 Java에 빌드 할 수없는 이유가 있습니까?


10

사용자를 위해 비 지속 상태가없는 서버에서 작업하고 있기 때문에 모든 사용자 관련 개체는 모든 요청에 ​​롤아웃됩니다.

결과적으로 종종 사용하지 않을 수있는 객체의 속성을 느리게 초기화합니다.

protected EventDispatcher dispatcher = new EventDispatcher();

된다 ...

protected EventDispatcher<EventMessage> dispatcher;

public EventDispatcher<EventMessage> getEventDispatcher() {
    if (dispatcher == null) {
        dispatcher = new EventDispatcher<EventMessage>();
    }
    return dispatcher;
}

이것이 자바에 내장되지 못한 이유가 있습니까?

protected lazy EventDispatcher dispatcher = new EventDispatcher();


아래 의견에서 언급했듯이 언어는 이론적으로 원하는 모든 것을 포함하도록 진화 할 수 있음을 알고 있습니다. 나는 가능성의 실제적인 측정을 찾고 있습니다. 다른 기능과 충돌합니까? 구현이 JVM과 함께 잘 작동하기에 충분히 간단합니까? 심지어 좋은 생각입니까?


2
dunno이지만 예제 코드는 스레드로부터 안전하지 않습니다
Armand

2
@Alison synchronized키워드는 메소드에있는 것과 동일하게 작동합니다. 좀 더 복잡한 시공 방법이 필요하다고 생각합니다. 내 특정 사용 사례에서는 문제의 특성으로 인해 모든 요청이 자체 세계이므로 동기화는 의미가 없습니다.
니콜

C #에서 Lazy는 라이브러리에 있지만 언어에서 지원됩니다. sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt Java에 람다와 대의원 및 클로저가 있습니까? 그건 그렇고, Jon Skeet & co가되도록 SO에 대해 묻고 싶습니다. 그들의 지혜를 공유 할 수 있습니다.
직업

3
거의 모든 언어를 모든 언어로 만들 수 있습니다. 그러나 복잡성 예산과 기능 목록은 제한적이며 언어 디자이너는 가장 중요하게 생각하는 것만 포함 할 수 있습니다 (래리 월을 제외하고는 특히 Perl 6에서 "모든 패러다임은 우리에게 속합니다").

1
근본적인 문제는 Java가 메타 프로그래밍 기능이없는 유일한 정적 유형 언어에 관한 것입니다. C에서는 이것을 10 분 안에 매크로로 쓸 수 있습니다. C ++에서는 이것을 약 2 분 안에 템플릿으로 작성할 수 있습니다. Java에서는 붙여 넣기 및 수정할 수 있습니다.
케빈 클라인

답변:


14

다음은 귀하의 질문에 대한 8 페이지 답변입니다 : http://tinlizzie.org/~awarth/papers/fool07.pdf

게으름을 추가 할 때 발생하는 문제를 거칠게 요약 할 수 있다면 문제가 될 수 있습니다. 부작용에는 많은 경고가 있습니다. 예를 들어 생성자가 전역 카운터 충돌 또는 I / O 수행과 같은 눈에 띄는 부작용이있는 경우 고려해보십시오. 또는 예외에 대한 더 나쁜 부작용을 고려하십시오 (게으른 객체를 참조 할 때 throw됩니다 ...)

위의 논문에서 섹션 6으로 넘어가십시오. (그리고 건너 뛴 페이지의 모든 유형 시스템 형식 논리에 감탄하십시오 ...)


용지가이 기능을 다루는 깊이로 인해이 답변을 수락합니다. 감사!
Nicole

TL; DR 프로그래밍 할 때 게으름으로 부작용을 방지하기 위해 어떤 일이 발생해야하는지 알아야합니다. 최대 절전 모드와 일부 사람들이 얼마나 많은 문제를 겪고 있는지 알고 있다면 전체 언어에 대해 동일하게 상상해보십시오.
Walfrat

10

물론 가능합니다. 실제로 스칼라는 이미이 기능을 가지고 있습니다! (Scala는 JVM 언어이며 바이트 코드로 컴파일됩니다). 스칼라 소스는 다음과 같습니다.

class Foo {
  lazy val bar = "Hello World"
}

그리고 컴파일 된 코드 의 중간 형태 는 다음과 같습니다.

scalac -Xprint:icode Foo.scala

[[syntax trees at end of icode]]// Scala source: Foo.scala
package <empty> {
  class Foo extends java.lang.Object with ScalaObject {
    @volatile protected var bitmap$0: Int = 0;
    lazy private[this] var bar: java.lang.String = _;
    <stable> <accessor> lazy def bar(): java.lang.String = {
      if (Foo.this.bitmap$0.&(1).==(0))
        {
          Foo.this.synchronized({
            if (Foo.this.bitmap$0.&(1).==(0))
              {
                Foo.this.bar = "Hello World";
                Foo.this.bitmap$0 = Foo.this.bitmap$0.|(1);
                ()
              };
            scala.runtime.BoxedUnit.UNIT
          });
          ()
        };
      Foo.this.bar
    };
    def this(): Foo = {
      Foo.super.this();
      ()
    }
  }

}


그렇다면 이것은 programmers.stackexchange.com/a/110958/24257 의 PT 답변과 어떻게 조화를 이룰 까요?
Pacerier

6

getX / setX 관용구에 의존하기보다는 Java 언어에 실제 속성을 추가해야한다고 생각합니다. 그렇게하면 속성을 게으른 것으로 표시 할 수 있습니다 (동기화, 읽기 전용 등).

여기서 요구되는 것의 종류 (Objective-C, 개념이 적용됨).


0

물론 이것은 자바에 추가 될 수 있으며 키워드 lazy는 구문 설탕으로 구현 될 수 있습니다. 그러나 구현 여부는 컴파일러 빌더의 비전에 따라 다릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.