java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java
changeset 36 03757ff74694
parent 27 165fb7ff9855
     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 +}