Câu hỏi Java: loại bỏ cảnh báo “So sánh là loại thô”


Giả sử tôi có một phương thức gọi là foo lấy 2 Object làm tham số. Cả hai đối tượng có cùng loại và cả hai thực hiện giao diện tương đương.

void foo(Object first, Object second){

    if (!first.getClass().isInstance(second))   //first and second of the same type
        return;

    Comparable firstComparable = (Comparable)first;  //WARNING
    Comparable secondComparable = (Comparable)second;  //WARNING

    int diff = firstComparable.compareTo(secondComparable);  //WARNING
}

Cảnh báo 2 đầu tiên là:

So sánh là một loại thô. Tham chiếu đến loại generic   nên được tham số hóa

Cảnh báo cuối cùng:

Kiểu an toàn: Phương thức compareTo (Object) thuộc về kiểu thô   So sánh. Tham chiếu đến loại generic So sánh phải là   tham số hóa

Làm thế nào tôi có thể refactor mã của tôi để loại bỏ các cảnh báo?

CHỈNH SỬA: Tôi có thể làm điều đó mà không thay đổi chữ ký của phương thức foo không?


7
2017-08-10 09:33


gốc


@overbose: tại sao không thay đổi tham số chức năng của đối tượng để so sánh? - Emil
@Emil gây ra cùng một Cảnh báo Comparable is a raw type - oliholz
@ 0verbose: tại sao bạn muốn loại bỏ cảnh báo? Ngay cả khi bạn sử dụng Generics vẫn còn đó chỉ là một cú pháp đường và đúc sẽ bất kỳ như thế nào diễn ra. Tại sao bạn không chỉ đơn giản là ngăn chặn các cảnh báo? - Emil
@Emil: đó chỉ là sự tò mò. Ngay cả với cảnh báo mã hoạt động tốt. - Heisenbug


Các câu trả lời:


Bạn phải nói với trình biên dịch rằng chúng cùng loại và có thể so sánh được. Nếu bạn không thể thay đổi chữ ký, bạn có thể thêm một phương thức để tương thích ngược.

@SuppressWarnings("unchecked")
static void foo(Object first, Object second) {
    foo((Comparable) first, (Comparable) second);
}

static <T extends Comparable<T>> void foo(T first, T second){
    int diff = first.compareTo(second); // no warning.
}

13
2017-08-10 09:48



Tôi không thể thay đổi chữ ký phương thức foo. Không thể đạt được điều đó mà không thay đổi chữ ký của foo? - Heisenbug
Bạn phải có một số cách để nói cho trình biên dịch loại đầu tiên và thứ hai là gì. Bạn không thể thay đổi điều này mà không thay đổi chữ ký. Nếu bạn không thể thay đổi chữ ký, bạn có thể sử dụng nhiều phương thức - Peter Lawrey
OK tôi hiểu rồi. cảm ơn cho câu trả lời .. có vẻ như là không thể làm những gì tôi muốn mà không có cảnh báo nào cả. - Heisenbug
Các cảnh báo được mong đợi khi trình biên dịch không thể xác định xem việc truyền mà bạn đang thực hiện có an toàn hay không. Chỉ có bạn mới có thể nói nó là an toàn bằng cách sử dụng chữ ký bên phải. - Peter Lawrey


Không thay đổi Chữ ký, bạn có thể làm

    void foo(Object first, Object second){

        if (!first.getClass().isInstance(second)) 
            return;

        Comparable<Object> firstComparable = (Comparable<Object>)first;  
        Comparable<Object> secondComparable = (Comparable<Object>)second; 

        int diff = firstComparable.compareTo(secondComparable);  
    }

Nhưng bạn vẫn có:
Type safety: Unchecked cast from Object to Comparable<Object>

nhưng không Comparable is a raw type. References to generic type Comparable<T> should be parameterized 
và không Type safety: The method compareTo(Object) belongs to the raw type Comparable. References to generic type Comparable<T> should be parameterized


3
2017-08-10 09:59



Bạn có thể kiểm tra diễn viên bằng if(Comparable.class.isAssignableFrom( first.getClass() )) - oliholz


Bạn phải sử dụng Comparable<Type> trong đó Type là đối tượng đang triển khai Comparable.

Đầu tiên, tại sao ví dụ tham số phương thức của bạn là Objects? Nếu bạn chắc chắn các kiểu tham số giống nhau, bạn nên sử dụng lớp cụ thể làm tham số. Nếu bạn có thể có một hệ thống phân cấp của các lớp, có lớp cao nhất trong hệ thống phân cấp. Đang có Object để đạt được chức năng chung không bao giờ là một ý tưởng hay.


1
2017-08-10 09:51



Tôi biết loại đó là Double hoặc Integer, hoặc một cái gì đó khác thực hiện giao diện Comparable, nhưng tôi không biết loại cụ thể nào. Loại cụ thể chỉ được biết khi chạy. - Heisenbug
Bạn phải thay đổi chữ ký của phương thức như trong câu trả lời của @Peter Lawrey, hoặc sống với cảnh báo ... - Nivas


EDIT: Vì bạn nói bạn không thể thay đổi chữ ký của phương thức, sau đó bạn thực sự không thể lấy đi mà không có một diễn viên không an toàn (cho trình biên dịch), và @SuppressWarnings:

@SuppressWarnings("unchecked")
public void foo(final Object first, final Object second) {
    if (!first.getClass().isInstance(second)) // first and second of the
        return;

    Comparable<Object> firstComparable = (Comparable<Object>) first;
    Comparable<Object> secondComparable = (Comparable<Object>) second;
    int diff = firstComparable.compareTo(secondComparable);
}

1
2017-08-10 10:01



Tôi muốn làm điều đó, nhưng như tôi đã nói tôi không nên thay đổi chữ ký phương pháp foo. - Heisenbug
Yup. Đã chỉnh sửa câu trả lời của tôi. - Alistair A. Israel


Thêm chú thích @SuppressWarnings.

@SuppressWarnings("unchecked")
void foo(Object first, Object second){

    if (!first.getClass().isInstance(second))   //first and second of the same type
        return;

    Comparable firstComparable = (Comparable)first;  //WARNING
    Comparable secondComparable = (Comparable)second;  //WARNING

    @SuppressWarnings("unused")
    int diff = firstComparable.compareTo(secondComparable);  //WARNING
}

0
2017-08-10 09:45



Điều này không thay đổi bất cứ điều gì .. nó chỉ ngăn chặn đầu ra cảnh báo. - Heisenbug