java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java
author František Kučera <franta-hg@frantovo.cz>
Sun, 14 Jun 2015 01:41:47 +0200
changeset 27 165fb7ff9855
child 36 03757ff74694
permissions -rw-r--r--
příklad reflexe v Javě – přepisování soukromé proměnné
https://blog.frantovo.cz/c/348/P%C5%99episujeme%20soukrom%C3%A9%20prom%C4%9Bnn%C3%A9%20v%C2%A0Jav%C4%9B%20pomoc%C3%AD%20reflexe
     1 package cz.frantovo.příklady.reflexe;
     2 
     3 import java.lang.reflect.Field;
     4 import java.math.BigDecimal;
     5 import java.math.RoundingMode;
     6 import java.util.function.Consumer;
     7 
     8 /**
     9  *
    10  * @author Ing. František Kučera (frantovo.cz)
    11  */
    12 public class Reflexe {
    13 
    14 	private static final String NÁZEV_PROMĚNNÉ = "proměnná";
    15 	private static final int POČET_OPAKOVÁNÍ = 1000000;
    16 	private static final RoundingMode ZAOKROUHLOVÁNÍ = RoundingMode.UP;
    17 	private static final int PŘESNOST_PROCENT = 2;
    18 
    19 	private static void nastav(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    20 		Field f = objekt.getClass().getDeclaredField(proměnná);
    21 		f.setAccessible(true);
    22 		f.set(objekt, hodnota);
    23 		// TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
    24 	}
    25 
    26 	private static void testSetter(int početOpakování) {
    27 		NějakáTřída t = new NějakáTřída();
    28 		for (int i = 0; i < početOpakování; i++) {
    29 			t.setProměnná(i);
    30 		}
    31 	}
    32 
    33 	private static void testPřímýPřístup(int početOpakování) {
    34 		NějakáTřída t = new NějakáTřída();
    35 		for (int i = 0; i < početOpakování; i++) {
    36 			t.veřejnáProměnná = i;
    37 		}
    38 	}
    39 
    40 	private static void testReflexe(int početOpakování) {
    41 		NějakáTřída t = new NějakáTřída();
    42 		try {
    43 			for (int i = 0; i < početOpakování; i++) {
    44 				nastav(t, NÁZEV_PROMĚNNÉ, i);
    45 			}
    46 		} catch (Exception e) {
    47 			throw new RuntimeException("test se nezdařil", e);
    48 		}
    49 	}
    50 
    51 	private static void testReflexePřipravená(int početOpakování) {
    52 		NějakáTřída t = new NějakáTřída();
    53 		try {
    54 			Field f = t.getClass().getDeclaredField(NÁZEV_PROMĚNNÉ);
    55 			f.setAccessible(true);
    56 			for (int i = 0; i < početOpakování; i++) {
    57 				f.set(t, i);
    58 			}
    59 		} catch (Exception e) {
    60 			throw new RuntimeException("test se nezdařil", e);
    61 		}
    62 	}
    63 
    64 	private static String lpad(int početZnaků, Object text) {
    65 		return String.format("%1$" + početZnaků + "s", String.valueOf(text));
    66 	}
    67 
    68 	private static BigDecimal spočítejProcenta(long hodnota, long základ) {
    69 		BigDecimal h = BigDecimal.valueOf(hodnota);
    70 		BigDecimal z = BigDecimal.valueOf(základ);
    71 		return h.multiply(BigDecimal.valueOf(100)).divide(z, PŘESNOST_PROCENT, ZAOKROUHLOVÁNÍ);
    72 	}
    73 
    74 	private static Long testuj(String názevTestu, int početOpakování, Long časProPorovnání, Consumer<Integer> test) {
    75 		System.out.print("TEST: " + lpad(20, názevTestu) + ": ");
    76 		try {
    77 			long začátek = System.currentTimeMillis();
    78 			test.accept(početOpakování);
    79 			long konec = System.currentTimeMillis();
    80 			long celkovýČas = konec - začátek;
    81 			BigDecimal relativníČas = časProPorovnání == null ? BigDecimal.valueOf(100).setScale(PŘESNOST_PROCENT) : spočítejProcenta(celkovýČas, časProPorovnání);
    82 			System.out.println("početOpakování = " + lpad(12, početOpakování) + " celkovýČas = " + lpad(8, celkovýČas) + " ms relativníČas = " + lpad(8, relativníČas) + " %");
    83 			return celkovýČas;
    84 		} catch (Exception e) {
    85 			System.out.println("došlo k chybě");
    86 			e.printStackTrace();
    87 			return null;
    88 		}
    89 	}
    90 
    91 	public static void main(String[] args) {
    92 		long základníČas = testuj("přímý přístup", POČET_OPAKOVÁNÍ, null, Reflexe::testPřímýPřístup);
    93 		testuj("setter", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testSetter);
    94 		testuj("reflexe", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexe);
    95 		testuj("reflexe připravená", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexePřipravená);
    96 	}
    97 
    98 }