Почему мы можем привести интерфейс Java к * любому * не финальному классу? - PullRequest
4 голосов
/ 05 августа 2009
import java.util.Collection;


public class Test
{
    public static void main(String[] args)
    {
        Collection c = null;
        Test s = null;

        s = (Test) c;
    }
}

В приведенном выше примере кода я приведу объект коллекции к объекту Test. (игнорируя нулевой указатель). У теста нет отношения к Collection, но эта программа пройдет все проверки во время компиляции.

Мне интересно, почему это так. Я предполагаю, что интерфейсы игнорируются, потому что они слишком сложны. У них нет общего супертипа, и каждый класс может реализовывать несколько интерфейсов, поэтому иерархия классов / интерфейсов будет слишком сложной для эффективного поиска?

Кроме этой причины, я в тупике. Кто-нибудь знает?!

Ответы [ 3 ]

8 голосов
/ 05 августа 2009

«Не финал» - это ключевое слово здесь. У вас может быть другой класс

public class Test2 extends Test implements Collection

, чей экземпляр будет назначен на s, что делает приведение в законную форму.

3 голосов
/ 05 августа 2009

Поскольку подкласс Test потенциально может быть также подтипом Collection! Спецификация языка разработана таким образом, чтобы быть немного гибкой, чтобы разрешить приведение, которое можно проверить во время выполнения.

0 голосов
/ 15 ноября 2018

Мы можем рассматривать это с другой точки зрения: любой не финальный класс может быть приведен к ЛЮБОМУ интерфейсу

import java.util.function.Predicate;

public class Test {
    public static void main(String[] args) {
        Predicate check;

        try {
            /*It's ok to cast to ANY interface because the Base class is not final.
              Java compiler allows it because some class may extend it 
              and implement the predicate interface. 
              So java compiler can check it only at runtime time not compile time.             
            */
            check = (Predicate)(new Base());

            /*
             Java compiler doesn’t allow it because the BaseFinal is final.
             And it means that no one can extend it and implement interface Predicate. 
             So java compiler can check it at compile time.
            */
            //check = (Predicate)(new BaseFinal()); 
        } catch (ClassCastException e) {
            System.out.println("Class Cast Exception");
        }
        check = (Predicate)(Base)(new Child());
    }    
}
final class BaseFinal {};

class Base {}

class Child extends Base implements Predicate {
    public boolean test(Object t) { return true; }
}
...