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:
- sprawdzenie czy num należy do podanego typu (
num instanceof Integer
) - jeśli tak utworzenie nowej zmiennej tego typu (
int i
) - 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ą:
- predicate (warunku), który może być zastosowany do celu
- 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)); } }