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 | ||
+ | } | ||
+ | |||
+ | </ |