2011-12-27 13 views
19

Załóżmy, że mam dwie klasy pochodzące od trzeciej klasy streszczenie:Czy istnieje forma "bezpiecznego odlewania" w Javie?

public abstract class Parent{ 
    public Parent(){ 
    } 
} 

public class ChildA extends Parent { 
    public ChildA { 
    } 
} 

public class ChildB extends Parent { 
    public ChildB { 
    } 
} 

w C# mogłem obsłużyć odlewania w nieco wpisz bezpieczny sposób, wykonując:

ChildA child = obj as ChildA; 

co uczyniłoby dziecko == null jeśli nie był obiektem typu ChildA. Gdybym miał zrobić:

ChildA child = (ChildA)obj; 

... w języku C# spowodowałoby to wyjątek, gdyby typ nie był poprawny.

Więc czy istnieje sposób na zrobienie pierwszego typu rzutowania w Javie? Dzięki.

+0

Duplikat : http://stackoverflow.com/questions/148828/how-to-emulate-c-sharp-as-operator-in-java –

+0

Przeprosiny. Szukałem "bezpiecznego rzucania typu java". Nie przychodzi mi do wyszukiwania "jako słowo kluczowe java". – garrettendi

+3

A następnie wysadza się NPE. ;) –

Odpowiedz

47

Nie mogę myśleć o sposób w samym języku, ale można łatwo naśladować to tak:

ChildA child = (obj instanceof ChildA ? (ChildA)obj : null); 
+0

Co powiesz na instancję listy ? (Lista ) obj: null? Nie można użyć instancji typu ogólnego, ponieważ zniknie ona w czasie wykonywania. – vajanko

+0

@vajanko Masz rację, nie możesz tego zrobić z typowym typem, jeśli musisz również sprawdzić rodzaj przedmiotów. Nadal możesz zrobić "List? (Lista) obj: null' - ale otrzymasz ostrzeżenia podczas kompilacji. Pytanie nic nie mówiło o generykach. –

5

Możesz użyć operatora instanceof.

if(obj instanceof ChildA){ 
    final ChildA child = (ChildA) obj; 
} 
2

zawsze można po prostu sprawdzić najpierw:

if (child instanceof ChildA) { 
    ChildA child = (ChildA) child; 
    // Do stuff. 
} 

Lub po prostu wykonaj szybką metodę:

public ChildA getInstance(Parent p) { 
    if (child instanceof ChildA) { 
     return (ChildA) p; 
    } else { 
     return null; 
    } 
} 
9

W języku Java 8 można również użyć składni strumienia z Opcjonalne:

Object o = new Integer(1); 

    Optional.ofNullable(o) 
      .filter(Number.class::isInstance) 
      .map(Number.class::cast) 
      .ifPresent(n -> System.out.print("o is a number")); 
1

Myślę, że najlepszym sposobem radzenia sobie z tym jest użycie metod ogólnych. Jest to moim zdaniem najbardziej wielokrotnego użytku/bezpieczne rozwiązanie.

Oto co Doszedłem do:

@SuppressWarnings("unchecked") 
public <E> E coerceTo(Object o, Class<E> target) throws IllegalArgumentException { 
    if(target.isInstance(o)) return (E)o; 
    String msg = "expected "+target.getName()+" but was "+o.getClass().getName(); 
    throw new IllegalArgumentException(msg); 
} 

Zauważ, że tutaj, obsada jest bezpieczny i to jest prawidłowe, aby dodać suppressWarnings adnotacji.

Oto przykład, jak wywołać metodę:

Object o = 1; 
int a = coerceTo(o, Integer.class); 
2

Można użyć tej metody, która jest kompatybilna ze wszystkimi rodzajami Java:

public static <T> T safeCast(Object o, Class<T> clazz) { 
    return clazz != null && clazz.isInstance(o) ? clazz.cast(o) : null; 
} 

Przykład:

// A given object obj 
Integer i = safeCast(obj, Integer.class); 
Powiązane problemy