Unchecked и Checked Cast.

 
 
 
Сообщения:3
Доброго времени суток. Помогите пожалуйста разобраться. Что означает что преобразование unchecked и когда преобразование checked?
Вот моя цепочка рассуждений, в которой я не могу уловить разницы между этимя двумя способами выполненния приведения типов.
Java обладает сильной системой типов. Это означает, что во время компиляции известен тип любого выражения и проведены проверки корретности присвоения переменной одного типа значения выражения имеющий другой тип. Такие присвоения возможны если типы совместимы. Дальше будем рассматривать только ссылочные типы для простоты. В Java два типа являются совместимыми если они находятся в отношении наследования. Причем мы можем двигаться как вверх по иерархии так и вниз. Движение вверх безопасно во время выполнения если программа скомилировалась, движение вниз во время выполнения может быть не безопасно и поэтому требует специальной проверки валидности преобрзования во время выполнения. То есть например
Object o = new Integer(1);
Integer i = (Integer)o;
String s = (String)o;

В строках 1,2 мы двигаемся вниз по иерархии. Во время компиляции ошибок не возникает, так как теоретически в Object может хранится Integer, а может и String. Но во время выполнения, чтобы не начать обращаться с куском памяти хранящем Integer как со строкой, что может привести к непредсказуемым последствиям, JVM проверяет действительно ли в куске памяти на который указывает o лежит String или Integer. Для этого JVM выполняет операцию checkcast. Если там лежит не то что мы ожидали, будет выброшено ClassCastException.
Такой вид преобразования я понимаю как checked. То есть невозможно начать обращаться с куском памяти как с типом который несовсместим с тем, который реально лежит в этом куске памяти.
Теперь рассмотрим вот такой, несколько надуманный код.
public class Main2{
	public static<T extends String> void m1(Object o){
		T t;
		t = (T)o;
		System.out.println(t.concat("123"));
	}
	//public static void m2()
	public static void main(String[] args){
		Main2.<String>m1("String");
	}
}

Ключевая строчка здесь t=(T)o. Мы сообщаем компилятору, что собираемся обращаться с Object как с неизвестным типом, но который точно унаследован от String. Так как generic релизованы стиранием, то мы не сможем во время выполнения проверить что o действительно содержит переменную этого неизвестного типа. Но! компилятор всеравно вставляет checkcast, но проверяет лежит ли там точно String.
  public static <T extends java.lang.String> void m1(java.lang.Object);
    Code:
       0: aload_0
       1: checkcast     #2                  // class java/lang/String
       4: astore_1
       5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       8: aload_1
       9: ldc           #4                  // String 123
      11: invokevirtual #5                  // Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
      14: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      17: return

То есть мы действительно не можем установить какой точно тип там лежит, но мы провряем лежит ли там String. А, так как попытка исопльзовать любой метод у переменной t не содержащийся в String или Object приведет к ошибке во время компиляции, такой код является безопасным. То есть опять, мы никогда не будем обращаться с кусоком памяти как с типом несовместемым с тем, что лежит в этом куске.
Тогда зачем комплятор выдает предупреждение
Main2.java:4: warning: [unchecked] unchecked cast
                t = (T)o;
                       ^
  required: T
  found:    Object
  where T is a type-variable:
    T extends String declared in method <T>m1(Object)
1 warning

В чем его смысл ? Какая операция выполняется для checked cast, которая не выполняется для unchecked?
Generic и non-generic код будут работать одинаково, либо не скомпилируется, либо ClassCastException во время исполнения.

Заранее большое спасибо за разъяснения.
 
 
Сообщения:139
нет никакого unchecked cast в java, а warning специально для generic'ов

 
 
Сообщения:3
Ок, переформулирую свой вопрос. О чем именно меня предупреждают? Какие могут быть последствия?
 
 
Сообщения:49
О том, что преобразование может выдать ClassCastException
 
 
Сообщения:3
Ок, почему в этом случае не выдается предупреждение, хотя это преобразование тоже может выдать ClassCastException

Object o = new Integer(1);
Integer i = (Integer)o;
Изменен:10 янв 2017 21:37
 
 
Сообщения:139
Потому что тут нет никаких generic'ов! См. моё предыдущее сообщение.

 
Модераторы:frymock
Сейчас эту тему просматривают:Нет