# HG changeset patch # User František Kučera # Date 1479590950 -3600 # Node ID 03757ff746945d5efd2ba16cc9104af8689808a9 # Parent ef8152d84946f30289955d8f28537c64f362d4f0 reflexe: vylepšení + netbeans diff -r ef8152d84946 -r 03757ff74694 java/reflexe/nbproject/build-impl.xml --- a/java/reflexe/nbproject/build-impl.xml Sat Nov 19 22:28:08 2016 +0100 +++ b/java/reflexe/nbproject/build-impl.xml Sat Nov 19 22:29:10 2016 +0100 @@ -191,7 +191,12 @@ - + + + + + + @@ -217,6 +222,7 @@ + @@ -693,7 +699,7 @@ - + @@ -768,7 +774,7 @@ - + @@ -795,7 +801,7 @@ - + diff -r ef8152d84946 -r 03757ff74694 java/reflexe/nbproject/genfiles.properties --- a/java/reflexe/nbproject/genfiles.properties Sat Nov 19 22:28:08 2016 +0100 +++ b/java/reflexe/nbproject/genfiles.properties Sat Nov 19 22:29:10 2016 +0100 @@ -4,5 +4,5 @@ # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=cd87ef88 -nbproject/build-impl.xml.script.CRC32=1e64564b -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48 +nbproject/build-impl.xml.script.CRC32=5b12b8e1 +nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48 diff -r ef8152d84946 -r 03757ff74694 java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java --- a/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java Sat Nov 19 22:28:08 2016 +0100 +++ b/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java Sat Nov 19 22:29:10 2016 +0100 @@ -3,6 +3,9 @@ import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.RoundingMode; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; /** @@ -16,6 +19,9 @@ private static final RoundingMode ZAOKROUHLOVÁNÍ = RoundingMode.UP; private static final int PŘESNOST_PROCENT = 2; + private static final Map známáPole = new ConcurrentHashMap<>(); + private static final Map> známáPole2 = new ConcurrentHashMap<>(); + private static void nastav(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field f = objekt.getClass().getDeclaredField(proměnná); f.setAccessible(true); @@ -23,6 +29,67 @@ // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou } + private static void nastavOptimalizovaně(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { + + KlíčTřídaPole klíč = new KlíčTřídaPole(objekt.getClass(), proměnná); + Field f = známáPole.get(klíč); + + if (f == null) { + f = objekt.getClass().getDeclaredField(proměnná); + f.setAccessible(true); + známáPole.put(klíč, f); + } + + f.set(objekt, hodnota); + // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou + } + + private static class KlíčTřídaPole { + + private final Class třída; + private final String pole; + + public KlíčTřídaPole(Class třída, String pole) { + this.třída = třída; + this.pole = pole; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof KlíčTřídaPole) { + KlíčTřídaPole druhýKlíč = (KlíčTřídaPole) obj; + return Objects.equals(třída, druhýKlíč.třída) && Objects.equals(pole, druhýKlíč.pole); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(třída, pole); + } + + } + + private static void nastavOptimalizovaně2(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { + + Map mapaPolí = známáPole2.get(objekt.getClass()); + if (mapaPolí == null) { + mapaPolí = new ConcurrentHashMap<>(); + známáPole2.put(objekt.getClass(), mapaPolí); + } + + Field f = mapaPolí.get(proměnná); + if (f == null) { + f = objekt.getClass().getDeclaredField(proměnná); + f.setAccessible(true); + mapaPolí.put(proměnná, f); + } + + f.set(objekt, hodnota); + // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou + } + private static void testSetter(int početOpakování) { NějakáTřída t = new NějakáTřída(); for (int i = 0; i < početOpakování; i++) { @@ -48,6 +115,28 @@ } } + private static void testReflexeOptimalizovaná(int početOpakování) { + NějakáTřída t = new NějakáTřída(); + try { + for (int i = 0; i < početOpakování; i++) { + nastavOptimalizovaně(t, NÁZEV_PROMĚNNÉ, i); + } + } catch (Exception e) { + throw new RuntimeException("test se nezdařil", e); + } + } + + private static void testReflexeOptimalizovaná2(int početOpakování) { + NějakáTřída t = new NějakáTřída(); + try { + for (int i = 0; i < početOpakování; i++) { + nastavOptimalizovaně2(t, NÁZEV_PROMĚNNÉ, i); + } + } catch (Exception e) { + throw new RuntimeException("test se nezdařil", e); + } + } + private static void testReflexePřipravená(int početOpakování) { NějakáTřída t = new NějakáTřída(); try { @@ -72,7 +161,7 @@ } private static Long testuj(String názevTestu, int početOpakování, Long časProPorovnání, Consumer test) { - System.out.print("TEST: " + lpad(20, názevTestu) + ": "); + System.out.print("TEST: " + lpad(24, názevTestu) + ": "); try { long začátek = System.currentTimeMillis(); test.accept(početOpakování); @@ -92,7 +181,9 @@ long základníČas = testuj("přímý přístup", POČET_OPAKOVÁNÍ, null, Reflexe::testPřímýPřístup); testuj("setter", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testSetter); testuj("reflexe", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexe); + testuj("reflexe optimalizovaná 1", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná); + testuj("reflexe optimalizovaná 2", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná2); testuj("reflexe připravená", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexePřipravená); } -} \ No newline at end of file +}