===== FallPits ===== * When doing Collection.equals(Collection2) - look out for different implementation. See chapter Collection.Comparisson * // what happens in new B() ? class A{ int size =1 public A(){ System.out.println(size); } } class B exends A{ { int size = 2 } public B(){ System.out.println(size); } } // new B() prints 1, becuase the block is called AFTER the constructor call ===== Libs ===== ^Object^ Comparisson^ Details ^ |[[http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/builder/EqualsBuilder.html|Apache Commons]] |EqualsBuilder.reflectionEquals(Object o1, Object o2)| Helps to implement Object comparison | |[[https://en.wikipedia.org/wiki/Javassist|Javassist]] | | Implements powerfull reflection funcitonality, e.g. proxies | ===== Available JDKs ===== https://sdkman.io/jdks ===== install alternative JDK using SDKman ===== install SDK man # sdkman curl -fsSL "https://get.sdkman.io?rcupdate=false" | bash Install sdk man in silent mode # sdkman curl -fsSL "https://get.sdkman.io?rcupdate=false" | bash List and install java sdk list java ================================================================================ Available Java Versions for Linux 64bit ================================================================================ Vendor | Use | Version | Dist | Status | Identifier -------------------------------------------------------------------------------- Corretto | | 19.0.2 | amzn | | 19.0.2-amzn | | 19.0.1 | amzn | | 19.0.1-amzn | | 17.0.6 | amzn | | 17.0.6-amzn | | 17.0.5 | amzn | | 17.0.5-amzn | | 11.0.18 | amzn | | 11.0.18-amzn | | 11.0.17 | amzn | | 11.0.17-amzn | | 8.0.362 | amzn | | 8.0.362-amzn | | 8.0.352 | amzn | | 8.0.352-amzn Dragonwell | | 17.0.6 | albba | | 17.0.6-albba | | 17.0.5 | albba | | 17.0.5-albba | | 17.0.4 | albba | | 17.0.4-albba | | 11.0.18 | albba | | 11.0.18-albba | | 11.0.17 | albba | | 11.0.17-albba | | 11.0.16 | albba | | 11.0.16-albba | | 8.0.362 | albba | | 8.0.362-albba | | 8.0.352 | albba | | 8.0.352-albba | | 8.0.345 | albba | | 8.0.345-albba Gluon | | 22.1.0.1.r17 | gln | | 22.1.0.1.r17-gln | | 22.1.0.1.r11 | gln | | 22.1.0.1.r11-gln GraalVM | | 22.3.r19 | grl | | 22.3.r19-grl | | 22.3.r17 | grl | | 22.3.r17-grl | | 22.3.r11 | grl | | 22.3.r11-grl | | 22.3.1.r19 | grl | | 22.3.1.r19-grl | | 22.3.1.r17 | grl | | 22.3.1.r17-grl | | 22.3.1.r11 | grl | | 22.3.1.r11-grl | | 22.2.r17 | grl | | 22.2.r17-grl | | 22.2.r11 | grl | | 22.2.r11-grl | | 22.1.0.r17 | grl | | 22.1.0.r17-grl | | 22.1.0.r11 | grl | | 22.1.0.r11-grl | | 22.0.0.2.r17 | grl | | 22.0.0.2.r17-grl | | 22.0.0.2.r11 | grl | | 22.0.0.2.r11-grl | | 21.3.3.r17 | grl | | 21.3.3.r17-grl | | 21.3.3.r11 | grl | | 21.3.3.r11-grl | | 21.3.3.1.r17 | grl | | 21.3.3.1.r17-grl | | 21.3.3.1.r11 | grl | | 21.3.3.1.r11-grl | | 21.3.2.r17 | grl | | 21.3.2.r17-grl | | 21.3.2.r11 | grl | | 21.3.2.r11-grl | | 21.3.1.r8 | grl | | 21.3.1.r8-grl | | 21.2.0.r8 | grl | | 21.2.0.r8-grl | | 21.1.0.r8 | grl | | 21.1.0.r8-grl | | 20.3.6.r11 | grl | | 20.3.6.r11-grl | | 20.3.3.r8 | grl | | 20.3.3.r8-grl | | 20.3.2.r8 | grl | | 20.3.2.r8-grl | | 19.3.6.r11 | grl | | 19.3.6.r11-grl | | 19.3.6.r8 | grl | | 19.3.6.r8-grl Java.net | | 21.ea.8 | open | | 21.ea.8-open | | 21.ea.7 | open | | 21.ea.7-open | | 21.ea.6 | open | | 21.ea.6-open | | 21.ea.5 | open | | 21.ea.5-open | | 21.ea.4 | open | | 21.ea.4-open | | 20.ea.34 | open | | 20.ea.34-open | | 20.ea.33 | open | | 20.ea.33-open | | 20.ea.32 | open | | 20.ea.32-open | | 20.ea.31 | open | | 20.ea.31-open | | 20.ea.30 | open | | 20.ea.30-open | | 19.ea.1.pma | open | | 19.ea.1.pma-open | | 19.0.2 | open | | 19.0.2-open | | 19.0.1 | open | | 19.0.1-open | | 11.0.12 | open | | 11.0.12-open | | 11.0.2 | open | | 11.0.2-open | | 8.0.302 | open | | 8.0.302-open | | 8.0.282 | open | | 8.0.282-open | | 8.0.265 | open | | 8.0.265-open Liberica | | 19.0.2.fx | librca | | 19.0.2.fx-librca | | 19.0.2 | librca | | 19.0.2-librca | | 19.0.1.fx | librca | | 19.0.1.fx-librca | | 19.0.1 | librca | | 19.0.1-librca | | 17.0.6.fx | librca | | 17.0.6.fx-librca | | 17.0.6 | librca | | 17.0.6-librca | | 17.0.5.fx | librca | | 17.0.5.fx-librca | | 17.0.5 | librca | | 17.0.5-librca | | 11.0.18.fx | librca | | 11.0.18.fx-librca | | 11.0.18 | librca | | 11.0.18-librca | | 11.0.17.fx | librca | | 11.0.17.fx-librca | | 11.0.17 | librca | | 11.0.17-librca | | 8.0.362.fx | librca | | 8.0.362.fx-librca | | 8.0.362 | librca | | 8.0.362-librca | | 8.0.352.fx | librca | | 8.0.352.fx-librca | | 8.0.352 | librca | | 8.0.352-librca | | 8.0.332.fx | librca | | 8.0.332.fx-librca Liberica NIK | | 22.3.r17 | nik | | 22.3.r17-nik | | 22.3.r11 | nik | | 22.3.r11-nik | | 22.3.1.r17 | nik | | 22.3.1.r17-nik | | 22.3.1.r11 | nik | | 22.3.1.r11-nik | | 22.2.r17 | nik | | 22.2.r17-nik | | 22.2.r11 | nik | | 22.2.r11-nik | | 22.1.r17 | nik | | 22.1.r17-nik | | 22.1.r11 | nik | | 22.1.r11-nik | | 22.0.0.2.r17 | nik | | 22.0.0.2.r17-nik | | 22.0.0.2.r11 | nik | | 22.0.0.2.r11-nik | | 21.3.3.r17 | nik | | 21.3.3.r17-nik | | 21.3.3.r11 | nik | | 21.3.3.r11-nik | | 21.3.3.1.r17 | nik | | 21.3.3.1.r17-nik | | 21.3.3.1.r11 | nik | | 21.3.3.1.r11-nik | | 21.3.2.r17 | nik | | 21.3.2.r17-nik | | 21.3.2.r11 | nik | | 21.3.2.r11-nik | | 21.2 | nik | | 21.2-nik | | 21.1 | nik | | 21.1-nik | | 21.0.0.2.r11 | nik | | 21.0.0.2.r11-nik | | 21.0.0.2 | nik | | 21.0.0.2-nik Mandrel | | 22.3.1.r17 | mandrel | | 22.3.1.r17-mandrel | | 22.3.0.1.r17 | mandrel | | 22.3.0.1.r17-mandrel | | 22.2.r17 | mandrel | | 22.2.r17-mandrel | | 22.2.r11 | mandrel | | 22.2.r11-mandrel | | 22.1.0.0.r17 | mandrel | | 22.1.0.0.r17-mandrel | | 22.1.0.0.r11 | mandrel | | 22.1.0.0.r11-mandrel | | 22.0.0.2.r17 | mandrel | | 22.0.0.2.r17-mandrel | | 22.0.0.2.r11 | mandrel | | 22.0.0.2.r11-mandrel | | 21.3.5.1.r17 | mandrel | | 21.3.5.1.r17-mandrel | | 21.3.5.1.r11 | mandrel | | 21.3.5.1.r11-mandrel | | 21.3.4.r17 | mandrel | | 21.3.4.r17-mandrel | | 21.3.4.r11 | mandrel | | 21.3.4.r11-mandrel | | 21.3.3.r17 | mandrel | | 21.3.3.r17-mandrel | | 21.3.3.r11 | mandrel | | 21.3.3.r11-mandrel | | 21.3.2.0.r17 | mandrel | | 21.3.2.0.r17-mandrel | | 21.3.2.0.r11 | mandrel | | 21.3.2.0.r11-mandrel | | 21.3.1.1.r17 | mandrel | | 21.3.1.1.r17-mandrel | | 21.3.1.1.r11 | mandrel | | 21.3.1.1.r11-mandrel | | 21.3.1.0.r17 | mandrel | | 21.3.1.0.r17-mandrel | | 21.3.1.0.r11 | mandrel | | 21.3.1.0.r11-mandrel | | 21.3.0.0 | mandrel | | 21.3.0.0-mandrel | | 21.2.0.2 | mandrel | | 21.2.0.2-mandrel | | 20.3.3.0 | mandrel | | 20.3.3.0-mandrel Microsoft | | 17.0.6 | ms | | 17.0.6-ms | | 17.0.5 | ms | | 17.0.5-ms | | 11.0.18 | ms | | 11.0.18-ms | | 11.0.17 | ms | | 11.0.17-ms Oracle | | 19.0.2 | oracle | | 19.0.2-oracle | | 19.0.1 | oracle | | 19.0.1-oracle | | 17.0.6 | oracle | | 17.0.6-oracle | | 17.0.5 | oracle | | 17.0.5-oracle SapMachine | | 19.0.2 | sapmchn | | 19.0.2-sapmchn | | 19.0.1 | sapmchn | | 19.0.1-sapmchn | | 17.0.6 | sapmchn | | 17.0.6-sapmchn | | 17.0.5 | sapmchn | | 17.0.5-sapmchn | | 11.0.18 | sapmchn | | 11.0.18-sapmchn | | 11.0.17 | sapmchn | | 11.0.17-sapmchn Semeru | | 18.0.2 | sem | | 18.0.2-sem | | 17.0.5 | sem | | 17.0.5-sem | | 17.0.4.1 | sem | | 17.0.4.1-sem | | 11.0.17 | sem | | 11.0.17-sem | | 11.0.16.1 | sem | | 11.0.16.1-sem | | 8.0.352 | sem | | 8.0.352-sem | | 8.0.345 | sem | | 8.0.345-sem Temurin | | 19.0.2 | tem | | 19.0.2-tem | | 19.0.1 | tem | | 19.0.1-tem | | 17.0.6 | tem | | 17.0.6-tem | | 17.0.5 | tem | | 17.0.5-tem | | 11.0.18 | tem | | 11.0.18-tem | | 11.0.17 | tem | | 11.0.17-tem | | 8.0.362 | tem | | 8.0.362-tem | | 8.0.352 | tem | | 8.0.352-tem | | 8.0.345 | tem | | 8.0.345-tem Trava | | 11.0.15 | trava | | 11.0.15-trava | | 11.0.9 | trava | | 11.0.9-trava | | 8.0.282 | trava | | 8.0.282-trava | | 8.0.232 | trava | | 8.0.232-trava Zulu | | 19.0.2 | zulu | | 19.0.2-zulu | | 19.0.2.fx | zulu | | 19.0.2.fx-zulu | | 19.0.1 | zulu | | 19.0.1-zulu | | 19.0.1.fx | zulu | | 19.0.1.fx-zulu | | 17.0.6 | zulu | | 17.0.6-zulu | | 17.0.6.fx | zulu | | 17.0.6.fx-zulu | | 17.0.5 | zulu | | 17.0.5-zulu | | 17.0.5.fx | zulu | | 17.0.5.fx-zulu | | 11.0.18 | zulu | | 11.0.18-zulu | | 11.0.18.fx | zulu | | 11.0.18.fx-zulu | | 11.0.17 | zulu | | 11.0.17-zulu | | 11.0.17.fx | zulu | | 11.0.17.fx-zulu | | 8.0.362 | zulu | | 8.0.362-zulu | | 8.0.362.fx | zulu | | 8.0.362.fx-zulu | | 8.0.352 | zulu | | 8.0.352-zulu | | 8.0.352.fx | zulu | | 8.0.352.fx-zulu | | 7.0.352 | zulu | | 7.0.352-zulu | | 6.0.119 | zulu | | 6.0.119-zulu ================================================================================ Omit Identifier to install default version 17.0.6-tem: $ sdk install java Use TAB completion to discover available versions $ sdk install java [TAB] Or install a specific version by Identifier: $ sdk install java 17.0.6-tem Hit Q to exit this list view ================================================================================ silent installing some java # java open GraalVM from liberica "native image kit" sdk install java 22.3.r17-nik < /dev/null # java openjdk sdk install java 19.0.2-open < /dev/null switching version sdk use java 19.0.2-open sdk use java 22.3.r17-nik ===== install alternative JDK in parallel and switch ===== https://ubunlog.com/en/instala-java-8-9-y-10-en-ubuntu-18-04-y-derivados/ sudo apt-get update // check which openjdk versions are available apt-cache search openjdk.*-jdk // install some JDK sudo apt install openjdk-8-jdk sudo apt install openjdk-9-jdk sudo apt install openjdk-11-jdk sudo apt install openjdk-17-jdk // list update-java-alternatives -l // switch sudo update-alternatives --config java There are 3 choices for the alternative java (providing /usr/bin/java). Selection Path... ------------------------------------------------------------ 0 /usr/lib/jvm/java-9-oracle/bin/java... * 1 /usr/lib/jvm/java-7-oracle/jre/bin/java... 2 /usr/lib/jvm/java-8-oracle/jre/bin/java... 3 /usr/lib/jvm/java-9-oracle/bin/java... ===== JDK Tools ===== Java consists of many tools Here is a full list: http://docs.oracle.com/javase/8/docs/technotes/tools/#basic Here are some tools, which I think are most useful: | java | launcher for java apps | | javac | compiler for the Java programms | | keytools | manages keystores, certificates | | jar | creates jars | | jarsigner | signs the jars using certificates | | jvisualvm | Tool to monitor a Java-Application (JVM) | | jconsole | wie jvisualvm | | | | ===== Garbage Collector, Java Memory (Heap, Stack) ===== == Heap == * **Process size** of your java app * **Native Heap** (C-Heap) - JVM uses this memory for its internal operations (JDBC Drivers allocate memory. IO OPerations may allocate native memory.) * **Java-Heap** - **Memory area**, from which memory for all **class-instances**, **arrays** is allocated * **Young Gen** - space for new Objects * Eden * Survivor1 * Survivor2 * **Old Gen** - space for Objects, which survived multiple Garbadge Collector runs Java-Heap is reclaimed by garbage collector. \\ More about garbage collector is described here: \\ http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html In Java8 the memory model was redesigned (PermGen was eliminated) {{http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/images/gcslides/Slide5.png?600}} {{http://i520.photobucket.com/albums/w327/schajtan/2015-10-08_20-08-38_zps2kxezs3c.png?600}} ===== JavaDoc ===== JavaDoc can contain Pictures /** Sorts labels according to {@link #LABEL_PRIORITY} * */ public static final method() { } ===== Annotations ===== * The annotations in java are like interface. * Annotations are applied to classes (methods, parameters) - not to objects! * Annotations are markers, which are used when evaluating by using **reflections**. * Via annotation parameters only following Types may be passed: \\ **primitive type, String, Class, annotation, enumeration, or 1-dimensional arrays thereof** Details are here: http://en.wikipedia.org/wiki/Java_annotation package com.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.METHOD, ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE, ElementType.PACKAGE,ElementType.FIELD,ElementType.LOCAL_VARIABLE}) @Inherited public @interface Unfinished { public enum Priority { LOW, MEDIUM, HIGH } String value(); String[] changedBy() default ""; String[] lastChangedBy() default ""; Priority priority() default Priority.MEDIUM; String createdBy() default "James Gosling"; String lastChanged() default "08/07/2011"; } @Unfinished( Proority = HIGH, value=2, createdBy="Mr. Anderson") class MyClass{ } ===== POJO, JavaBean, DTO, ValueObject ===== Here are some details about the differences: http://stackoverflow.com/questions/1612334/difference-between-dto-vo-pojo-javabeans Java provides some API to work with JavaBean getter / setter BeanInfo info = Introspector.getBeanInfo(domainObjectType); PropertyDescriptor[] props = info.getPropertyDescriptors(); for (PropertyDescriptor pd : props) { Class propertyType = pd.getPropertyType(); String propertyName = pd.getName(); } ===== Collections ===== == LinkedList == // good to iterate over elements, stop on each element while condition is true LinkedList.getFirst(); LinkedList.removeFirst(); ==== Comparisson ==== The Following code does different things. Collection.equals(Collection) In **HashMaps**: it copares the elements in collections, by computing a key for every element, which is a hash and checking, whether the other collection contains the key. The implementation of MyObject.equals() is never called. In **ArrayList**: it copares the elements in collections, by doing MyObject.equals(MyObject2) for every element. ==== Multithreading ==== ==Threadlocal variables == It may happen, that every thread should have an own variable. private static final ThreadLocal current = new ThreadLocal<>(); public static void setCurrent(ApplicationContext context) { current.set(context); } public static ApplicationContext getCurrent() { return current.get(); } ===== Enums with Parameters ===== The Enum can hava a Constructor and Methods. It can be used to create many constants, dependent on X factors, like price ... Example: http://www.avajava.com/tutorials/lessons/how-do-i-use-the-enum-type-with-a-constructor.html ===== Logging ===== ==== Logging Fascade ==== The jar with a logging Fascade contains a bunch of interfaces, without implementation. The implementation of the interfaces are provided in a separate jar, see logging engine. The following logging Fascade are available: |Slf4J| Most popular logging interfaces in the java world. | |Apache’s commons-logging| Less popular option. | ==== Logging Engine ==== |Log4j2| Replaces Log4j. Claims to be faster, than the predecessor.| |LogBack| which is an evolved version of Log4j. Logback is the implementation of the SL4J interfaces. The Details are here: http://logback.qos.ch/ This implementation is available for all platforms. Once learned it can be reused. The configurations may be done in XML or in code. Sometimes they do not work in XML, here an example of a configuration in code. | ==== Details Logback ==== ^Concept ^ Explanation^ |Logger | hiererachy - loggers are hierarchically arranged by name. The names mark the packages/classes which the messages d ooriginate from! "com.test.logger" is parent of "com.test.logger.core" is parent of "com.test.logger.core.gui" is parent of .. | |Appender | the Objects which are attached to the Loggers. They are responsible for writing down the output into Files, Consoles etc. Each Logger may have multiple appenders. | |LoggerContext | is reponsible for maufacturing loggers! Every logger is attached to one. | |Layout | configures the Format of the output messages, e.g. : 176 [main] DEBUG manual.architecture.HelloWorld2 - Hello world. | |TurboFilter | is used to deny or accept messages according to some conditions. LevelFilter can be used to filter messages below of level ERROR for an appender. Then several appenders with different LevelFilters can be applied to the same logging level. | import java.io.File; import org.slf4j.LoggerFactory; import android.os.Environment; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.android.LogcatAppender; import ch.qos.logback.classic.encoder.PatternLayoutEncoder; import ch.qos.logback.classic.filter.LevelFilter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.rolling.RollingFileAppender; import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy; import ch.qos.logback.core.rolling.TimeBasedRollingPolicy; import ch.qos.logback.core.spi.FilterReply; public class LoggerConfig { //The path is relative to the Android External storage. final static String LOG_DIR_REL_PATH = "/Android/data/de.ivu.eticket.app/logs"; final static String MAX_FILE_SIZE = "30MB"; final static String LOG_PATTERN = "%-7level %date{dd MMM HH:mm} [%thread]: %message%n"; final static String FILENAME_ERRORS = "logErrors"; final static String FILENAME_TRACE = "logТrace"; public static void configureLogbackDirectly() { File file = Environment.getExternalStorageDirectory(); String pathExternalStorage = file.getPath(); String logPathAbsolute = pathExternalStorage + LOG_DIR_REL_PATH; LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); context.reset(); //FILE ERRORS RollingFileAppender rollingFileAppenderErrors = new RollingFileAppender(); rollingFileAppenderErrors.setAppend(true); rollingFileAppenderErrors.setContext(context); // OPTIONAL: Set an active log file (separate from the rollover files). // If rollingPolicy.fileNamePattern already set, you don't need this. rollingFileAppenderErrors.setFile(logPathAbsolute + "/"+FILENAME_ERRORS+".txt"); TimeBasedRollingPolicy rollingPolicy1 = new TimeBasedRollingPolicy(); rollingPolicy1.setFileNamePattern(logPathAbsolute + "/" +FILENAME_ERRORS+".%d.txt"); //is overridden by setFile() but necessary rollingPolicy1.setMaxHistory(7); rollingPolicy1.setParent(rollingFileAppenderErrors); // parent and context required! rollingPolicy1.setContext(context); rollingPolicy1.start(); rollingFileAppenderErrors.setRollingPolicy(rollingPolicy1); SizeBasedTriggeringPolicy sizePolicy1 = new SizeBasedTriggeringPolicy(); sizePolicy1.setMaxFileSize(MAX_FILE_SIZE); sizePolicy1.start(); rollingFileAppenderErrors.setTriggeringPolicy(sizePolicy1); LevelFilter levelFilter1 = new LevelFilter(); levelFilter1.setLevel(Level.ERROR); levelFilter1.start(); levelFilter1.setOnMatch(FilterReply.ACCEPT); levelFilter1.setOnMismatch(FilterReply.DENY); rollingFileAppenderErrors.addFilter(levelFilter1); PatternLayoutEncoder encoder1 = new PatternLayoutEncoder(); encoder1.setPattern(LOG_PATTERN); encoder1.setContext(context); encoder1.start(); rollingFileAppenderErrors.setEncoder(encoder1); rollingFileAppenderErrors.start(); //FILE DEBUG RollingFileAppender rollingFileAppenderDebug = new RollingFileAppender(); rollingFileAppenderDebug.setAppend(true); rollingFileAppenderDebug.setContext(context); // OPTIONAL: Set an active log file (separate from the rollover files). // If rollingPolicy.fileNamePattern already set, you don't need this. rollingFileAppenderDebug.setFile(logPathAbsolute + "/"+FILENAME_TRACE+".txt"); TimeBasedRollingPolicy rollingPolicy2 = new TimeBasedRollingPolicy(); rollingPolicy2.setFileNamePattern(logPathAbsolute + "/" +FILENAME_TRACE+".%d.txt"); //is overridden by setFile() but necessary rollingPolicy2.setMaxHistory(7); rollingPolicy2.setParent(rollingFileAppenderDebug); // parent and context required! rollingPolicy2.setContext(context); rollingPolicy2.start(); SizeBasedTriggeringPolicy sizePolicy2 = new SizeBasedTriggeringPolicy(); sizePolicy2.setMaxFileSize(MAX_FILE_SIZE); rollingFileAppenderDebug.setRollingPolicy(rollingPolicy2); rollingFileAppenderDebug.setTriggeringPolicy(sizePolicy2); PatternLayoutEncoder encoder2 = new PatternLayoutEncoder(); encoder2.setPattern(LOG_PATTERN); encoder2.setContext(context); encoder2.start(); rollingFileAppenderDebug.setEncoder(encoder2); rollingFileAppenderDebug.start(); //LOGCAT PatternLayoutEncoder logCatENcoder = new PatternLayoutEncoder(); logCatENcoder.setContext(context); logCatENcoder.setPattern(LOG_PATTERN); logCatENcoder.start(); LogcatAppender logcatAppender = new LogcatAppender(); logcatAppender.setContext(context); logcatAppender.setEncoder(logCatENcoder); logcatAppender.start(); // add the newly created appenders to the root logger; ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); root.setLevel(Level.TRACE); root.addAppender(rollingFileAppenderDebug); root.addAppender(rollingFileAppenderErrors); root.addAppender(logcatAppender); } } ===== Internationalization ===== The internationalization is made via *.properties files. The *.properties files may be translated to Excelt files, using an open source tool: https://code.google.com/p/i18n-binder/ If you would like to insert some values into the translated strings do that as following: ==locale.properties == Define the places, where the data should be inserted into the strings by inserting **{i}** into the strings. \\ **i** is the number of the parameter you will pass beginning with 0. UserNameMessage={0} users with the name {1} have been found ==code == Insert the data into the String at predefined places: MessageFormat.format(Messages.UserNameMessage, "3", "Steve"); This mehtod is better than adding **%s** into the translations and inserting the data by doing the following, because Runtime-Exceptions will be thrown, if the string does not contains enoughh placeholders **%s** UserNameMessage=%s users with the name %s have been found String.format(Messages.UserNameMessage, "3", "Steve"); ===== Date ===== Details: http://tutorials.jenkov.com/java-date-time/java-util-timezone.html **ACHTUNG:** * Etc/GMT+1 - counts the timezones backwards. It is equal to UTC-1. It is equal to GMT-1. * When Java converts a numer to Date - in interprets the number as UTC and add the local offset to create a local time. \\ so new Date(System.currentTimeMillis()) - is in local time, even if System.currentTimeMillis() is in UTC == Timezones == Java knows TimeZones. TimeZone utc = TimeZone.getTimeZone("UTC"); // TimeZone berlin = TimeZone.getTimeZone("Europe/Berlin"); // TimeZone cassablanca = TimeZone.getTimeZone("Africa/Casablanca"); TimeZone local = TimeZone.getDefault(); == Objects== * The Object **Date** is silly and does not contain * The Object **Timezone** contains the operations about Timzeones * The Object **Calendar** contains the operations on Dates. **GregorianCalendar** is a concreate calendar. TimeZone utc = TimeZone.getTimeZone("UTC"); Date barcodeDateInUTC = new Date(2014,22,05); // assume barcodeDate is in UTC GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTimeZone(utc); gregorianCalendar.setTime(barcodeDateInUTC); == Conversion between TimeZones == TimeZone local = TimeZone.getDefault(); // assume barcodeDate is in UTC GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTimeZone(utc); gregorianCalendar.setTime(barcodeDateInUTC); // ACHTUNG: // offset is given relative to the LOCAL ZONE, not to UTC. // GMT-1 gives an offset of -1 Convert from UTC: utc --1 // GMT+1 gives an offset of 1 Convert from UTC: utc - 1 // "Europe/Berlin" gives an offset of 1. int offset = local.getOffset(0); // calendar is UTC now. Convert to European time. gregorianCalendar.add(Calendar.MILLISECOND, -offset); Date localTime = gregorianCalendar.getTime(); == Format of Date == The Date is conveted from String and back by using **DateFormat**. It should by used, considering the Local formats. E.g. in Europe you display date as 24.12.2014. In USA you display date as 12.24.2014. DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault()); |DateFormat.SHORT | 24.12.06 | 21:54 | |DateFormat.MEDIUM | 24.12.2006 | 21:54:46 | |DateFormat.LONG | 24. Dezember 2006 | 21:54:20 GMT+02:00 | |DateFormat.FULL | Sonntag, 24. Dezember 2006 |21.54 Uhr GMT+02:00| ===== Bit arithmetik ===== Bit arithmetik in Java. Details: http://openbook.galileocomputing.de/javainsel/javainsel_18_001.html#dodtp63255d32-d0b5-4be8-9423-e891b6949017 May be used to pass settings to a method in java, if many settings are allowd in arbitrary combinations, like SWT bits in java /** * * 0 in binary format is 0000 0000 0000 0000 * 1 in binary format is 0000 0000 0000 0001 * -1 in binary format is 1111 1111 1111 1111 * */ static final int first = 1 << 0; // binary 0000 0000 0000 0001 static final int second = 1 << 1; // binary 0000 0000 0000 0010 static final int third = 1 << 2; // binary 0000 0000 0000 0100 static final int four = 1 << 3; // binary 0000 0000 0000 1000 public static void main(String[] args) { System.out.println(isBitSet(first, first)); // true System.out.println(isBitSet(0, first)); // false System.out.println(isBitSet(second, first)); // false System.out.println(isBitSet(second|first, first)); // true System.out.println("--"); int bits = first|second|third; System.out.println(isBitSet(bits, second)); // true bits = unsetBit(bits, second); System.out.println(isBitSet(bits, second)); // false } /** * Checks whether the bits in mask are set inside the bits input * @param bits * @param mask * @return */ public static boolean isBitSet(int bits, int mask){ return (bits & mask) == mask; } /** * Takes the mask, flips the bits in mask * @param bits - where to flip the bits * @param mask - the mask which contains the bits to flip * @return */ public static int unsetBit(int bits, int mask){ int negatedMask = ~mask; return (bits & negatedMask); } ===== Java VM ===== Following parameters are possible C:\java -X -Xmixed mixed mode execution (default) -Xint interpreted mode execution only -Xbootclasspath: set search path for bootstrap classes and resources -Xbootclasspath/a: append to end of bootstrap class path -Xbootclasspath/p: prepend in front of bootstrap class path -Xnoclassgc disable class garbage collection -Xincgc enable incremental garbage collection -Xloggc: log GC status to a file with time stamps -Xbatch disable background compilation -Xms set initial Java heap size -Xmx set maximum Java heap size -Xss set java thread stack size -Xprof output cpu profiling data -Xfuture enable strictest checks, anticipating future default -Xrs reduce use of OS signals by Java/VM (see documentation) -Xcheck:jni perform additional checks for JNI functions -Xshare:off do not attempt to use shared class data -Xshare:auto use shared class data if possible (default) -Xshare:on require using shared class data, otherwise fail. The -X options are non-standard and subject to change without notice. ===== System properties ===== There are infos about the PC environment which may be retrieved from java: System.getProperty("user.dir") Key Description of Associated Value java.version Java Runtime Environment version java.vendor Java Runtime Environment vendor java.vendor.url Java vendor URL java.home Java installation directory java.vm.specification.version Java Virtual Machine specification version java.vm.specification.vendor Java Virtual Machine specification vendor java.vm.specification.name Java Virtual Machine specification name java.vm.version Java Virtual Machine implementation version java.vm.vendor Java Virtual Machine implementation vendor java.vm.name Java Virtual Machine implementation name java.specification.version Java Runtime Environment specification version java.specification.vendor Java Runtime Environment specification vendor java.specification.name Java Runtime Environment specification name java.class.version Java class format version number java.class.path Java class path java.library.path List of paths to search when loading libraries java.io.tmpdir Default temp file path java.compiler Name of JIT compiler to use java.ext.dirs Path of extension directory or directories os.name Operating system name os.arch Operating system architecture os.version Operating system version file.separator File separator ("/" on UNIX) path.separator Path separator (":" on UNIX) line.separator Line separator ("\n" on UNIX) user.name User's account name user.home User's home directory user.dir User's current working directory ===== Reflection ===== * When setting the fields via Reflection boxing is not done automatically. * And you have to use the Field.set() methods to set the wraper types (not Field.setShort(), Field.setInteger()) public static void initAllFieldsWithDefaults(Object modelToInit, Map, Object> defaultValues) { int defaultInt = Integer.valueOf(defaultValues.get(Integer.class).toString()); double defaultDouble = Double.valueOf(defaultValues.get(Double.class).toString()); float defaultFloat = Float.valueOf(defaultValues.get(Float.class).toString()); short defaultShort = Short.valueOf(defaultValues.get(Short.class).toString()); String defaultString = defaultValues.get(String.class).toString(); Date defaultDate = (Date) defaultValues.get(Date.class); for (Field f : getAllNonStaticFieldsInHierarchy(modelToInit.getClass())) { Class type = f.getType(); String name = f.getName(); try { if (type == Integer.class) { f.set(modelToInit, new Integer(defaultInt)); } else if (type == int.class) { f.setInt(modelToInit, defaultInt); } else if (type == Double.class) { f.set(modelToInit, new Double(defaultDouble)); } else if (type == double.class) { f.setDouble(modelToInit, defaultDouble); } else if (type == Float.class) { f.set(modelToInit, new Float(defaultFloat)); } else if (type == float.class) { f.setFloat(modelToInit, defaultFloat); } else if (type == Short.class) { f.set(modelToInit, new Short(defaultShort)); } else if (type == short.class) { f.setShort(modelToInit, defaultShort); } else if (type == String.class) { f.set(modelToInit, defaultString); } else if (type.isInstance(Date.class)) { f.set(modelToInit, defaultDate); } } catch (Exception e) { LOG.error("Failed to initialize model's ({}) field '{}' with type '{}' ", f.getDeclaringClass() .getSimpleName(), name, type); } } } ===== Generics ===== == PeCs - Producer Extends - Consumer super == // OK - can hold any Function private Collection producerExtends1(){ return new ArrayList(); } /* WRONG! - ArrayList is not a legal replacement for Collection. * It is legal to try putting NonUnaryOperator into Collection. * It is NOT legal to put NonUnaryOperator into Collection. * So you can not return Collection here. */ // private Collection producerExtends2(){ // return new ArrayList(); // } private void producerExtends3(Collection collection){ /* Indeed it is not possible to put something into the collection, * since you do not know what is ?, * in the instance of Collection. * May have been anything. UnaryOperator, NonUnaryOperator. * * WRONG! */ // collection.add(new ArrayList()) } /* OK - can put any Function in here, * because you know - collection contains ONLY some superclasses of Function. * So you can put any Function in here. */ private void consumerSuper1(Collection collection){ UnaryOperator u = null; collection.add(u); } private void consumerSuper2(Collection collection){ /* WRONG! * You do not know which superclasses of Function the collection contains. */ // Function func = collection.iterator().next(); } ===== Debugging Tools ===== == VisualVm == VisualVm is able to connect to a Java virtual mashine and to debug it. \\ It is Delivered together with JDK. \\ ..\Java\jdk1.7.0_15\bin\jvisualvm.exe \\ {{http://46zwyrvli634e39iq2l9mv8g.wpengine.netdna-cdn.com/wp-content/uploads/2011/10/Screen-Shot-2011-10-19-at-7.14.47-PM2.png}} == Decompiler == Procyon - a nice decompiler Luyten - a GUI for the decompiler Luyten v0.4.8 / Procyon v0.5.32 https://github.com/deathmarine/Luyten/releases/tag/v0.4.8 {{http://i520.photobucket.com/albums/w327/schajtan/2016-08-13_11-36-52_zpspcjqdmpl.png}} === Remote debugging === To debug Ant you can enable let ant wait for the debugger to attach, then you may attach to the debugger from Eclipse IDE. To make a java application wait for debugger to attach the following JVM params have to be passed to it -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 To attach with the debugger with Eclipse IDE use the Debug COnfiguration and set the Breaking Point, to stop on an uncatched Exception \\ {{http://i520.photobucket.com/albums/w327/schajtan/2015-06-18_13-36-44_zpshnsjyjju.png}} === suspend=y === makes the serer stop and wait for debugger to atach. ===== Install on Ubuntu and switch version ===== sudo apt-get update sudo apt-get install openjdk-8-jdk sudo apt-get install openjdk-11-jdk Then switch the JDK sudo update-alternatives --config java ==== Get File as String ===== private Document getStringFromFile(String aspectJsonFile) throws IOException { Path workDirPath = Path.of(getProjectBasePath()); Path subPath = Path.of("src", "test", "resources", aspectJsonFile); final Path absPath = workDirPath.resolve(subPath); return Files.readString(absPath); } // returns project base path private static String getProjectBasePath() { return new File("").getAbsolutePath(); } ===== JUnit 5 ===== ===== Hamcrest ===== Has matches useful for unit tests. Set the groovy dependencies dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1' // import here testImplementation 'org.hamcrest:hamcrest:2.2' } Now you can import "org.hamcrest" import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import org.junit.jupiter.api.Test; public class MyTest { @Test void testExample() { String value = "Hello, world!"; assertThat(value, containsString("Hello")); assertThat(value, endsWith("!")); assertThat(value, is(notNullValue())); } } ===== Text processing ===== ==== Regular Expressions (java.util.regex) ==== When using Regex - make sure you dont introduce too greedy patterns https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html Boundary matchers ^ The beginning of a line $ The end of a line \b A word boundary \B A non-word boundary \A The beginning of the input \G The end of the previous match \Z The end of the input but for the final terminator, if any \z The end of the input ==== Tokenize strings ==== Break into single words. String[] result = "this is a test".split("\\s"); for (int x=0; x @Test void patternMatch() { mymatch(".*(alice|bob).*", "bob and alice like to text each other" ); // 1 - because greedy match matches the whole string mymatch("\\b(alice|bob)\\b", "bob and alice like to text each other" ); // 2 - ACHTUNG: escape back slashes. \b marks word boundaries } public static long mymatch(String regex, String text) { Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(text); List res = matcher .results() .toList(); System.out.printf("%s matches %s%n", regex, res.size()); return res.size(); } ==== ReplaceAll ==== @Test void stringReplaceAll() { String s = "bob and alice like to text each other"; String john = s.replaceAll("\\b(bob)\\b", "john"); System.out.println(john); } ===== Records ===== First: Java 14 // some interface interface MyBarkInterface{ default void bark(){ System.out.println("bark bark"); } } record MyPoint(int x, int y) implements MyBarkInterface{}; // Cant inherit from Record - its final //record MyPoint2(int x, int y) extends MyPoint{}; @Test void recordTest1() { MyPoint p = new MyPoint(1,2); System.out.println(p); // MyPoint[x=1, y=2] System.out.println(p.x()); // can access vars via methods System.out.println(p.x()); // can access vars via methods p.bark(); // can access hiearchy }