2010-02-23 37 views
14

Có thể tối ưu hóa tôi có thể áp dụng cho một trong các phương pháp của tôi, nếu tôi có thể xác định rằng một phương thức khác trong cùng một lớp không bị ghi đè. Nó chỉ là một tối ưu hóa nhỏ, vì vậy phản ánh là ra khỏi câu hỏi. Tôi có nên chỉ thực hiện một phương thức được bảo vệ trả về cho dù phương thức được đề cập có bị ghi đè hay không, sao cho một lớp con có thể làm cho nó trở về đúng?Làm thế nào để nhanh chóng xác định xem một phương pháp có bị ghi đè trong Java

+2

Làm thế nào về chỉ không tối ưu hóa nó? Có vẻ như việc tối ưu hóa không đủ quan trọng để thực sự quan trọng. –

+0

Anon: Phương pháp này được gọi là hàng trăm lần mỗi giây. – bgw

+0

Sau đó, đi để phản ánh, và bộ nhớ cache kết quả trong một lĩnh vực tư nhân. –

Trả lời

29

Tôi sẽ không làm điều này. Nó vi phạm đóng gói và thay đổi hợp đồng của những gì lớp học của bạn có nghĩa vụ phải làm mà không có người thực hiện biết về nó.

Nếu bạn phải làm điều đó, tuy nhiên, cách tốt nhất là để gọi

class.getMethod("myMethod").getDeclaringClass(); 

Nếu lớp học đó là quay trở lại là của riêng bạn, sau đó nó không ghi đè; nếu nó là cái gì khác, phân lớp đó đã ghi đè nó. Vâng, đây là sự phản ánh, nhưng nó vẫn còn khá rẻ.

Tuy nhiên, tôi thực sự thích phương thức bảo vệ phương pháp của bạn. Điều đó sẽ trông giống như sau:

public class ExpensiveStrategy { 
    public void expensiveMethod() { 
    // ... 
    if (employOptimization()) { 
     // take a shortcut 
    } 
    } 

    protected boolean employOptimization() { 
    return false; 
    } 
} 

public class TargetedStrategy extends ExpensiveStrategy { 
    @Override 
    protected boolean employOptimization() { 
    return true; // Now we can shortcut ExpensiveStrategy. 
    } 
} 
+0

Vâng, tối ưu hóa của tôi là một lợi nhuận nhỏ trên cơ sở từng trường hợp, và nó chỉ tăng tốc độ nhiều thứ bởi vì nó được gọi là hàng trăm lần mỗi giây. Với sự phản ánh, năng suất đó sẽ giảm xuống đến mức tối ưu hóa là vô nghĩa. Một câu trả lời tốt, vì vậy tôi sẽ upvoting anyways này. – bgw

+0

Nếu bạn thực sự thực sự cần nó, bạn có thể xác định xem các phương thức (s) bị quá tải thông qua trong một initialiser tĩnh và lưu trữ kết quả trong một boolean. Ngoài ra, bạn có thể thêm điều này thông qua aspectj – vickirk

+0

Sử dụng Class.getMethod để thay thế. Class.getDeclaredMethod sẽ tăng NoSuchMethodException nếu bạn hỏi về một phương thức kế thừa mà lớp con không ghi đè lên. Tất nhiên, bạn có thể sử dụng ngoại lệ như là một chỉ báo (nghèo) rằng phương pháp này không được overriden. –

2

Bạn mong đợi bao nhiêu lần chức năng được gọi trong suốt thời gian tồn tại của chương trình? Phản ánh cho một phương thức cụ thể không nên quá tệ. Nếu nó không phải là giá trị mà nhiều thời gian trong suốt cuộc đời của chương trình khuyến nghị của tôi là để giữ cho nó đơn giản, và không bao gồm tối ưu hóa nhỏ.

Jacob

+0

Nó là một phương pháp rất phổ biến. – bgw

+2

Hãy để tôi làm rõ câu trả lời của tôi. Tôi đã gợi ý rằng nếu bạn có mẫu phổ biến này, và các cá thể là tất cả cùng loại, bạn có thể cache giá trị của sự phản chiếu được thực hiện một lần. Bạn xác định cấu hình lần đầu tiên và sử dụng giá trị đó trong suốt. Bằng cách này, chi phí phản chiếu sẽ là một thời gian và các cuộc gọi sẽ là một con số lớn hơn nhiều. Nếu điều này được gọi lặp đi lặp lại trên mỗi cá thể, một biến cá thể được khai báo trong lớp cha và lười được khởi tạo trong lần gọi đầu tiên (sử dụng sự phản chiếu) có thể giúp bạn tăng cường. – TheJacobTaylor

0

Phản ánh có thể được sử dụng để xác định xem phương pháp có bị ghi đè hay không. Mã này hơi phức tạp một chút. Ví dụ, bạn cần phải biết rằng bạn có một lớp thời gian chạy là lớp con của lớp ghi đè phương thức.

Bạn sẽ thấy cùng các lớp thời gian chạy lặp đi lặp lại. Vì vậy, bạn có thể lưu kết quả của séc vào một số WeakHashMap được đánh dấu trên Class.

Xem mã của tôi trong java.awt.Component giao dịch với coalesceEvents để biết ví dụ.

+0

không có thể làm, giá trị thay đổi một chút mỗi lần. – bgw

+0

@PiPeep: Ví dụ thực tế không liên quan. Như tôi đã nói, khóa bản đồ dựa trên lớp thời gian chạy. –

1

Chú thích các lớp con ghi đè phương pháp cụ thể. @OverridesMethodX.

Thực hiện công việc phản chiếu cần thiết về tải lớp học (ví dụ: trong khối static) để bạn xuất bản thông tin qua cờ boolean cuối cùng. Sau đó, truy vấn cờ ở đâu và khi nào bạn cần.

+1

các khối tĩnh ngắt kế thừa. – bgw

+0

Tôi biết nó có mùi. Nhưng tối ưu hóa bạn muốn là đã lật đổ đa hình. –

7

Vâng, tối ưu hóa của tôi là một lợi nhuận nhỏ trên cơ sở từng trường hợp, và nó chỉ tăng tốc độ nhiều thứ bởi vì nó được gọi là hàng trăm lần mỗi giây.

Bạn có thể muốn xem chỉ những gì trình tối ưu hóa Java có thể thực hiện. Tối ưu hóa mã hóa bằng tay của bạn có thể không cần thiết.

Nếu bạn quyết định tối ưu hóa mã hóa bằng tay là cần thiết, cách tiếp cận phương pháp được bảo vệ mà bạn mô tả không phải là ý tưởng hay vì nó cho thấy chi tiết về việc triển khai của bạn.

+0

+1 Có vẻ như lời khuyên tốt cho tôi, không biết tại sao nó lại bị bỏ phiếu. – vickirk

1

có thể có cách sạch hơn để thực hiện điều này qua Strategy Pattern, mặc dù tôi không biết phần còn lại của ứng dụng và dữ liệu của bạn được mô hình hóa như thế nào nhưng có vẻ như nó có thể phù hợp.

Nó đã làm cho tôi dù sao đi nữa khi tôi gặp phải vấn đề tương tự.Bạn có thể có một heuristic quyết định chiến lược nào sẽ sử dụng tùy thuộc vào dữ liệu được xử lý.

Một lần nữa, tôi không có đủ thông tin về mức sử dụng cụ thể của bạn để xem đây có phải là quá mức cần thiết hay không. Tuy nhiên tôi sẽ không thay đổi chữ ký của lớp để tối ưu hóa cụ thể như vậy. Thông thường khi tôi cảm thấy sự thôi thúc chống lại hiện tại, tôi coi nó như một bài hát mà tôi đã không nhìn thấy một trường hợp góc khi tôi thiết kế điều đó và tôi nên refactor nó đến một giải pháp toàn diện sạch hơn.

tuy nhiên hãy cẩn thận, việc tái cấu trúc như vậy chỉ được thực hiện trên cơ sở tối ưu hóa gần như chắc chắn dẫn đến thảm họa. Nếu đây là trường hợp tôi sẽ có cách tiếp cận phản xạ gợi ý ở trên. Nó không làm thay đổi hợp đồng thừa kế, và khi thực hiện đúng cách cần được thực hiện một lần duy nhất cho mỗi lớp con yêu cầu nó cho thời gian chạy của ứng dụng.

1

Tôi biết đây là một câu hỏi hơi cũ, nhưng vì lợi ích của người dùng Google khác:

tôi đã đưa ra một giải pháp khác nhau sử dụng giao diện.

class FastSub extends Super {} 
class SlowSub extends Super implements Super.LetMeHandleThis { 
    void doSomethingSlow() { 
     //not optimized 
    } 
} 
class Super { 
    static interface LetMeHandleThis { 
     void doSomethingSlow(); 
    } 
    void doSomething() { 
     if (this instanceof LetMeHandleThis) 
      ((LetMeHandleThis) this).doSomethingSlow(); 
     else 
      doSomethingFast(); 
    } 
    private final void doSomethingFast() { 
     //optimized 
    } 
} 

hoặc cách khác xung quanh:

class FastSub extends Super implements Super.OptimizeMe {} 
class SlowSub extends Super { 
    void doSomethingSlow() { 
     //not optimized 
    } 
} 
class Super { 
    static interface OptimizeMe {} 
    void doSomething() { 
     if (this instanceof OptimizeMe) 
      doSomethingFast(); 
     else 
      doSomethingSlow(); 
    } 
    private final void doSomethingFast() { 
     //optimized 
    } 
    void doSomethingSlow(){} 
} 
0
private static boolean isMethodImplemented(Object obj, String name) 
{ 
    try 
    { 
     Class<? extends Object> clazz = obj.getClass(); 

     return clazz.getMethod(name).getDeclaringClass().equals(clazz); 
    } 
    catch (SecurityException e) 
    { 
     log.error("{}", e); 
    } 
    catch (NoSuchMethodException e) 
    { 
     log.error("{}", e); 
    } 

    return false; 
} 
+0

Bạn đã đăng chính xác câu trả lời ở đây và [tại đây] (http://stackoverflow.com/questions/4821704/java-how-to-find-if-a-method-is-overridden-from-base-class/19637356# 19637356). Nếu bạn có thể trả lời chính xác thì bạn nên đánh dấu ** câu hỏi là trùng lặp **, ** không trùng lặp câu trả lời ** quá. –

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