programming:java:java
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| programming:java:java [2023/11/01 07:31] – removed - external edit (Unknown date) 127.0.0.1 | programming:java:java [2023/11/02 14:33] (current) – [Records] skipidar | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ===== 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(){ | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | class B exends A{ | ||
| + | { | ||
| + | int size = 2 | ||
| + | } | ||
| + | public B(){ | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // new B() prints 1, becuase the block is called AFTER the constructor call | ||
| + | </ | ||
| + | ===== Libs ===== | ||
| + | |||
| + | ^Object^ Comparisson^ Details ^ | ||
| + | |[[http:// | ||
| + | |[[https:// | ||
| + | |||
| + | |||
| + | |||
| + | ===== Available JDKs ===== | ||
| + | https:// | ||
| + | |||
| + | ===== install alternative JDK using SDKman ===== | ||
| + | |||
| + | install SDK man | ||
| + | < | ||
| + | # sdkman | ||
| + | curl -fsSL " | ||
| + | </ | ||
| + | |||
| + | Install sdk man in silent mode | ||
| + | < | ||
| + | # sdkman | ||
| + | curl -fsSL " | ||
| + | </ | ||
| + | |||
| + | List and install java | ||
| + | < | ||
| + | sdk list java | ||
| + | </ | ||
| + | |||
| + | <sxh shell> | ||
| + | ================================================================================ | ||
| + | Available Java Versions for Linux 64bit | ||
| + | ================================================================================ | ||
| + | | ||
| + | -------------------------------------------------------------------------------- | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | | 21.3.4.r11 | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | ================================================================================ | ||
| + | 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 " | ||
| + | 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:// | ||
| + | |||
| + | < | ||
| + | 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 / | ||
| + | |||
| + | Selection | ||
| + | ------------------------------------------------------------ | ||
| + | 0 / | ||
| + | * 1 / | ||
| + | 2 / | ||
| + | 3 / | ||
| + | |||
| + | </ | ||
| + | |||
| + | ===== JDK Tools ===== | ||
| + | Java consists of many tools | ||
| + | Here is a full list: http:// | ||
| + | |||
| + | 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**, | ||
| + | * **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:// | ||
| + | |||
| + | In Java8 the memory model was redesigned (PermGen was eliminated) | ||
| + | |||
| + | {{http:// | ||
| + | {{http:// | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== JavaDoc ===== | ||
| + | JavaDoc can contain Pictures | ||
| + | <sxh java> | ||
| + | /** Sorts labels according to {@link # | ||
| + | * <img alt="" | ||
| + | */ | ||
| + | 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, | ||
| + | |||
| + | Details are here: http:// | ||
| + | |||
| + | <sxh java> | ||
| + | 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, | ||
| + | | ||
| + | | ||
| + | @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 " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <sxh java> | ||
| + | @Unfinished( Proority = HIGH, value=2, createdBy=" | ||
| + | class MyClass{ | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | ===== POJO, JavaBean, DTO, ValueObject ===== | ||
| + | Here are some details about the differences: | ||
| + | |||
| + | Java provides some API to work with JavaBean getter / setter | ||
| + | |||
| + | <sxh java> | ||
| + | BeanInfo info = Introspector.getBeanInfo(domainObjectType); | ||
| + | PropertyDescriptor[] props = info.getPropertyDescriptors(); | ||
| + | |||
| + | for (PropertyDescriptor pd : props) { | ||
| + | | ||
| + | | ||
| + | } | ||
| + | </ | ||
| + | ===== 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, | ||
| + | The implementation of MyObject.equals() is never called. | ||
| + | |||
| + | In **ArrayList< | ||
| + | it copares the elements in collections, | ||
| + | |||
| + | |||
| + | ==== Multithreading ==== | ||
| + | |||
| + | ==Threadlocal variables == | ||
| + | It may happen, that every thread should have an own variable. | ||
| + | <sxh java> | ||
| + | private static final 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:// | ||
| + | |||
| + | |||
| + | ===== 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:// | ||
| + | |||
| + | 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/ | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | </ | ||
| + | |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. | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | <sxh java> | ||
| + | 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 = "/ | ||
| + | final static String MAX_FILE_SIZE = " | ||
| + | final static String LOG_PATTERN = " | ||
| + | final static String FILENAME_ERRORS = " | ||
| + | final static String FILENAME_TRACE = " | ||
| + | |||
| + | 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.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 + "/" | ||
| + | |||
| + | TimeBasedRollingPolicy< | ||
| + | rollingPolicy1.setFileNamePattern(logPathAbsolute + "/" | ||
| + | rollingPolicy1.setMaxHistory(7); | ||
| + | rollingPolicy1.setParent(rollingFileAppenderErrors); | ||
| + | rollingPolicy1.setContext(context); | ||
| + | rollingPolicy1.start(); | ||
| + | rollingFileAppenderErrors.setRollingPolicy(rollingPolicy1); | ||
| + | | ||
| + | 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.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 + "/" | ||
| + | |||
| + | TimeBasedRollingPolicy< | ||
| + | rollingPolicy2.setFileNamePattern(logPathAbsolute + "/" | ||
| + | rollingPolicy2.setMaxHistory(7); | ||
| + | rollingPolicy2.setParent(rollingFileAppenderDebug); | ||
| + | rollingPolicy2.setContext(context); | ||
| + | rollingPolicy2.start(); | ||
| + | |||
| + | | ||
| + | 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:// | ||
| + | |||
| + | |||
| + | |||
| + | 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, | ||
| + | </ | ||
| + | |||
| + | |||
| + | 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, | ||
| + | </ | ||
| + | ===== Date ===== | ||
| + | Details: http:// | ||
| + | |||
| + | **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. | ||
| + | |||
| + | <sxh java> | ||
| + | | ||
| + | // TimeZone berlin = TimeZone.getTimeZone(" | ||
| + | // TimeZone cassablanca = TimeZone.getTimeZone(" | ||
| + | | ||
| + | </ | ||
| + | |||
| + | |||
| + | == 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. | ||
| + | |||
| + | <sxh java> | ||
| + | | ||
| + | Date barcodeDateInUTC = new Date(2014, | ||
| + | |||
| + | // assume barcodeDate is in UTC | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | |||
| + | == Conversion between TimeZones == | ||
| + | <sxh java> | ||
| + | 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 | ||
| + | // " | ||
| + | int offset = local.getOffset(0); | ||
| + | |||
| + | // calendar is UTC now. Convert to European time. | ||
| + | gregorianCalendar.add(Calendar.MILLISECOND, | ||
| + | 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. | ||
| + | <sxh java> | ||
| + | DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG, | ||
| + | </ | ||
| + | |||
| + | |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:// | ||
| + | |||
| + | May be used to pass settings to a method in java, if many settings are allowd in arbitrary combinations, | ||
| + | |||
| + | <sxh 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, | ||
| + | System.out.println(isBitSet(0, | ||
| + | System.out.println(isBitSet(second, | ||
| + | System.out.println(isBitSet(second|first, | ||
| + | |||
| + | System.out.println(" | ||
| + | |||
| + | int bits = first|second|third; | ||
| + | System.out.println(isBitSet(bits, | ||
| + | bits = unsetBit(bits, | ||
| + | System.out.println(isBitSet(bits, | ||
| + | |||
| + | |||
| + | } | ||
| + | |||
| + | /** | ||
| + | * 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 | ||
| + | -Xint | ||
| + | -Xbootclasspath:< | ||
| + | set search path for bootstrap classes and resources | ||
| + | -Xbootclasspath/ | ||
| + | append to end of bootstrap class path | ||
| + | -Xbootclasspath/ | ||
| + | prepend in front of bootstrap class path | ||
| + | -Xnoclassgc | ||
| + | -Xincgc | ||
| + | -Xloggc:< | ||
| + | -Xbatch | ||
| + | -Xms< | ||
| + | -Xmx< | ||
| + | -Xss< | ||
| + | -Xprof | ||
| + | -Xfuture | ||
| + | -Xrs reduce use of OS signals by Java/VM (see documentation) | ||
| + | -Xcheck: | ||
| + | -Xshare: | ||
| + | -Xshare: | ||
| + | -Xshare: | ||
| + | |||
| + | 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(" | ||
| + | |||
| + | 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 ("/" | ||
| + | path.separator Path separator (":" | ||
| + | line.separator Line separator (" | ||
| + | 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(), | ||
| + | |||
| + | <sxh java> | ||
| + | | ||
| + | |||
| + | 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<?> | ||
| + | String name = f.getName(); | ||
| + | try { | ||
| + | if (type == Integer.class) { | ||
| + | f.set(modelToInit, | ||
| + | |||
| + | } else if (type == int.class) { | ||
| + | f.setInt(modelToInit, | ||
| + | |||
| + | } else if (type == Double.class) { | ||
| + | f.set(modelToInit, | ||
| + | |||
| + | } else if (type == double.class) { | ||
| + | f.setDouble(modelToInit, | ||
| + | |||
| + | } else if (type == Float.class) { | ||
| + | f.set(modelToInit, | ||
| + | |||
| + | } else if (type == float.class) { | ||
| + | f.setFloat(modelToInit, | ||
| + | |||
| + | } else if (type == Short.class) { | ||
| + | f.set(modelToInit, | ||
| + | |||
| + | } else if (type == short.class) { | ||
| + | f.setShort(modelToInit, | ||
| + | |||
| + | } else if (type == String.class) { | ||
| + | f.set(modelToInit, | ||
| + | |||
| + | } else if (type.isInstance(Date.class)) { | ||
| + | f.set(modelToInit, | ||
| + | } | ||
| + | } catch (Exception e) { | ||
| + | LOG.error(" | ||
| + | .getSimpleName(), | ||
| + | } | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ===== Generics ===== | ||
| + | |||
| + | == PeCs - Producer Extends - Consumer super == | ||
| + | |||
| + | <sxh java> | ||
| + | |||
| + | // OK - can hold any Function | ||
| + | private Collection<? | ||
| + | return new ArrayList< | ||
| + | } | ||
| + | |||
| + | /* WRONG! - ArrayList< | ||
| + | * It is legal to try putting NonUnaryOperator into Collection< | ||
| + | * It is NOT legal to put NonUnaryOperator | ||
| + | * So you can not return Collection< | ||
| + | */ | ||
| + | // private Collection< | ||
| + | // return new ArrayList< | ||
| + | // } | ||
| + | |||
| + | |||
| + | private void producerExtends3(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, | ||
| + | * | ||
| + | * WRONG! | ||
| + | */ | ||
| + | // | ||
| + | } | ||
| + | |||
| + | /* 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<? | ||
| + | UnaryOperator u = null; | ||
| + | collection.add(u); | ||
| + | } | ||
| + | |||
| + | private void consumerSuper2(Collection<? | ||
| + | /* WRONG! | ||
| + | * You do not know which superclasses of Function the collection contains. | ||
| + | */ | ||
| + | // | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== 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:// | ||
| + | |||
| + | |||
| + | == Decompiler == | ||
| + | Procyon - a nice decompiler | ||
| + | Luyten - a GUI for the decompiler | ||
| + | |||
| + | Luyten v0.4.8 / Procyon v0.5.32 | ||
| + | |||
| + | https:// | ||
| + | |||
| + | {{http:// | ||
| + | |||
| + | |||
| + | === 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: | ||
| + | </ | ||
| + | |||
| + | |||
| + | To attach with the debugger with Eclipse IDE use the Debug COnfiguration and set the Breaking Point, to stop on an uncatched Exception \\ | ||
| + | {{http:// | ||
| + | |||
| + | === 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 ===== | ||
| + | |||
| + | <sxh java> | ||
| + | private Document getStringFromFile(String aspectJsonFile) throws IOException { | ||
| + | Path workDirPath = Path.of(getProjectBasePath()); | ||
| + | Path subPath = Path.of(" | ||
| + | final Path absPath = workDirPath.resolve(subPath); | ||
| + | |||
| + | return Files.readString(absPath); | ||
| + | |||
| + | } | ||
| + | |||
| + | // returns project base path | ||
| + | private static String getProjectBasePath() { | ||
| + | return new File("" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ===== JUnit 5 ===== | ||
| + | |||
| + | <sxh groovy> | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Hamcrest ===== | ||
| + | |||
| + | Has matches useful for unit tests. | ||
| + | |||
| + | Set the groovy dependencies | ||
| + | <sxh groovy> | ||
| + | dependencies { | ||
| + | testImplementation ' | ||
| + | testImplementation ' | ||
| + | |||
| + | // import here | ||
| + | testImplementation ' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Now you can import " | ||
| + | |||
| + | <sxh java> | ||
| + | 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 = " | ||
| + | | ||
| + | assertThat(value, | ||
| + | assertThat(value, | ||
| + | assertThat(value, | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Text processing ===== | ||
| + | |||
| + | ==== Regular Expressions (java.util.regex) ==== | ||
| + | |||
| + | When using Regex - make sure you dont introduce too greedy patterns | ||
| + | |||
| + | https:// | ||
| + | < | ||
| + | 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. | ||
| + | |||
| + | <sxh java> | ||
| + | |||
| + | String[] result = "this is a test" | ||
| + | for (int x=0; x< | ||
| + | System.out.println(result[x]); | ||
| + | |||
| + | /* this | ||
| + | is | ||
| + | a | ||
| + | test | ||
| + | */ | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | <sxh java> | ||
| + | @Test | ||
| + | void patternMatch() { | ||
| + | mymatch(" | ||
| + | mymatch(" | ||
| + | } | ||
| + | |||
| + | public static long mymatch(String regex, String text) { | ||
| + | Pattern pattern = Pattern.compile(regex); | ||
| + | Matcher matcher = pattern.matcher(text); | ||
| + | |||
| + | List< | ||
| + | .results() | ||
| + | .toList(); | ||
| + | |||
| + | System.out.printf(" | ||
| + | return res.size(); | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== ReplaceAll | ||
| + | |||
| + | <sxh java> | ||
| + | @Test | ||
| + | void stringReplaceAll() { | ||
| + | String s = "bob and alice like to text each other"; | ||
| + | String john = s.replaceAll(" | ||
| + | System.out.println(john); | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Records ===== | ||
| + | First: Java 14 | ||
| + | |||
| + | |||
| + | |||
| + | <sxh java> | ||
| + | // some interface | ||
| + | interface MyBarkInterface{ | ||
| + | default void bark(){ | ||
| + | System.out.println(" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | 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, | ||
| + | |||
| + | System.out.println(p); | ||
| + | System.out.println(p.x()); | ||
| + | System.out.println(p.x()); | ||
| + | | ||
| + | p.bark(); // can access hiearchy | ||
| + | } | ||
| + | |||
| + | </ | ||
