2011-02-04 5 views
0

Я не понимаю, почему мне нужно передавать переменные-члены в соответствующий тип, когда их типы уже объявлены. Например:Вопрос о кастинге Java

public class SomeClass extends SomethingElse { 

    private Funky mFunkyVar; 
    // a whole bunch of other variables and methods 

    public void needToCast() { 
    mFunkyVar = (Funky) new FunkySubClass(); 
    } 

} 

Я делаю ошибку для новичков или это действительно идиоматическая Java? В приведенном выше примере я предполагаю, что FunkySubClass действительно является подклассом Funky.

+3

Вам не нужно, если 'FunkySubClass' действительно является подклассом« Funky ». – casablanca

+0

, если FunkySubClass расширяет Funky, тогда вам не нужно бросать, нет. –

+0

Какую версию java вы используете? –

ответ

4

На самом деле вам не нужно бросать его!

Могу ли я сделать некоторые ошибки новичка

Yeap, но не беспокойтесь ... после этого вы не будете делать это снова;)

См:

$cat Funky.java 
class Funky { 
} 
class FunkySubClass extends Funky { 
} 
class SomethingElse { 
} 
class SomeClass extends SomethingElse { 
    private Funky aFunkyVar; 
    //... 
    public void noNeedToCast() { 
     aFunkyVar = new FunkySubClass(); 
    } 
} 

$javac Funky.java 
$ 

Нет ошибок компиляции.

EDIT

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

Для примитивов вы «имеете», если хотите сузить значение.

Например:

int i = 255; 
byte b = (byte) i; 

Если вы не отбрасывают компилятор предупредит вас, «эй, вы действительно не хотите, чтобы сделать это»

... 
byte b = i; 
... 
Funky.java:18: possible loss of precision 
found : int 
required: byte 
     byte d = i; 

Кастинг походит на сообщение компилятор: «Эй, не волнуйся, я знаю, что я делаю, хорошо?"

Конечно, если вы приводите, а значение не подходит, вы получите странные результаты:

int i = 2550; 
byte b = (byte) i; 
System.out.println(b); 

принты:

-10 

Вы не нужно литые, когда тип шире, чем другого типа:

byte b = 255; 
int i = b;// no cast needed 

Для справок работает аналогичным образом.

Вам нужно включить, если вы хотите спуститься в иерархию классов (узкий), и вам не нужно бросать, когда вы хотите перейти в иерархию (например, в вашем примере).

Так что, если мы имеем:

java.lang.Object 
    | 
    + -- Funky 
     | 
     +-- FunkySubclass 

Вам нужно только бросить, когда у вас есть тип верхней в иерархии (Object или Напуганный) в этом случае. И вы не должны, если у вас есть тип ниже в иерархии:

void other(Object o) { 
    // Cast needed: 
    Funky f = (Funky) o; 
    FunkySubClass fsc = (FunkySubClass) o; 
    FunkySubClass fscII = (FunkySubClass) f; 
    // Cast not needed: 
    Object fobj = f; 
    Object fscobj = fsc; 
    Funky fparent = fsc; 
} 

С примитивов виртуальная машина знает, как усечение значение, но со ссылкой нет. Итак, если значение casted равно , а не целевого типа, вы получите java.lang.ClassCastException во время выполнения. Это цена, которую вы должны заплатить, когда рассказываете компилятору «Я знаю, что делаю», а вы этого не делаете.

Надеюсь, это достаточно ясно и не смущает вас.

:)

+0

Где я могу найти правила для кастинга в Java? В учебниках по андроидам все происходит, и это просто странно, объявляя переменную определенного типа, а затем бросая ее. – davidk01

+0

@ davidk01: Неявное литье может быть гораздо более неудобным. Можете ли вы представить себе, что при компиляции не возникает ошибка: «Object o =« hello »; HashMap h = o; '? В конце концов, с точки зрения компилятора, которая является той же самой операцией, которую вы пытаетесь, только здесь это, очевидно, неправильно. –

+0

Вам нужно бросить, когда хотите «сузить» тип (и у вас более широкий тип в иерархии) ... mmhh дайте мне посмотреть, смогу ли я сделать что-то достаточно простое. – OscarRyz

0

new FunkySubClass() возвращает объект типа FunkySubClass, а не Funky. Следовательно, вы должны четко сказать Java, чтобы рассматривать его как Фанки объект

Это правая рука, которая преобразовывается

+0

Неправда. Объект может быть напрямую привязан к переменной, типизированной как любой из ее предков. –

+0

Что было бы актуально, если бы «FunkySubClass» не был подклассом «Funky». Но это похоже на то, что предлагают названия. –

+1

Заочно фактического определения я предположил, что автор попробовал код без актерского состава. –

2

Если FunkySubClass действительно подкласс фанки вам не нужен бросок.

Если вы покажете нам ошибку, которую вы получаете, мы сможем помочь больше.

+0

Ошибок нет, но этот тип кода появляется во всех обучающих программах для Android, и суть моего смятения заключалась в том, что переменная была объявлена ​​как «Кое-что», а затем прислала ее каким-то способом. – davidk01

+0

@ davidk01: В этом случае ответ @Foo Bah может быть полезным. –

1

Нет необходимости "(Funky)", а FunkySubClassесть-Funky.

+1

... мы думаем (на основе названий) –

1

Вам не нужно явно приводить к базовому классу. Например, это на самом деле более идиоматических не бросать - обычное дело:

List<String> somelist=new ArrayList<String>(); 
0

Вам не нужно, чтобы бросить его. Что заставляет вас думать, что вы делаете?

1

Вам нужно было бы просто отличить, если FunkySubClass был (неправильно назван) и фактически является родительским классом Funky. Назначение дочернего класса родительскому объекту в порядке.

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