2015-05-10 2 views
2

Почему работает следующий код?Являются ли интерфейсы обработаны как объекты?

interface I { } 

class A implements I{ 
    public String toString(){ return "in a"; } 
} 

class B extends A{ 
    public String toString(){ return "in b"; } 
} 
B b = new B(); 
A a = b; 
I i = a; 

System.out.println(i); 
System.out.println((B)a); 
System.out.println(b); 

Как вы можете видеть i является допустимым параметром для println метода. Зачем? Рассматривая типы параметров, принятые этим методом, только объект кажется релевантным.

enter image description here

Я искал ответ и нашел несколько соответствующих вещей here: "Ссылочных типов все наследуются от java.lang.Object классов, перечислений, массивов и интерфейсов всех ссылки. типы. "

Но также найдено следующее: «Наследуются ли интерфейсы от класса Object в Java?» и ответ: Нет, они этого не делают. И нет общего «корневого» интерфейса, неявно унаследованного всеми интерфейсами (как в случае с классами). (*)

Что это значит? Может кто-нибудь объяснить мне, почему интерфейс принят в качестве аргумента для функции println?

Я полагаю, что дело здесь в том, что вы не можете передать объект через интерфейс, не имея самого объекта.

Но вопрос все еще остается. Почему компилятор принимает интерфейс в качестве параметра для этого метода?

+3

Интерфейсы не наследуют 'Object', но любой экземпляр реализации любой интерфейс наследует' Object', поэтому имеет 'toString()' метод. –

+0

Я полагаю, когда вы вызываете, System.out.println (....) передавая ему объект, компилятор будет вызывать его toString(), таким образом, в идеале мы передаем строку. –

+0

@SashaSalauyou: Не знаю, какая актуальность 'toString' здесь ... –

ответ

5

The JLS объясняет:

Учитывая необщего типа декларации C, прямые супертипами типа С являются все следующие:

Прямой суперкласса С (§8.1.4).

Прямые суперинтерфейсы C (§8.1.5).

Тип Объект, если C - тип интерфейса без прямых суперинтерфейсов (§9.1.3).

Вы можете задать вопрос Почему Объект является супертипом любого интерфейса. Причина в том, что объект не может быть экземпляром конкретного класса, и нет никакого способа, чтобы этот конкретный класс не расширил Object. Следовательно, компилятор знает, что ссылка на тип интерфейса является ссылкой на объект.

+0

Учитывая 'interface' под названием' Countable', я могу передать ссылку типа 'Countable', которая была инициализирована' null' в 'println'. Поскольку 'null' не является объектом, как это работает? – CKing

+2

@ChetanKinger Мы говорим о типах здесь, а не о объектах. Тип 'Object' всегда является прямым (или косвенным) супертипом типа' Countable'. – biziclop

+0

@biziclop В этом ответе говорится: «Каждый объект является экземпляром какого-то конкретного класса». Мне интересно, как это относится к вопросу из ОП и, следовательно, к моему вопросу в предыдущем комментарии.Говоря это, вы хотите сказать, что все ссылки в 'java' являются' Object'? – CKing

1

Это как. Вы не можете создать интерфейс, поэтому любая ссылка с интерфейсом должна указывать на объект некоторого класса, который реализует указанный интерфейс. И суперкласс класса этого объекта должен быть Объектом в какой-то момент.

1

Ваше недоразумение связано с конфличностью. Наследование и подтипирование - это разные вещи.

The JLS объясняет смысл наследования:

Интерфейс Iнаследует от своих прямых суперинтерфейсов все абстрактные и стандартные методы m [...]

Если у вас есть что-то вроде class String extends Object {}, String является подтип из Object и тем самым наследует члены суперкласса Object.

Интерфейсы, с другой стороны, являются подтипы из Object но не наследуют членов от него. Это то, что aioobe's answer объясняет, что интерфейсы не наследуют.

0

Компилятор не столько принимает интерфейс в качестве аргумента, сколько ссылку на объект, который реализует интерфейс. Рассмотрим следующий фрагмент кода, похожий на ваш, и вывод. Вы увидите, что в обоих случаях вывод является объектом Box. Параметр (или «вещь»), передаваемый в обоих случаях в println(), является тем же самым объектом Box. Просто в одном случае это называется конкретным экземпляром Box, а в другом - ссылкой на объект, реализующий интерфейс A.

interface A {} 

public class Box implements A 
{ 

    public Box() 
    { 

    } 

    public static void main(String[] args) 
    { 
     Box b =new Box(); 
     A a = b; //define a reference to an object that implements interface A 
     System.out.println(a); 
     System.out.println(b); 
    } 
} 

Выход:

Box @ 19e0bfd

Box @ 19e0bfd

Смежные вопросы