2010-02-10 4 views
18

Когда какой-либо объект может быть перенесен в другой объект? Кастованный объект должен быть подтипом другого объекта? Я пытаюсь выяснить правила ...Правила Java для литья

Редактировать: Я понял, что я вообще не объяснял свою проблему: в основном я бросаю объект в тип интерфейса. Однако во время выполнения я получаю java.lang.ClassCastException. Что должно произойти с моим объектом, чтобы я мог применить его к этому интерфейсу? Нужно ли это реализовать?

Благодаря

+0

В какой ситуации вы на самом деле нужны явно привести объект к своему типу интерфейса? – harto

+0

У вас здесь очень полезный ответ. Я бы хотел, чтобы вы его выбрали. – orbfish

ответ

1

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

EDIT:

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

+0

Вы думаете об этом совершенно неправильно. То, что вам следует задавать, - «в каких ситуациях имеет смысл рассматривать этот« Foo »как« IBar »? –

+0

Что делать, если объект, который я пытаюсь применить к этому интерфейсу, расширяет класс, реализующий интерфейс? это позволит избежать ошибки во время выполнения? – alan

+0

oh ok..i попытался перефразировать мой оригинальный комментарий, так как на первый взгляд это не имело смысла – alan

27

В Java есть два типа эталонной переменной литья:

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

  • Приведение к базовому типу: Вы можете назначить ссылку на переменную к опорному супертип переменная явно или неявно. Это безопасная операция , поскольку назначение ограничивает возможности доступа новой переменной .

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

+0

Я не уверен, написал ли вы это, скопировал или обобщил, но это отлично, заставило меня понять, что я пытаюсь это не имело смысла. – orbfish

+0

примеры были бы полезны –

+0

Упрощенный из-за написанного человеком текста, а не какая-то болтовня 'B extends A'. –

1

Если:

interface MyInterface{} 

class MyClass implements MyInterface{} 

Тогда

MyClass m = new MyClass(); 
MyInterface i = (MyInterface)m; 

возможно.

2

Есть интуитивный способ думать об этом - вы не меняете объект с приведением, вы делаете только то, что уже было бы разрешено, если бы этот тип был известен - inotherwords, вы можете использовать только тип что ваш объект уже есть. Поэтому просто посмотрите «вверх» на цепочку объектов, чтобы узнать, какие виды применяются к вашему объекту.

Таким образом, вы можете отличить только от интерфейса , если он определен где-то выше в цепочке (например, если ваш родитель классов реализует его и т. Д. И т. Д.).Он должен быть явным - по вашему вопросу это звучит так, как будто вы можете подумать, что если вы реализуете метод «void foo()», тогда вы должны быть способны передать в интерфейс, который определяет метод «void foo()» - это иногда описывается как "duck typing" (если он крякает, как утка, это утка), но не так, как работает java.

3

Это будет работать:

class Foo implements Runnable { 
    public void run() {} 
} 

Foo foo = new Foo(); 
System.out.println((Runnable) foo); 

Но это не будет:

class Bar { 
    public void run() {} 
} 

Bar bar = new Bar(); 
System.out.println((Runnable) bar); 

Потому что, хотя Bar имеет run() метод, который мог реализовать Runnable.run(), Bar не объявлен, чтобы реализовать Runnable так его не может быть отброшена до Runnable.

Java требует, чтобы вы объявили реализованные интерфейсы на имя. Он не имеет duck typing, в отличие от некоторых других языков, таких как Python и Go

2

Предположим, мы хотим, чтобы бросить d объект A,

Аа = (C) D;

Так что внутренне 3 правила были проверены компилятором и JVM. Компилятор проверяет первые 2 правила во время компиляции, а JVM проверяет последнее правило во время выполнения.

Правило 1 (время компиляции проверки):

Тип «D» и С должны иметь какое-то отношение (ребенка к родителю или родителям к ребенку или одновременно) .Если нет отношения, то мы получим ошибку компиляции (неконвертируемые типы).

Правило 2 (Compile время проверки):

'C' должны быть того же типа или производный тип (подкласс) из 'A' иначе мы получим ошибку компиляции (несовместим типов).

Правило 3 (время выполнение Исключение):

время выполнение типа объект из 'D' должны быть одинаковыми или производным типа противном случае мы получим исключение во время выполнения 'C' (ClassCastException Исключение).

Найти следующие примеры, чтобы получить больше идей,

String s = new String("hello"); StringBuffer sb = (StringBuffer)s; // Compile error : Invertible types because there is no relationship between. 

Object o = new String("hello"); StringBuffer sb = (String)o;  // Compile error : Incompatible types because String is not child class of StringBuffer. 

Object o = new String("hello"); StringBuffer sb = (StringBuffer)o; // Runtime Exception : ClassCastException because 'o' is string type and trying to cast into StingBuffer and there is no relationship between String and StringBuffer. 
Смежные вопросы