1.1 --- a/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java Sat Nov 19 22:28:08 2016 +0100
1.2 +++ b/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java Sat Nov 19 22:29:10 2016 +0100
1.3 @@ -3,6 +3,9 @@
1.4 import java.lang.reflect.Field;
1.5 import java.math.BigDecimal;
1.6 import java.math.RoundingMode;
1.7 +import java.util.Map;
1.8 +import java.util.Objects;
1.9 +import java.util.concurrent.ConcurrentHashMap;
1.10 import java.util.function.Consumer;
1.11
1.12 /**
1.13 @@ -16,6 +19,9 @@
1.14 private static final RoundingMode ZAOKROUHLOVÁNÍ = RoundingMode.UP;
1.15 private static final int PŘESNOST_PROCENT = 2;
1.16
1.17 + private static final Map<KlíčTřídaPole, Field> známáPole = new ConcurrentHashMap<>();
1.18 + private static final Map<Class, Map<String, Field>> známáPole2 = new ConcurrentHashMap<>();
1.19 +
1.20 private static void nastav(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
1.21 Field f = objekt.getClass().getDeclaredField(proměnná);
1.22 f.setAccessible(true);
1.23 @@ -23,6 +29,67 @@
1.24 // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
1.25 }
1.26
1.27 + private static void nastavOptimalizovaně(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
1.28 +
1.29 + KlíčTřídaPole klíč = new KlíčTřídaPole(objekt.getClass(), proměnná);
1.30 + Field f = známáPole.get(klíč);
1.31 +
1.32 + if (f == null) {
1.33 + f = objekt.getClass().getDeclaredField(proměnná);
1.34 + f.setAccessible(true);
1.35 + známáPole.put(klíč, f);
1.36 + }
1.37 +
1.38 + f.set(objekt, hodnota);
1.39 + // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
1.40 + }
1.41 +
1.42 + private static class KlíčTřídaPole {
1.43 +
1.44 + private final Class třída;
1.45 + private final String pole;
1.46 +
1.47 + public KlíčTřídaPole(Class třída, String pole) {
1.48 + this.třída = třída;
1.49 + this.pole = pole;
1.50 + }
1.51 +
1.52 + @Override
1.53 + public boolean equals(Object obj) {
1.54 + if (obj instanceof KlíčTřídaPole) {
1.55 + KlíčTřídaPole druhýKlíč = (KlíčTřídaPole) obj;
1.56 + return Objects.equals(třída, druhýKlíč.třída) && Objects.equals(pole, druhýKlíč.pole);
1.57 + } else {
1.58 + return false;
1.59 + }
1.60 + }
1.61 +
1.62 + @Override
1.63 + public int hashCode() {
1.64 + return Objects.hash(třída, pole);
1.65 + }
1.66 +
1.67 + }
1.68 +
1.69 + private static void nastavOptimalizovaně2(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
1.70 +
1.71 + Map<String, Field> mapaPolí = známáPole2.get(objekt.getClass());
1.72 + if (mapaPolí == null) {
1.73 + mapaPolí = new ConcurrentHashMap<>();
1.74 + známáPole2.put(objekt.getClass(), mapaPolí);
1.75 + }
1.76 +
1.77 + Field f = mapaPolí.get(proměnná);
1.78 + if (f == null) {
1.79 + f = objekt.getClass().getDeclaredField(proměnná);
1.80 + f.setAccessible(true);
1.81 + mapaPolí.put(proměnná, f);
1.82 + }
1.83 +
1.84 + f.set(objekt, hodnota);
1.85 + // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
1.86 + }
1.87 +
1.88 private static void testSetter(int početOpakování) {
1.89 NějakáTřída t = new NějakáTřída();
1.90 for (int i = 0; i < početOpakování; i++) {
1.91 @@ -48,6 +115,28 @@
1.92 }
1.93 }
1.94
1.95 + private static void testReflexeOptimalizovaná(int početOpakování) {
1.96 + NějakáTřída t = new NějakáTřída();
1.97 + try {
1.98 + for (int i = 0; i < početOpakování; i++) {
1.99 + nastavOptimalizovaně(t, NÁZEV_PROMĚNNÉ, i);
1.100 + }
1.101 + } catch (Exception e) {
1.102 + throw new RuntimeException("test se nezdařil", e);
1.103 + }
1.104 + }
1.105 +
1.106 + private static void testReflexeOptimalizovaná2(int početOpakování) {
1.107 + NějakáTřída t = new NějakáTřída();
1.108 + try {
1.109 + for (int i = 0; i < početOpakování; i++) {
1.110 + nastavOptimalizovaně2(t, NÁZEV_PROMĚNNÉ, i);
1.111 + }
1.112 + } catch (Exception e) {
1.113 + throw new RuntimeException("test se nezdařil", e);
1.114 + }
1.115 + }
1.116 +
1.117 private static void testReflexePřipravená(int početOpakování) {
1.118 NějakáTřída t = new NějakáTřída();
1.119 try {
1.120 @@ -72,7 +161,7 @@
1.121 }
1.122
1.123 private static Long testuj(String názevTestu, int početOpakování, Long časProPorovnání, Consumer<Integer> test) {
1.124 - System.out.print("TEST: " + lpad(20, názevTestu) + ": ");
1.125 + System.out.print("TEST: " + lpad(24, názevTestu) + ": ");
1.126 try {
1.127 long začátek = System.currentTimeMillis();
1.128 test.accept(početOpakování);
1.129 @@ -92,7 +181,9 @@
1.130 long základníČas = testuj("přímý přístup", POČET_OPAKOVÁNÍ, null, Reflexe::testPřímýPřístup);
1.131 testuj("setter", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testSetter);
1.132 testuj("reflexe", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexe);
1.133 + testuj("reflexe optimalizovaná 1", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná);
1.134 + testuj("reflexe optimalizovaná 2", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná2);
1.135 testuj("reflexe připravená", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexePřipravená);
1.136 }
1.137
1.138 -}
1.139 \ No newline at end of file
1.140 +}