지연 초기화를 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.