Снимите флажок Предупреждение при вызове «Class.forName» - PullRequest
7 голосов
/ 07 июля 2011

Мой код выглядит следующим образом

package com.foo;

public class TestComposition {
    public static void main(String[] args) {
        try {
            Class<Foo> fooClass = 
                    (Class<Foo>) Class.forName("Foo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Присвоение в блоке 'try' приводит к появлению предупреждения о

Type safety: Unchecked cast from Class<capture#1-of ?> to 
     Class<Foo>

Почему это?

Ответы [ 4 ]

34 голосов
/ 07 июля 2011

Во-первых, если вы знаете точный класс, тогда вам не нужно Class.forName. Foo.class будет делать. (До J2SE 5.0 Foo.class фактически компилировался для выполнения Class.forName("Foo") и затем кэшировал его в статическом виде.)

То, что вы, вероятно, хотите, это что-то вроде:

Class<? extends Foo> fooClass =
    (Class<? extends Foo>) Class.forName("MyFoo");

(Когда я говорю «хочу», высказывания и особенно отражения - это зло.)

Как это бывает, у вас есть подходящий метод, чтобы выполнить приведение "безопасно" (при условии, что Foo сам по себе не является общим). Безопасно, как при отсутствии ссылки на несовместимый объект, так и при отсутствии ошибок или непредвиденных исключений.

Class<? extends Foo> fooClass =
    Class.forName("MyFoo").asSubclass(Foo.class);
7 голосов
/ 07 июля 2011

Ну, для начала давайте разберемся, где проблема - это в самом актерском составе.Вот более короткий пример:

public class Test {    
    public static void main(String[] args) throws Exception {
        Object x = (Class<Test>) Class.forName("Test");
    }
}

Это все еще та же проблема.Проблема в том, что актерский состав фактически не собирается ничего тестировать, потому что он будет эффективно преобразован в тип Class.Для Class<T> это немного удивительнее, потому что на самом деле объект знает , о котором идет речь, но учитывает похожую ситуацию:

List<?> list = ... get list from somewhere;
List<String> stringList = (List<String>) list;

Этот бросок не будет проверять, что он действительно a List<String>, потому что эта информация теряется из-за стирания типа .

Теперь в вашем случае, на самом деле, есть более простое решение - если вы знаетеимя класса во время компиляции в любом случае, просто используйте:

Class<Foo> fooClass = Foo.class;

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

2 голосов
/ 07 июля 2011

Система времени выполнения не знает об общих и поэтому может только проверять, что что-то имеет тип Class, но не если оно имеет тип Class<Test>.Вот о чем предупреждение.

Метод специально добавлен в класс Class, чтобы избежать этого предупреждения.Вы можете использовать это вместо того, чтобы кастовать себя: http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#asSubclass(java.lang.Class)

1 голос
/ 07 июля 2011

Если бы вы знали точный класс, вам не нужно было бы использовать Class.forName

Class<Foo> fooClass = Foo.class;

Это имеет смысл делать только тогда, когда вы не знаете тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...