2016-01-08 11 views
5

Một dự án tôi làm việc gần đây đã chuyển từ Java 7 sang Java 8. Tôi muốn có thể tìm thấy các giao diện có một phương thức trừu tượng đơn lẻ làm ứng viên giới thiệu các giao diện chức năng vào cơ sở mã của chúng tôi. (Chú thích các giao diện hiện có dưới dạng @FunctionalInterface, mở rộng chúng từ các giao diện trong java.util.function hoặc có thể chỉ thay thế chúng).Làm cách nào tôi có thể tìm kiếm một cơ sở mã java cho các giao diện có một phương thức đơn lẻ?

+1

Điều này có sẵn dưới dạng kiểm tra trong IntelliJ. Tạo hồ sơ kiểm tra chỉ có kiểm tra này và chạy nó trên dự án của bạn. –

+0

Khi thay đổi này sẽ yêu cầu phân tích từng trường hợp, và ngoài việc bổ sung chú thích, 2 giải pháp kia đều yêu cầu tái cấu trúc quan trọng, tôi sẽ không thực hiện nó. Nếu bạn không thiết kế một thư viện, việc thêm chú thích cũng không cung cấp nhiều giá trị, vì bạn sẽ nhanh chóng thấy các vấn đề biên dịch nếu bạn chuyển đổi giao diện thành một giao diện không hoạt động trong khi nó có triển khai lambda. –

Trả lời

6

Dự án reflections có thể định vị và trả lại tất cả các lớp trên đường dẫn lớp. Dưới đây là một ví dụ làm việc:

ReflectionUtils.forNames(new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner(false)) 
                    .addUrls(ClasspathHelper.forClassLoader())) 
         .getAllTypes()).stream() 
       .filter(Class::isInterface) 
       .collect(toMap(c -> c, 
           c -> Arrays.stream(c.getMethods()) 
             .filter(m -> !m.isDefault()) 
             .filter(m -> !Modifier.isStatic(m.getModifiers())) 
             .filter(m -> !isObjectMethod(m)) 
             .collect(toSet()))) 
       .entrySet().stream() 
       .filter(e -> e.getValue().size() == 1) 
       .sorted(comparing(e -> e.getKey().toString())) 
       .map(e -> e.getKey().toString() + " has single method " + e.getValue())//getOnlyElement(e.getValue())) 
       .forEachOrdered(System.out::println); 

Các helper isObjectMethod được định nghĩa như thế này:

private static final Set<Method> OBJECT_METHODS = ImmutableSet.copyOf(Object.class.getMethods()); 
private static boolean isObjectMethod(Method m){ 
    return OBJECT_METHODS.stream() 
         .anyMatch(om -> m.getName().equals(om.getName()) && 
             m.getReturnType().equals(om.getReturnType()) && 
             Arrays.equals(m.getParameterTypes(), 
                 om.getParameterTypes())); 
} 

này không giúp bạn quay trở lại mã nguồn và thêm chú thích, nhưng nó sẽ cung cấp cho bạn một danh sách để làm việc.

+0

Điều gì sẽ xảy ra nếu giao diện ghi đè phương thức 'Đối tượng', như' Trình so sánh'? Sau đó, phương pháp nên được lọc ra. Và các phương thức 'static' cũng phải được loại bỏ. Hoặc tốt hơn, chỉ cho phép bộ lọc chuyển các phương thức 'abstract'. Và có một lý do để sử dụng 'stream (spliterator (c.getMethods(), 0), false)' thay vì 'Arrays.stream (c.getMethods())'? – Holger

+0

cập nhật với ý kiến ​​của bạn –

+0

Tại sao không '.filter (m -> Modifier.isAbstract (m.getModifiers()))' thay vì '.filter (m ->! M.isDefault()). Filter (m ->! Modifier.isStatic (m.getModifiers())) '? – Holger

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