Zielony Smok - logo witryny

pattern matching for instanceof = dopasowywanie wzorca dla instanceof

Podstawa https://openjdk.java.net/jeps/305

Więcej o dopasowywaniu wzorców w języku Java.

Dotychczasowy sposób użycia instanceof

 private final Object num;
@Override
    public String toString() {
        String formatted = "unknown";
        if (num instanceof Byte) {
            byte b = (Byte) num;
            formatted = String.format("byte %d", b);
        }
        if (num instanceof Short) {
            short s = (Short) num;
            formatted = String.format("short %d", s);
        }
        if (num instanceof Integer) {
            int i = (Integer) num;
            formatted = String.format("int %d", i);
        }
        if (num instanceof Long) {
            long l = (Long) num;
            formatted = String.format("long %d", l);
        }
        if (num instanceof Float) {
            float f = (Float) num;
            formatted = String.format("float %f", f);
        }
        if (num instanceof Double) {
            double d = (Double) num;
            formatted = String.format("double %f", d);
        }
        return formatted;
    }

W kodzie

if(num instanceof Integer){
int i = (Integer)num;
...
}

dzieją się trzy rzeczy:

  1. sprawdzenie czy num należy do podanego typu (num instanceof Integer)
  2. jeśli tak utworzenie nowej zmiennej tego typu (int i)
  3. jeśli tak rzutowanie do podanego typu ((Integer)num) i przypisanie do zmiennej (int i =
    (Integer(num)
    )

Nowy sposób użycia instanceof

 private final Object num;
@Override
    public String toString() {
        String formatted;
        if (num instanceof Byte b) {
            formatted = String.format("byte %d", b);
        } else if (num instanceof Short s) {
            formatted = String.format("short %d", s);
        } else if (num instanceof Integer i) {
            formatted = String.format("int %d", i);
        } else if (num instanceof Long l) {
            formatted = String.format("long %d", l);
        } else if (num instanceof Float f) {
            formatted = String.format("float %f", f);
        } else if (num instanceof Double d) {
            formatted = String.format("double %f", d);
        } else {
            formatted = "unknown";
        }
        return formatted;

Kod

 } else if (num instanceof Integer i) {
            formatted = String.format("int %d", i);
        } e

Pattern jest kombinacją:

  1. predicate (warunku), który może być zastosowany do celu
  2. set of binding variables (zestaw związanych zmiennych), które są wyłuskiwane z celu jeśli
    zastosowanie warunku zakończy się sukcesem. W tym wypadku mamy jedną związana zmienną

W kodzie powyżej operator instanceof dopasowuje cel num do typu Integer.
Jeśli dopasowanie się uda to obj jest rzutowany do typu Integer i przypisany do
zmiennej i. Zmienna i znajduje się w zakresie bloku true polecenia if
else.

Stary sposób pisania metody equals

 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PatternMatching1 that)) return false;
        return getNum().equals(that.getNum());
    }

Nowy sposób pisania metody equals

  @Override
    public boolean equals(Object o) {

        return (o instanceof PatternMatching2 other)
                && (this.num == other.num);
    }

Jest to pierwsze podejście do dopasowywania wzorców. Z zapowiedzi wynika, że wkrótce można
oczekiwać zastosowania dopasowywania wzorców do wyrażeń przełącznikowych
(switch expressions) i poleceń (statements).

Kompletne klasy

InstanceofOld
package pattmatch;

import java.util.Objects;

public class InstanceofOld {

    private final Object num;

    public InstanceofOld(Object num) {
        this.num = num;
    }

    public Object getNum() {
        return num;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof InstanceofOld that)) return false;
        return getNum().equals(that.getNum());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getNum());
    }

    @Override
    public String toString() {
        String formatted = "unknown";
        if (num instanceof Byte) {
            byte b = (Byte) num;
            formatted = String.format("byte %d", b);
        }
        if (num instanceof Short) {
            short s = (Short) num;
            formatted = String.format("short %d", s);
        }
        if (num instanceof Integer) {
            int i = (Integer) num;
            formatted = String.format("int %d", i);
        }
        if (num instanceof Long) {
            long l = (Long) num;
            formatted = String.format("long %d", l);
        }
        if (num instanceof Float) {
            float f = (Float) num;
            formatted = String.format("float %f", f);
        }
        if (num instanceof Double) {
            double d = (Double) num;
            formatted = String.format("double %f", d);
        }
        return formatted;
    }

    public static void main(String[] args) {
        Integer i1 = 1952;
        InstanceofNew pm1 = new InstanceofNew(i1);
        System.out.println(pm1);
        Integer i2 = 1952;
        InstanceofNew pm2 = new InstanceofNew(i2);
        System.out.println(pm1.equals(pm2));
    }
}
InstanceofNew
package pattmatch;

import java.util.Objects;

public class InstanceofNew {

    private final Object num;

    public InstanceofNew(Object num) {
        this.num = num;
    }

    public Object getNum() {
        return num;
    }

    @Override
    public boolean equals(Object o) {

        return (o instanceof InstanceofNew other)
                && (this.num == other.num);
    }

    @Override
    public int hashCode() {
        return Objects.hash(getNum());
    }

    @Override
    public String toString() {
        String formatted;
        if (num instanceof Byte b) {
            formatted = String.format("byte %d", b);
        } else if (num instanceof Short s) {
            formatted = String.format("short %d", s);
        } else if (num instanceof Integer i) {
            formatted = String.format("int %d", i);
        } else if (num instanceof Long l) {
            formatted = String.format("long %d", l);
        } else if (num instanceof Float f) {
            formatted = String.format("float %f", f);
        } else if (num instanceof Double d) {
            formatted = String.format("double %f", d);
        } else {
            formatted = "unknown";
        }
        return formatted;
    }

    public static void main(String[] args) {
        Integer i1 = 1952;
        InstanceofNew pm1 = new InstanceofNew(i1);
        System.out.println(pm1);
        Integer i2 = 1952;
        InstanceofNew pm2 = new InstanceofNew(i2);
        System.out.println(pm1.equals(pm2));
    }
}