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