È possibile utilizzare l'operatore instanceof in un'istruzione switch?


267

Ho una domanda sull'uso di switch case per instanceofoggetto:

Ad esempio: il mio problema può essere riprodotto in Java:

if(this instanceof A)
    doA();
else if(this instanceof B)
    doB();
else if(this instanceof C)
    doC():

Come verrebbe implementato usando switch...case?


6
Se ritieni davvero di aver bisogno di un passaggio, puoi inserire il nome della classe in un int e usarlo, ma fai attenzione ai possibili scontri. Aggiungendo come commento piuttosto che una risposta in quanto non mi piace l'idea di questo effettivamente utilizzato. Forse quello di cui hai davvero bisogno è il modello di visitatore.
Vickirk,

1
A partire da java 7 potresti persino attivare il nome di classe completo per evitare scontri hash come sottolineato da @vickirk, ma è ancora brutto.
Mitja,

Risposte:


225

Questo è uno scenario tipico in cui il polimorfismo dei sottotipi aiuta. Eseguire le seguenti operazioni

interface I {
  void do();
}

class A implements I { void do() { doA() } ... }
class B implements I { void do() { doB() } ... }
class C implements I { void do() { doC() } ... }

Poi si può semplicemente chiamare do()su this.

Se non sei libero di cambiare A, Be C, puoi applicare lo schema visitatore per ottenere lo stesso.


33
Il modello Visitatore significa che A, B e C devono implementare un'interfaccia con un metodo astratto che accetta un Visitatore come parametro di input, cosa succede se non è possibile modificare A, B, C e nessuno di essi implementa tale interfaccia?
thermz,

21
L'ultimo commento sul modello di visitatore è sbagliato. Dovresti comunque fare in modo che A, B e C implementino un'interfaccia.
Ben Thurley,

10
Purtroppo questo non funziona se il codice do () - richiede l'ambiente dell'host (ovvero l'accesso a variabili non presenti nel do () stesso).
mafu,

2
La domanda di @mafu OP riguardava il dispacciamento basato sul tipo. Se il tuo metodo do () ha bisogno di più input per essere inviato rispetto al tuo problema, IMHO è al di fuori dell'ambito della domanda discussa qui.
jmg,

3
questa risposta presuppone che sia possibile modificare le classi A, B, C, mentre penso che il punto sia come farlo senza modificare A, B, C perché potrebbero essere in una libreria di terze parti
cloudy_weather

96

se non puoi assolutamente codificare un'interfaccia, allora puoi usare un enum come intermediario:

public A() {

    CLAZZ z = CLAZZ.valueOf(this.getClass().getSimpleName());
    switch (z) {
    case A:
        doA();
        break;
    case B:
        doB();
        break;
    case C:
        doC();
        break;
    }
}


enum CLAZZ {
    A,B,C;

}

grazie, ho anche dovuto apportare alcune modifiche: 1) inizializzare ciascun ID enum con il riferimento Class; 2) asserire il nome semplice della classe con l'enum id .toString (); 3) trova l'enum attraverso il riferimento di classe memorizzato per ID enum. Penso che anche questo sia offuscamento sicuro allora.
Aquarius Power il

se this.getClass (). getSimpleName () non corrisponde a un valore di CLAZZ genera un'eccezione ... è meglio circondare con un blocco try catch e l'eccezione verrebbe trattata come l'opzione "default" o "else" di lo switch
tetri

40

Basta creare una mappa in cui la classe è la chiave e la funzionalità, ovvero lambda o simile, è il valore.

Map<Class,Runnable> doByClass = new HashMap<>();
doByClass.put(Foo.class, () -> doAClosure(this));
doByClass.put(Bar.class, this::doBMethod);
doByClass.put(Baz.class, new MyCRunnable());

// ovviamente, refactor questo per inizializzare solo una volta

doByClass.get(getClass()).run();

Se è necessario selezionare Eccezioni anziché implementare una FunctionalInterface che genera l'eccezione e utilizzarla al posto di Runnable.


3
La migliore soluzione imho, specialmente perché consente un facile refactoring.
Feiteira,

2
L'unico aspetto negativo di questa soluzione è che non è possibile utilizzare le variabili locali (metodo) nelle lambda (supponendo che potrebbe essere necessario ovviamente).
zapatero,

1
@zapatero Puoi semplicemente passare a Funzione anziché Runnable, passare l'istanza come parametro, quindi
eseguirne il

upvoted; questa è una delle poche risposte che aiuta effettivamente l'OP a fare ciò che sta chiedendo (e sì, spesso è possibile riformattare il codice per non doverlo fare instanceof, e no, purtroppo il mio scenario non è uno di quelli che si adattano facilmente quella scatola ...)
Per Lundberg l'

@ SergioGutiérrez Grazie. Bene, questo modello dovrebbe essere necessario solo con una libreria esterna. E anche allora puoi semplicemente creare un'interfaccia con un'implementazione dell'adattatore, ma è utile dove vuoi che il DIFF comportamentale, per così dire, sia più ovvio. Suppongo che sia simile al routing dell'API fluente vs annotazione.
Novaterata,

36

Nel caso in cui qualcuno lo leggerà:

La soluzione MIGLIORE in Java è:

public enum Action { 
    a{
        void doAction(...){
            // some code
        }

    }, 
    b{
        void doAction(...){
            // some code
        }

    }, 
    c{
        void doAction(...){
            // some code
        }

    };

    abstract void doAction (...);
}

I GRANDI benefici di tale modello sono:

  1. Lo fai semplicemente come (NO switch affatto):

    void someFunction ( Action action ) {
        action.doAction(...);   
    }
  2. Nel caso in cui aggiungi una nuova azione chiamata "d" DEVI implementare il metodo doAction (...)

NOTA: questo modello è descritto in Bloch di Joshua "Effective Java (2nd Edition)"


1
simpatico! È @Overriderichiesto sopra ogni implementazione di doAction()?
mateuscb,

9
Come è questa la soluzione "MIGLIORE"? Come decideresti quale actionusare? Da un'istanza esterna di cascata che chiama someFunction()con il corretto action? Questo aggiunge solo un altro livello di riferimento indiretto.
PureSpider

1
No, verrà eseguito automaticamente in fase di esecuzione. Se chiami someFunction (Action.a), verrà chiamato a.doAction.
se.solovyev,

11
Non lo capisco Come sapresti quale enum usare? Come ha detto @PureSpider, questo sembra solo un altro livello di lavoro da fare.
James Manes,

2
È molto triste che tu non abbia offerto un esempio completo , ad esempio come mappare un'istanza di classe di a, b o C a questa enum. Proverò a trasmettere l'istanza a questo Enum.
Tom,

21

Non puoi. L' switchistruzione può contenere solo caseistruzioni che sono costanti di tempo di compilazione e che valutano un numero intero (fino a Java 6 e una stringa in Java 7).

Quello che stai cercando è chiamato "pattern matching" nella programmazione funzionale.

Vedi anche Evitare istanza di Java


1
No, nella maggior parte dei linguaggi funzionali non è possibile modellare la corrispondenza sui tipi, solo sui costruttori. Questo è almeno vero in ML e Haskell. In Scala e OCaml è possibile ma non l'applicazione tipica della corrispondenza dei motivi.
jmg,

Certo, ma il controllo contro i costruttori sarebbe "equivalente" allo scenario sopra descritto.
Carlo V. Dango,

1
In alcuni casi, ma non in generale.
jmg,

Gli switch possono anche supportare enum.
Solomon Ucko,

"Non puoi" guardare una lingua diversa è raramente una risposta utile.
L. Blanc,

17

Come discusso nelle risposte migliori, l'approccio OOP tradizionale prevede l'uso del polimorfismo anziché dell'interruttore. Esiste anche un modello di refactoring ben documentato per questo trucco: sostituire il condizionale con il polimorfismo . Ogni volta che cerco questo approccio, mi piace anche implementare un oggetto Null per fornire il comportamento predefinito.

A partire da Java 8, possiamo usare lambda e generici per darci qualcosa con cui i programmatori funzionali hanno molta familiarità: il pattern matching. Non è una funzionalità del linguaggio principale ma la libreria Javaslang fornisce un'implementazione. Esempio dal javadoc :

Match.ofType(Number.class)
    .caze((Integer i) -> i)
    .caze((String s) -> new BigDecimal(s))
    .orElse(() -> -1)
    .apply(1.0d); // result: -1

Non è il paradigma più naturale nel mondo Java, quindi usalo con cautela. Mentre i metodi generici ti eviteranno di dover digitare il valore abbinato, ci manca un modo standard per scomporre l'oggetto abbinato come ad esempio con le classi di case di Scala .


9

So che è molto tardi, ma per i futuri lettori ...

Fai attenzione agli approcci sopra che si basano solo sul nome della classe di A , B , C ...:

A meno che non sia possibile garantire che A , B , C ... (tutte le sottoclassi o gli implementatori di Base ) siano definitivi, le sottoclassi di A , B , C ... non verranno trattate.

Anche se l' approccio if, elseif, elseif .. è più lento per un gran numero di sottoclassi / implementatori, è più accurato.


In effetti, non dovresti mai usare il polimorfismo (alias OOP)
Val

8

Sfortunatamente, non è possibile out of the box poiché l'istruzione switch-case prevede un'espressione costante. Per ovviare a questo, un modo sarebbe quello di utilizzare i valori enum con i nomi delle classi es

public enum MyEnum {
   A(A.class.getName()), 
   B(B.class.getName()),
   C(C.class.getName());

private String refClassname;
private static final Map<String, MyEnum> ENUM_MAP;

MyEnum (String refClassname) {
    this.refClassname = refClassname;
}

static {
    Map<String, MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
    for (MyEnum instance : MyEnum.values()) {
        map.put(instance.refClassname, instance);
    }
    ENUM_MAP = Collections.unmodifiableMap(map);
}

public static MyEnum get(String name) {
    return ENUM_MAP.get(name);
 }
}

Con ciò è possibile usare l'istruzione switch in questo modo

MyEnum type = MyEnum.get(clazz.getName());
switch (type) {
case A:
    ... // it's A class
case B:
    ... // it's B class
case C:
    ... // it's C class
}

Credo che fino a quando il problema JEP 8213076 non sarà completamente implementato, questo è il modo più pulito di ottenere un'istruzione switch in base al tipo, senza modificare la classe di destinazione.
Rik Schaaf,


5

L'uso di istruzioni switch come questa non è orientato agli oggetti. Dovresti invece usare il potere del polimorfismo . Basta scrivere

this.do()

Avendo precedentemente impostato una classe base:

abstract class Base {
   abstract void do();
   ...
}

che è la classe base per A, Be C:

class A extends Base {
    void do() { this.doA() }
}

class B extends Base {
    void do() { this.doB() }
}

class C extends Base {
    void do() { this.doC() }
}

suggeests @jmg ( stackoverflow.com/questions/5579309/switch-instanceof/... ) utilizzando un'interfaccia invece di una classe base astratta. Questo può essere superiore in alcune circostanze.
Raedwald,

5

Funzionerà più velocemente e renderà conto nel caso in cui
tu abbia relativamente molti "casi"
- il processo viene eseguito in un contesto sensibile alle prestazioni

public <T> T process(Object model) {
    switch (model.getClass().getSimpleName()) {
        case "Trade":
            return processTrade();
        case "InsuranceTransaction":
            return processInsuranceTransaction();
        case "CashTransaction":
            return processCashTransaction();
        case "CardTransaction":
            return processCardTransaction();
        case "TransferTransaction":
            return processTransferTransaction();
        case "ClientAccount":
            return processAccount();
        ...
        default:
            throw new IllegalArgumentException(model.getClass().getSimpleName());
    }
}

1
Ciò non equivale a fare un'istanza di, poiché funziona solo se la classe di implementazione viene utilizzata per cambiare, ma non funzionerà per interfacce / abstractclass / superclasses
lifeesoordinary

sì, questo non lo è
Mike

Uno sforzo, ma a parte il commento di @ lifesoordinary, ti manca anche la sicurezza tipica che hai normalmente, perché questa risposta usa stringhe codificate, invece di riferimenti di classe. È abbastanza facile fare un refuso, specialmente se avresti bisogno di estendere questa funzionalità con nomi canonici completi se qui ci fosse una sovrapposizione in nomi di classe con nomi di pacchetti diversi. Modifica: errore di battitura fisso (che in qualche modo dimostra il mio punto)
Rik Schaaf

4

Non è possibile che uno switch funzioni solo con i tipi byte, short, char, int, String e enumerati (e le versioni degli oggetti delle primitive, dipende anche dalla versione java, Le stringhe possono essere modificate switchin java 7)


Non è possibile attivare Stringhe in Java 6. E non è possibile attivare "Versioni oggetto delle primitive".
Lukas Eder

@Bozho Ho detto che dipende dalla tua versione java, in Java 7 puoi attivare Stringhe.
Tnem,

@Lukas Eder controlla le tue specifiche java che puoi
Tnem

4

Personalmente mi piace il seguente codice Java 1.8:

    mySwitch("YY")
            .myCase("AA", (o) -> {
                System.out.println(o+"aa");
            })
            .myCase("BB", (o) -> {
                System.out.println(o+"bb");
            })
            .myCase("YY", (o) -> {
                System.out.println(o+"yy");
            })
            .myCase("ZZ", (o) -> {
                System.out.println(o+"zz");
            });

Uscita:

YYyy

Il codice di esempio utilizza le stringhe ma è possibile utilizzare qualsiasi tipo di oggetto, inclusa la classe. per esempio.myCase(this.getClass(), (o) -> ...

Ha bisogno del seguente frammento:

public Case mySwitch(Object reference) {
    return new Case(reference);
}

public class Case {

    private Object reference;

    public Case(Object reference) {
        this.reference = reference;
    }

    public Case myCase(Object b, OnMatchDo task) {
        if (reference.equals(b)) {
            task.task(reference);
        }
        return this;
    }
}

public interface OnMatchDo {

    public void task(Object o);
}

4

Java ora consente di cambiare nel modo dell'OP. Lo chiamano Pattern Matching per switch. Attualmente è in bozza, ma vedendo quanto lavoro hanno svolto recentemente negli switch, penso che passerà attraverso. L'esempio fornito nel JEP è

String formatted;
switch (obj) {
    case Integer i: formatted = String.format("int %d", i); break;
    case Byte b:    formatted = String.format("byte %d", b); break;
    case Long l:    formatted = String.format("long %d", l); break;
    case Double d:  formatted = String.format("double %f", d); break;
    case String s:  formatted = String.format("String %s", s); break
    default:        formatted = obj.toString();
}  

o usando la loro sintassi lambda e restituendo un valore

String formatted = 
    switch (obj) {
        case Integer i -> String.format("int %d", i)
        case Byte b    -> String.format("byte %d", b);
        case Long l    -> String.format("long %d", l); 
        case Double d  -> String.format("double %f", d); 
        case String s  -> String.format("String %s", s); 
        default        -> obj.toString();
    };

in entrambi i casi hanno fatto cose interessanti con gli switch.


3

Se riesci a manipolare l'interfaccia comune, potresti aggiungere un enum e fare in modo che ogni classe restituisca un valore univoco. Non avrai bisogno di instanceof o di un modello di visitatore.

Per me, la logica doveva essere scritta nell'istruzione switch, non l'oggetto stesso. Questa era la mia soluzione:

ClassA, ClassB, and ClassC implement CommonClass

Interfaccia:

public interface CommonClass {
   MyEnum getEnumType();
}

enum:

public enum MyEnum {
  ClassA(0), ClassB(1), ClassC(2);

  private int value;

  private MyEnum(final int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }

impl:

...
  switch(obj.getEnumType())
  {
    case MyEnum.ClassA:
      ClassA classA = (ClassA) obj;
    break;

    case MyEnum.ClassB:
      ClassB classB = (ClassB) obj;
    break;

    case MyEnum.ClassC:
      ClassC classC = (ClassC) obj;
    break;
  }
...

Se sei su Java 7, puoi inserire i valori di stringa per l'enum e il blocco del case switch continuerà a funzionare.


Il valuecampo è ridondante se si desidera solo distinguere le costanti enum: è possibile utilizzare le costanti direttamente (come si fa).
user905686

2

Cosa ne pensi di questo ?

switch (this.name) 
{
  case "A":
    doA();
    break;
  case "B":
    doB();
    break;
  case "C":
    doC();
    break;
  default:
    console.log('Undefined instance');
}

3
Dovresti sottolineare che questo funziona solo su Java 7. E che devi chiamare this.getSimpleName()Non sono sicuro se il poster sia confuso con JS (sì, sta usando la console, hehe).
pablisco,

5
Questo ha il problema di perdere la trasparenza referenziale del codice sorgente. Cioè, il tuo IDE non sarà in grado di mantenere l'integrità di riferimento. Supponiamo che tu voglia rinominare il tuo nome. Il riflesso è malvagio.
Val

1
Non è una grande idea. I nomi delle classi non sono univoci se si hanno caricatori di più classi.
Doradus,

Si rompe quando si tratta di compressione del codice (→ ProGuard)
Matthias Ronge,

1

Penso che ci siano ragioni per usare un'istruzione switch. Se stai usando forse il codice generato da xText. O un altro tipo di classi generate da EMF.

instance.getClass().getName();

restituisce una stringa del nome di implementazione della classe. cioè: org.eclipse.emf.ecore.util.EcoreUtil

instance.getClass().getSimpleName();

restituisce la rappresentazione semplice, ovvero: EcoreUtil


Non puoi usarlo switchcome casecondizione perché non è un valore costante
B-GangsteR

1

Se è necessario "passare" attraverso il tipo di classe di "questo" oggetto, questa risposta è la migliore https://stackoverflow.com/a/5579385/2078368

Ma se è necessario applicare "switch" a qualsiasi altra variabile. Vorrei suggerire un'altra soluzione. Definire la seguente interfaccia:

public interface ClassTypeInterface {
    public String getType();
}

Implementa questa interfaccia in ogni classe che desideri "cambiare". Esempio:

public class A extends Something implements ClassTypeInterface {

    public final static String TYPE = "A";

    @Override
    public String getType() {
        return TYPE;
    }
}

Dopodiché puoi usarlo nel modo seguente:

switch (var.getType()) {
    case A.TYPE: {
        break;
    }
    case B.TYPE: {
        break;
    }
    ...
}

L'unica cosa di cui dovresti preoccuparti: mantenere i "tipi" unici in tutte le classi che implementano ClassTypeInterface. Non è un grosso problema, perché in caso di intersezione si riceve un errore di compilazione per l'istruzione "switch-case".


Invece di usare String per il TYPE, puoi usare un enum e l'unicità è garantita (come fatto in questa risposta ). Tuttavia, con uno qualsiasi degli approcci dovrai fare il refactoring in due punti quando fai una ridenominazione.
user905686

@ user905686 rinominare cosa? Nell'esempio corrente, il tipo "A" è definito all'interno della classe Something per ridurre al minimo la quantità di codice. Ma nella vita reale dovresti ovviamente definirlo all'esterno (in un luogo comune) e non ci sono problemi con ulteriori refactoring.
Sergey Krivenkov,

Intendo rinominare la classe A. Il refactoring automatico potrebbe non includere la variabile TYPE = "A"durante la ridenominazione. Soprattutto se è al di fuori della classe corrispondente, si potrebbe anche dimenticarlo quando lo si fa manualmente. IntelliJ in realtà trova anche le occorrenze del nome della classe in stringhe o commenti, ma questa è solo una ricerca di testo (invece di guardare l'albero della sintassi) e quindi include falsi positivi.
user905686

@ user905686 è solo un esempio per visualizzare l'idea. Non utilizzare String per le definizioni dei tipi nel progetto reale, dichiarare alcuni titolari di classe MyTypes con costanti intere (o enum) e utilizzarli nelle classi che implementano ClassTypeInterface.
Sergey Krivenkov,

1

Ecco un modo funzionale per realizzarlo in Java 8 usando http://www.vavr.io/

import static io.vavr.API.*;
import static io.vavr.Predicates.instanceOf;
public Throwable liftRootCause(final Throwable throwable) {
        return Match(throwable).of(
                Case($(instanceOf(CompletionException.class)), Throwable::getCause),
                Case($(instanceOf(ExecutionException.class)), Throwable::getCause),
                Case($(), th -> th)
        );
    }

1

Sebbene non sia possibile scrivere un'istruzione switch, è possibile eseguire il branch out all'elaborazione specifica per ciascun tipo specificato. Un modo per farlo è utilizzare il meccanismo standard di doppia spedizione. Un esempio in cui vogliamo "cambiare" in base al tipo è il mappatore di eccezioni Jersey in cui dobbiamo mappare una moltitudine di eccezioni alle risposte di errore. Mentre per questo caso specifico esiste probabilmente un modo migliore (ovvero usare un metodo polimorfico che traduce ogni eccezione in una risposta di errore), l'uso del doppio meccanismo di invio è ancora utile e pratico.

interface Processable {
    <R> R process(final Processor<R> processor);
}

interface Processor<R> {
    R process(final A a);
    R process(final B b);
    R process(final C c);
    // for each type of Processable
    ...
}

class A implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

class B implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

class C implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

Quindi ovunque sia necessario lo "switch", puoi farlo come segue:

public class LogProcessor implements Processor<String> {
    private static final Logger log = Logger.for(LogProcessor.class);

    public void logIt(final Processable base) {
        log.info("Logging for type {}", process(base));
    }

    // Processor methods, these are basically the effective "case" statements
    String process(final A a) {
        return "Stringifying A";
    }

    String process(final B b) {
        return "Stringifying B";
    }

    String process(final C c) {
        return "Stringifying C";
    }
}

Questo sembra un po 'come il modello visitatore, che è stato già discusso in questa risposta: stackoverflow.com/a/5579385
typeracer

0

Crea un Enum con nomi di classe.

public enum ClassNameEnum {
    A, B, C
}

Trova il nome della classe dell'oggetto. Scrivi un interruttore caso sopra l'enum.

private void switchByClassType(Object obj) {

        ClassNameEnum className = ClassNameEnum.valueOf(obj.getClass().getSimpleName());

        switch (className) {
            case A:
                doA();
                break;
            case B:
                doB();
                break;
            case C:
                doC();
                break;
        }
    }
}

Spero che questo ti aiuti.


2
Contrariamente a questo approccio in cui l'accoppiamento tra costanti di enum e classi viene fatto in modo esplicito, si esegue l'accoppiamento implicitamente per nome della classe. Ciò interromperà il codice quando rinominerai solo una delle costanti enum o la classe mentre l'altro approccio funzionerebbe comunque.
user905686

0

Eclipse Modeling Framework ha un'idea interessante che considera anche l'eredità. Il concetto di base è definita nello Switch interfaccia : la commutazione viene effettuata richiamando il doSwitch metodo.

Ciò che è veramente interessante è l'implementazione. Per ogni tipo di interesse, a

public T caseXXXX(XXXX object);

il metodo deve essere implementato (con un'implementazione predefinita che restituisce null). L' implementazione di doSwitch tenterà di chiamare tutti i metodi caseXXX sull'oggetto per tutta la sua gerarchia di tipi. Qualcosa nelle righe di:

BaseType baseType = (BaseType)object;
T result = caseBaseType(eAttribute);
if (result == null) result = caseSuperType1(baseType);
if (result == null) result = caseSuperType2(baseType);
if (result == null) result = caseSuperType3(baseType);
if (result == null) result = caseSuperType4(baseType);
if (result == null) result = defaultCase(object);
return result;

Il framework effettivo utilizza un ID intero per ogni classe, quindi la logica è in realtà un puro switch:

public T doSwitch(Object object) {
    return doSwitch(object.class(), eObject);
}

protected T doSwitch(Class clazz, Object object) {
    return doSwitch(getClassifierID(clazz), object);
}

protected T doSwitch(int classifierID, Object theObject) {
    switch (classifierID) {
    case MyClasses.BASETYPE:
    {
      BaseType baseType = (BaseType)object;
      ...
      return result;
    }
    case MyClasses.TYPE1:
    {
      ...
    }
  ...

Puoi vedere un'implementazione completa di ECoreSwitch per avere un'idea migliore.


-1

c'è un modo ancora più semplice di emulare una struttura di switch che utilizza instanceof, lo fai creando un blocco di codice nel tuo metodo e nominandolo con un'etichetta. Quindi usi if strutture per emulare le dichiarazioni del caso. Se un caso è vero, utilizzare l'interruzione LABEL_NAME per uscire dalla struttura dell'interruttore di fortuna.

        DEFINE_TYPE:
        {
            if (a instanceof x){
                //do something
                break DEFINE_TYPE;
            }
            if (a instanceof y){
               //do something
                break DEFINE_TYPE;
            }
            if (a instanceof z){
                // do something
                break DEFINE_TYPE;
            }
        }

In che modo è migliore del if... else ifcodice fornito dall'OP?
Typeracer,

Solo per approfondire il mio commento precedente: quello che stai proponendo è essenzialmente di sostituire if... else ifcon le dichiarazioni "goto", che è il modo sbagliato di implementare il flusso di controllo in linguaggi come Java.
Typeracer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.