2015-07-19 27 views
5
  • dụ đầu tiênkhác biệt giữa một lĩnh vực thức tĩnh và một thể hiện lĩnh vực thức khởi tạo vào khai khi truy cập thông qua một đối tượng

    public class MyClass { 
        final int x = 2; 
    } 
    

    x

    1. thức có nghĩa là nó không bao giờ có thể được đặt sau khi khởi tạo.
    2. Được khởi tạo lúc khai báo có nghĩa là nó không thể có giá trị khác được gán cho nó sau này (ngay cả trong hàm tạo).
    3. cố định (bất kể trường hợp nào) vì giá trị của nó không thể thay đổi trong hàm tạo (hoặc bất kỳ nơi nào khác thực sự).
  • Thứ hai ví dụ

    public class MyOtherClass { 
        static final int x = 3; 
    } 
    

    x

    1. thức có nghĩa là nó không bao giờ có thể được thiết lập sau khi khởi tạo.
    2. Được khởi tạo tại khai báo có nghĩa là nó không thể có giá trị khác được gán cho nó sau này.
    3. a trường tĩnh và giá trị sẽ luôn giữ nguyên bất kể trường hợp nào.
    4. hằng số vì cả hai là staticfinal.

Câu hỏi của tôi là

sự khác biệt giữa hai là gì? (không bao gồm thời gian tạo)

Tôi có thiếu gì đó không?

+0

Đây là câu hỏi đầu tiên của tôi, hãy bình luận về phong cách và nếu tôi có thể ứng biến e nó. – naaz

+0

Nếu bạn khởi tạo biến cuối cùng tại thời điểm khai báo thì có thể là tĩnh ... – assylias

+1

Một sự khác biệt tiềm năng là nguyên thủy 'tĩnh cuối cùng 'không được sử dụng trong thời gian chạy. Trình biên dịch sẽ thay thế tất cả các lần xuất hiện của nó với giá trị trong quá trình biên dịch làm cho nó được tối ưu hóa hơn. – Codebender

Trả lời

6

Sự khác biệt giữa x trong MyClassMyOtherClass là:

  • là người đầu tiên chỉ có thể được truy cập thông qua một ví dụ MyClass và có thể có nhiều bản sao của hằng số.

  • tùy chọn thứ hai có thể được truy cập mà không cần MyOtherClass bản sao và chỉ có một bản sao có thể tồn tại.

Trong ví dụ của bạn, không có sự khác biệt thực tiễn giữa có một hoặc nhiều trường hợp của hằng số. Tuy nhiên, hãy xem xét điều này:

public class YetAnotherClass { 
    final int x; 

    public YetAnotherClass(int x) { 
     this.x = x; 
    } 
} 

... hiển thị cách hằng số thể hiện có thể có giá trị khác nhau trong các trường hợp khác nhau.


1 - Đó là cách nói quá mức. Đầu tiên, static final int x = 3; khai báo hằng số biên dịch và hằng số biên dịch có thể được sử dụng trong biểu thức trường hợp chuyển đổi, trong đó hằng số không biên dịch không thể. Thứ hai, phiên bản không tĩnh của hằng số sẽ chiếm không gian trong mỗi trường hợp của MyClass. Cuối cùng, sẽ có sự khác biệt về hành vi nếu bạn đủ daft để cố gắng thay đổi các hằng số bằng cách sử dụng sự phản chiếu. (Chỉ cần không làm điều đó ...)

+0

Có thể thoát khỏi phân tích/JIT tối ưu hóa giá trị bộ nhớ cache của x khi chỉ 'cuối cùng int x' được sử dụng? – TheLostMind

+0

Có thể. Tuy nhiên, mã vẫn sẽ cần phải làm việc nếu hằng số được truy cập bằng cách sử dụng sự phản chiếu, do đó, trường có lẽ sẽ cần phải được phân bổ anyway. –

+0

có ý nghĩa. Điều này sau đó sẽ áp dụng cho 'static final int' .. – TheLostMind

1

Mặc dù final, JVM không thực hiện bất kỳ tối ưu hóa hoặc giả định nào, do đó, mỗi phiên bản của lớp sẽ có một phiên bản x. Nếu bạn khai báo thành viên static, mỗi cá thể của lớp sẽ chia sẻ cùng một thể hiện của x vì nó được phân bổ tĩnh. Hơn nữa, như được viết (x có khả năng hiển thị gói), các lớp khác có khả năng truy cập x tĩnh, tức là, mà không có một thể hiện của lớp có sẵn.

1

Nếu bạn tạo nhiều trường hợp của cả hai loại lớp học sau đó,

Trong kịch bản đầu tiên tất cả các đối tượng của MyClass sẽ phải final x lĩnh vực riêng.

Trong trường hợp như trong trường hợp thứ hai, tất cả đối tượng của MyOtherClass sẽ có điểm cho một trường lớp final x vì nó là tĩnh trong tự nhiên.

+0

Tôi nghĩ trong trường hợp thứ hai, đối tượng 'MyOtherClass' không trỏ tới' static final x'. Nó thuộc về lớp và không phải là đối tượng. – Codebender

+0

vâng, dats đúng, tôi đã cố gắng để miêu tả giống nhau. –

1

Sự khác biệt: Tĩnh thuộc về lớp Vì vậy, bạn có thể truy cập nó mà không cần bất kỳ trường hợp nào và do đó chỉ có một bản sao của lớp đó.

Trong khi truy cập thứ hai, bạn cần thể hiện của một lớp để truy cập nó để bạn có thể có nhiều bản sao của đối tượng cuối cùng không tĩnh vì nó thuộc về đối tượng.

Bạn có thể Xác nhận với Byte Code: Đối tĩnh

Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

Đối với Non-static final

Code: 
     stack=2, locals=1, args_size=1 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: aload_0 
     5: iconst_2 
     6: putfield  #2     // Field x:I 
     9: return 
     LineNumberTable: 

Như bạn có thể thấy nó có putfield nào đặt giá trị của lĩnh vực này được xác định trong objectref (tham chiếu đến một đối tượng)

+3

Nó làm tôi khó hiểu rằng mọi người nghĩ rằng đó là một ý tưởng tốt để giải thích ngôn ngữ Java cho người mới bắt đầu bằng cách hiển thị chúng các chuỗi bytecode. –

+2

@StephenC - bảo vệ câu trả lời này .. Câu trả lời này có thể hữu ích cho những người khác (cấp trung gian?) :) .. Không chỉ là OP .. – TheLostMind

+1

@StephenC Nó chỉ dành cho tất cả mọi người :) –

Các vấn đề liên quan