Почему мы можем привести интерфейс Java к *любому* нефинальному классу?

StackOverflow https://stackoverflow.com/questions/1235068

  •  22-07-2019
  •  | 
  •  

Вопрос

import java.util.Collection;


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

        s = (Test) c;
    }
}

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

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

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

Это было полезно?

Решение

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

public class Test2 extends Test implements Collection

чей экземпляр в конечном итоге будет назначен s создание актерского состава совершенно законно.

Другие советы

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

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

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; }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top