2014-04-24 16 views
5

Trong Scala immutable Vector code có một bình luận nói rằng:Private phương pháp nội tuyến

Về nguyên tắc, hầu hết các thành viên nên tin. Tuy nhiên, đặc quyền truy cập phải được lựa chọn cẩn thận để không ngăn chặn phương thức nội tuyến

  1. Tác động của quyết định nội tuyến là gì?
  2. Điều này cũng áp dụng cho Java không?

Trả lời

1

Tôi không phải là một chuyên gia trong "quyết định trình biên dịch", nhưng logic tôi sẽ nói:

Hãy tưởng tượng hai loại cổ phiếu này (trong Java ví dụ):

class A { 

    private B b; 

    public void execute(){ 
    b.execute(); 
    } 

} 

class B { 

    private int number; 

    public void execute { 
    println(number); 
    } 

} 

Nếu B execute là được biên dịch bởi trình biên dịch vào số execute của A, nó sẽ dẫn đến truy cập bất hợp pháp kể từ number là riêng tư trong B:

class A { 

    private B b; 

    public void execute(){ 
    println(number); //OUPS! number is unreachable directly from A 
    } 

} 

Vì vậy, tôi sẽ nói rằng khi bạn mong đợi một số "nội tuyến", thích tránh một số phạm vi của biến không tương thích. Tất nhiên, tôi sẽ tưởng tượng nó hữu ích trong trường hợp hiếm hoi (chủ yếu là để tối ưu hóa hiệu suất, tôi không tưởng tượng các trường hợp khác) .. có thể trường hợp bạn shew, nếu không nó sẽ dẫn đến rất nhiều "đóng gói xấu". ..

8

Điều này thường không áp dụng cho Java. Kiểm tra truy cập chỉ được thực hiện một lần trong quá trình Resolution. Khi phương thức Java được biên dịch JIT, các tham chiếu tượng trưng đã được giải quyết và xác minh. Trong thực tế, nội tuyến được thực hiện không phải trên bytecode ban đầu, nhưng trên đại diện trình biên dịch trung gian cụ thể. Vì vậy, các công cụ sửa đổi truy cập thường không có hiệu ứng phụ.

Tuy nhiên, tôi có thể viết một trường hợp thử nghiệm nhân tạo nơi một modifier private/public ảnh hưởng đến hiệu suất đáng kể:

public class Test { 
    static final Inner inner = new Inner(); 

    static class Inner { 
     int x = 1; 

     int getX1() { return x; } 
     int getX2() { return getX1(); } 
     int getX3() { return getX2(); } 
     int getX4() { return getX3(); } 
     int getX5() { return getX4(); } 
     int getX6() { return getX5(); } 
     int getX7() { return getX6(); } 
     int getX8() { return getX7(); } 
     int getX9() { return getX8(); } 

     private int getPrivate() { return getX9(); } 
     public int getPublic() { return getX9(); } 
    } 

    @GenerateMicroBenchmark 
    public int inlinePrivate() { 
     return inner.getPrivate(); 
    } 

    @GenerateMicroBenchmark 
    public int inlinePublic() { 
     return inner.getPublic(); 
    } 
} 

Benchmark    Mode Thr Cnt Sec   Mean Mean error Units 
b.Test.inlinePrivate thrpt 1  3 5 289480,928  2247,656 ops/msec 
b.Test.inlinePublic  thrpt 1  3 5 1157970,245 18473,139 ops/msec 

Hiệu ứng này được giải thích bởi một phương pháp tổng hợp access$000javac tạo để cho phép truy cập vào một thành viên riêng của lớp bên trong. Trong trường hợp kiểm tra ở trên, accessor phụ này ngăn cản nội tuyến, vì mức nội tuyến tối đa mặc định trong HotSpot là 9 (-XX:MaxInlineLevel=9). Vì không thể gọi trực tiếp từ getPrivate() từ lớp bên ngoài, phương thức access$000() bổ sung làm cho mức độ gọi thứ 10 và do đó không được gạch chân.

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