Có lý do nào khởi tạo lười biếng không thể được xây dựng trong Java không?


10

Vì tôi đang làm việc trên một máy chủ hoàn toàn không có trạng thái không tồn tại cho người dùng, mọi đối tượng liên quan đến Người dùng mà chúng tôi có đều được triển khai theo mọi yêu cầu.

Do đó, tôi thường thấy mình lười biếng khởi tạo các thuộc tính của các đối tượng có thể không được sử dụng.

protected EventDispatcher dispatcher = new EventDispatcher();

Trở thành ...

protected EventDispatcher<EventMessage> dispatcher;

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

Có bất kỳ lý do nào điều này không thể được xây dựng vào Java?

protected lazy EventDispatcher dispatcher = new EventDispatcher();


Như đã đề cập dưới đây trong các bình luận, tôi nhận ra một ngôn ngữ có thể phát triển về mặt lý thuyết để bao gồm hầu hết mọi thứ bạn muốn. Tôi đang tìm kiếm một phép đo thực tế về khả năng. Điều này sẽ xung đột với các tính năng khác? Việc triển khai có đủ đơn giản để làm việc tốt với JVM khi nó tồn tại không? Và thậm chí, nó là một ý tưởng tốt?


2
dunno nhưng mã ví dụ không an toàn cho chuỗi
Armand

2
@Alison synchronizedtừ khóa sẽ hoạt động giống như khi nó ở trên phương thức. Tôi tưởng tượng sẽ có một số chỗ ở của các phương pháp xây dựng phức tạp hơn. Trong trường hợp sử dụng cụ thể của tôi , do bản chất của vấn đề, với mỗi yêu cầu là thế giới riêng của nó, đồng bộ hóa là vô nghĩa.
Nicole

Trong C # Lazy nằm trong thư viện, nhưng nó được hỗ trợ bởi ngôn ngữ. sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt Java có lambdas và đại biểu và đóng cửa không? Nhân tiện, bạn muốn hỏi điều này trên SO, để Jon Skeet & co. có thể chia sẻ sự khôn ngoan của họ.
Công việc

3
Bạn có thể xây dựng khá nhiều thứ thành bất kỳ ngôn ngữ nào. Nhưng ngân sách phức tạp và danh sách tính năng bị hạn chế và các nhà thiết kế ngôn ngữ chỉ có thể bao gồm những gì họ cho là quan trọng nhất (tốt, ngoại trừ Larry Wall - đặc biệt là trong Perl 6 hay còn gọi là "Tất cả các mô hình của bạn đều thuộc về chúng tôi.").

1
Vấn đề cơ bản là Java là về ngôn ngữ được gõ tĩnh duy nhất không có cơ sở lập trình meta. Trong C, bạn có thể viết điều này dưới dạng macro trong mười phút. Trong C ++, bạn có thể viết nó dưới dạng mẫu trong khoảng hai phút. Trong Java, bạn có thể ... dán và sửa đổi.
kevin cline

Câu trả lời:


14

Đây là một câu trả lời tám trang cho câu hỏi của bạn: http://tinlizzie.org/~awarth/ con / fool07.pdf

Nếu tôi có thể thử và tóm tắt các vấn đề bằng cách thêm sự lười biếng, thì đó là trường hợp góc. Có rất nhiều cảnh báo xung quanh tác dụng phụ. Trong ví dụ của bạn, hãy xem xét, nếu nhà xây dựng có các tác dụng phụ có thể nhìn thấy như va chạm vào bộ đếm toàn cầu hoặc thực hiện I / O ... Thật khó để lý do khi nào điều đó sẽ xảy ra. Hoặc xem xét các tác dụng phụ thậm chí xấu hơn về các ngoại lệ (chúng bị ném ... khi bạn tham chiếu đối tượng lười biếng?)

Chỉ cần bỏ qua phần 6 trong bài báo trên. (Và chiêm ngưỡng tất cả các loại logic chính thức của hệ thống trên các trang bạn bỏ qua ...)


Chấp nhận câu trả lời này do độ sâu mà bài viết đề cập đến tính năng này. Cảm ơn!
Nicole

TL; DR khi bạn lập trình bạn phải biết điều gì xảy ra để ngăn chặn tác dụng phụ, với sự lười biếng, điều này thực sự có thể giúp bạn xử lý. Nếu bạn biết Hibernate và có bao nhiêu rắc rối mà một số người gặp phải với nó, chỉ cần tưởng tượng tương tự cho toàn bộ ngôn ngữ.
Walfrat

10

Tất nhiên là có thể. Trong thực tế, scala đã có chính xác tính năng này! (Scala là ngôn ngữ JVM và biên dịch thành mã byte). Đây là một phần của nguồn scala:

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

Và đây là dạng trung gian của mã được biên dịch trông như sau:

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

}


Vậy làm thế nào điều này sẽ hòa giải với câu trả lời của PT tại lập trình viên.stackexchange.com/a/110958/24257 ?
Pacerier

6

Tôi nghĩ rằng trước tiên bạn cần thêm các thuộc tính thực vào ngôn ngữ Java, thay vì dựa vào thành ngữ getX / setX. Bằng cách đó, bạn có thể đánh dấu tài sản là lười biếng (và đồng bộ hóa, chỉ đọc, v.v.).

Sắp xếp những gì được yêu cầu ở đây (Mục tiêu-C, nhưng áp dụng khái niệm).


0

Tất nhiên điều này có thể được thêm vào Java, từ khóa lười biếng có thể được thực hiện dưới dạng đường cú pháp. Tuy nhiên, thời tiết này sẽ được thực hiện tùy thuộc vào tầm nhìn của các nhà xây dựng trình biên dịch.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.