reflexe: vylepšení + netbeans
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 19 Nov 2016 22:29:10 +0100
changeset 3603757ff74694
parent 35 ef8152d84946
child 37 0a06481eec13
reflexe: vylepšení + netbeans
java/reflexe/nbproject/build-impl.xml
java/reflexe/nbproject/genfiles.properties
java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java
     1.1 --- a/java/reflexe/nbproject/build-impl.xml	Sat Nov 19 22:28:08 2016 +0100
     1.2 +++ b/java/reflexe/nbproject/build-impl.xml	Sat Nov 19 22:29:10 2016 +0100
     1.3 @@ -191,7 +191,12 @@
     1.4                  </not>
     1.5              </and>
     1.6          </condition>
     1.7 -        <property name="javac.fork" value="${jdkBug6558476}"/>
     1.8 +        <condition else="false" property="javac.fork">
     1.9 +            <or>
    1.10 +                <istrue value="${jdkBug6558476}"/>
    1.11 +                <istrue value="${javac.external.vm}"/>
    1.12 +            </or>
    1.13 +        </condition>
    1.14          <property name="jar.index" value="false"/>
    1.15          <property name="jar.index.metainf" value="${jar.index}"/>
    1.16          <property name="copylibs.rebase" value="true"/>
    1.17 @@ -217,6 +222,7 @@
    1.18          <condition else="" property="testng.debug.mode" value="-mixed">
    1.19              <istrue value="${junit+testng.available}"/>
    1.20          </condition>
    1.21 +        <property name="java.failonerror" value="true"/>
    1.22      </target>
    1.23      <target name="-post-init">
    1.24          <!-- Empty placeholder for easier customization. -->
    1.25 @@ -693,7 +699,7 @@
    1.26              <sequential>
    1.27                  <property environment="env"/>
    1.28                  <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
    1.29 -                <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
    1.30 +                <java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}">
    1.31                      <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
    1.32                      <jvmarg value="${profiler.info.jvmargs.agent}"/>
    1.33                      <jvmarg line="${profiler.info.jvmargs}"/>
    1.34 @@ -768,7 +774,7 @@
    1.35              <attribute default="${debug.classpath}" name="classpath"/>
    1.36              <element name="customize" optional="true"/>
    1.37              <sequential>
    1.38 -                <java classname="@{classname}" dir="${work.dir}" fork="true">
    1.39 +                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
    1.40                      <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
    1.41                      <jvmarg line="${debug-args-line}"/>
    1.42                      <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
    1.43 @@ -795,7 +801,7 @@
    1.44              <attribute default="jvm" name="jvm"/>
    1.45              <element name="customize" optional="true"/>
    1.46              <sequential>
    1.47 -                <java classname="@{classname}" dir="${work.dir}" fork="true">
    1.48 +                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
    1.49                      <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
    1.50                      <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
    1.51                      <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
     2.1 --- a/java/reflexe/nbproject/genfiles.properties	Sat Nov 19 22:28:08 2016 +0100
     2.2 +++ b/java/reflexe/nbproject/genfiles.properties	Sat Nov 19 22:29:10 2016 +0100
     2.3 @@ -4,5 +4,5 @@
     2.4  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     2.5  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
     2.6  nbproject/build-impl.xml.data.CRC32=cd87ef88
     2.7 -nbproject/build-impl.xml.script.CRC32=1e64564b
     2.8 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
     2.9 +nbproject/build-impl.xml.script.CRC32=5b12b8e1
    2.10 +nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48
     3.1 --- a/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java	Sat Nov 19 22:28:08 2016 +0100
     3.2 +++ b/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java	Sat Nov 19 22:29:10 2016 +0100
     3.3 @@ -3,6 +3,9 @@
     3.4  import java.lang.reflect.Field;
     3.5  import java.math.BigDecimal;
     3.6  import java.math.RoundingMode;
     3.7 +import java.util.Map;
     3.8 +import java.util.Objects;
     3.9 +import java.util.concurrent.ConcurrentHashMap;
    3.10  import java.util.function.Consumer;
    3.11  
    3.12  /**
    3.13 @@ -16,6 +19,9 @@
    3.14  	private static final RoundingMode ZAOKROUHLOVÁNÍ = RoundingMode.UP;
    3.15  	private static final int PŘESNOST_PROCENT = 2;
    3.16  
    3.17 +	private static final Map<KlíčTřídaPole, Field> známáPole = new ConcurrentHashMap<>();
    3.18 +	private static final Map<Class, Map<String, Field>> známáPole2 = new ConcurrentHashMap<>();
    3.19 +
    3.20  	private static void nastav(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    3.21  		Field f = objekt.getClass().getDeclaredField(proměnná);
    3.22  		f.setAccessible(true);
    3.23 @@ -23,6 +29,67 @@
    3.24  		// TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
    3.25  	}
    3.26  
    3.27 +	private static void nastavOptimalizovaně(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    3.28 +
    3.29 +		KlíčTřídaPole klíč = new KlíčTřídaPole(objekt.getClass(), proměnná);
    3.30 +		Field f = známáPole.get(klíč);
    3.31 +
    3.32 +		if (f == null) {
    3.33 +			f = objekt.getClass().getDeclaredField(proměnná);
    3.34 +			f.setAccessible(true);
    3.35 +			známáPole.put(klíč, f);
    3.36 +		}
    3.37 +
    3.38 +		f.set(objekt, hodnota);
    3.39 +		// TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
    3.40 +	}
    3.41 +
    3.42 +	private static class KlíčTřídaPole {
    3.43 +
    3.44 +		private final Class třída;
    3.45 +		private final String pole;
    3.46 +
    3.47 +		public KlíčTřídaPole(Class třída, String pole) {
    3.48 +			this.třída = třída;
    3.49 +			this.pole = pole;
    3.50 +		}
    3.51 +
    3.52 +		@Override
    3.53 +		public boolean equals(Object obj) {
    3.54 +			if (obj instanceof KlíčTřídaPole) {
    3.55 +				KlíčTřídaPole druhýKlíč = (KlíčTřídaPole) obj;
    3.56 +				return Objects.equals(třída, druhýKlíč.třída) && Objects.equals(pole, druhýKlíč.pole);
    3.57 +			} else {
    3.58 +				return false;
    3.59 +			}
    3.60 +		}
    3.61 +
    3.62 +		@Override
    3.63 +		public int hashCode() {
    3.64 +			return Objects.hash(třída, pole);
    3.65 +		}
    3.66 +
    3.67 +	}
    3.68 +
    3.69 +	private static void nastavOptimalizovaně2(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    3.70 +
    3.71 +		Map<String, Field> mapaPolí = známáPole2.get(objekt.getClass());
    3.72 +		if (mapaPolí == null) {
    3.73 +			mapaPolí = new ConcurrentHashMap<>();
    3.74 +			známáPole2.put(objekt.getClass(), mapaPolí);
    3.75 +		}
    3.76 +
    3.77 +		Field f = mapaPolí.get(proměnná);
    3.78 +		if (f == null) {
    3.79 +			f = objekt.getClass().getDeclaredField(proměnná);
    3.80 +			f.setAccessible(true);
    3.81 +			mapaPolí.put(proměnná, f);
    3.82 +		}
    3.83 +
    3.84 +		f.set(objekt, hodnota);
    3.85 +		// TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
    3.86 +	}
    3.87 +
    3.88  	private static void testSetter(int početOpakování) {
    3.89  		NějakáTřída t = new NějakáTřída();
    3.90  		for (int i = 0; i < početOpakování; i++) {
    3.91 @@ -48,6 +115,28 @@
    3.92  		}
    3.93  	}
    3.94  
    3.95 +	private static void testReflexeOptimalizovaná(int početOpakování) {
    3.96 +		NějakáTřída t = new NějakáTřída();
    3.97 +		try {
    3.98 +			for (int i = 0; i < početOpakování; i++) {
    3.99 +				nastavOptimalizovaně(t, NÁZEV_PROMĚNNÉ, i);
   3.100 +			}
   3.101 +		} catch (Exception e) {
   3.102 +			throw new RuntimeException("test se nezdařil", e);
   3.103 +		}
   3.104 +	}
   3.105 +
   3.106 +	private static void testReflexeOptimalizovaná2(int početOpakování) {
   3.107 +		NějakáTřída t = new NějakáTřída();
   3.108 +		try {
   3.109 +			for (int i = 0; i < početOpakování; i++) {
   3.110 +				nastavOptimalizovaně2(t, NÁZEV_PROMĚNNÉ, i);
   3.111 +			}
   3.112 +		} catch (Exception e) {
   3.113 +			throw new RuntimeException("test se nezdařil", e);
   3.114 +		}
   3.115 +	}
   3.116 +
   3.117  	private static void testReflexePřipravená(int početOpakování) {
   3.118  		NějakáTřída t = new NějakáTřída();
   3.119  		try {
   3.120 @@ -72,7 +161,7 @@
   3.121  	}
   3.122  
   3.123  	private static Long testuj(String názevTestu, int početOpakování, Long časProPorovnání, Consumer<Integer> test) {
   3.124 -		System.out.print("TEST: " + lpad(20, názevTestu) + ": ");
   3.125 +		System.out.print("TEST: " + lpad(24, názevTestu) + ": ");
   3.126  		try {
   3.127  			long začátek = System.currentTimeMillis();
   3.128  			test.accept(početOpakování);
   3.129 @@ -92,7 +181,9 @@
   3.130  		long základníČas = testuj("přímý přístup", POČET_OPAKOVÁNÍ, null, Reflexe::testPřímýPřístup);
   3.131  		testuj("setter", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testSetter);
   3.132  		testuj("reflexe", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexe);
   3.133 +		testuj("reflexe optimalizovaná 1", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná);
   3.134 +		testuj("reflexe optimalizovaná 2", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná2);
   3.135  		testuj("reflexe připravená", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexePřipravená);
   3.136  	}
   3.137  
   3.138 -} 
   3.139 \ No newline at end of file
   3.140 +}