Java: непроверенное приведение из X в Y / как реализовать castOrNull - PullRequest
6 голосов
/ 14 октября 2010

Я реализовал эту функцию:

 static <X,Y> Y castOrNull(X obj) {
  try {
   return (Y)obj;
  }
  catch(ClassCastException e) {
   return null;
  }
 }

Это дает мне предупреждение компилятора:

Type safety: Unchecked cast from X to Y

Что я не совсем понимаю. Разве try/catch, который я здесь делаю, не проверяет это? Могу ли я проигнорировать предупреждение?

Будет ли моя функция работать должным образом или нет? Как бы я это правильно реализовал?

Я также пробовал с проверкой obj instanceof Y, но она не работает из-за способа обработки обобщенных данных в Java.

Кстати, эта функция мне кажется весьма полезной (чтобы сделать какой-то другой код более чистым). Интересно, может ли такая функция уже существовать в Java?


Один пример, где я хочу его использовать:

    void removeEmptyRawStrings() {
        for(Iterator<Entity> e = entities.iterator(); e.hasNext();) {
            RawString s = castOrNull(e.next());
            if(s != null && s.content.isEmpty()) e.remove();
        }
    }

В моем коде такие случаи встречаются довольно часто. И я думаю, что это читабельнее и проще, чем все остальное. Но, пожалуйста, дайте мне лучшее предложение, если вы хотите узнать, как сделать этот код еще проще.

Ответы [ 4 ]

11 голосов
/ 14 октября 2010

Таким образом, проблема в том, что универсальный параметр Y при использовании для динамического приведения трактуется как Object.Он никогда не бросит CCE.Вы получаете CCE в методе , вызывающем , поскольку вы нарушили безопасность статического типа.

Также X здесь совершенно бессмысленно:

Почти наверняка правильное решениене пытаться ничего подобного.null это плохо.Кастинг плохой.

Однако, если вы решили написать ерунду, вы можете передать объект Class:

public static <T> T evilMethod(Class<T> clazz, Object obj) {
    try {
        return clazz.cast(obj);
    } catch (ClassCastException exc) {
        return null;
    }
}
4 голосов
/ 14 октября 2010

Я не совсем уверен, что это будет работать так, как ожидалось.(Зависит от того, что вы ожидаете, конечно :-), но этот код, например, приведет к java.lang.ClassCastException ( ideone ):

public class Main {

    public static void main(String[] args) {
        Integer o = Main.<String, Integer>castOrNull("hello");
    }


    public static <X, Y> Y castOrNull(X obj) {
        try {
            return (Y) obj;
        } catch (ClassCastException e) {
            return null;
        }
    }
}

@ Том Хотин получил «правильное» решение .

1 голос
/ 14 октября 2010

Благодаря тому, что java-дженерики были разработаны, этот код вообще не будет работать.Обобщения полезны только для проверки типов во время компиляции, так как классы не используют информацию об общем типе во время выполнения.

Ваш код будет скомпилирован следующим образом:никогда не терпит неудачу, и скомпилированный код не имеет доступа к универсальным типам, присутствующим во время компиляции.Поскольку приведение происходит не так, как должно, вы должны получить предупреждение о непроверенной операции.

1 голос
/ 14 октября 2010

Вы можете отключить предупреждение в этом методе, если вы точно знаете, что это не проблема, пометив его как @SuppressWarnings("unchecked")

...