Merge branch 'master' into JAVA-1278-2
This commit is contained in:
commit
f435d18d03
|
@ -15,9 +15,5 @@ This module contains articles about algorithms. Some classes of algorithms, e.g.
|
||||||
- [Maximum Subarray Problem](https://www.baeldung.com/java-maximum-subarray)
|
- [Maximum Subarray Problem](https://www.baeldung.com/java-maximum-subarray)
|
||||||
- [How to Merge Two Sorted Arrays](https://www.baeldung.com/java-merge-sorted-arrays)
|
- [How to Merge Two Sorted Arrays](https://www.baeldung.com/java-merge-sorted-arrays)
|
||||||
- [Median of Stream of Integers using Heap](https://www.baeldung.com/java-stream-integers-median-using-heap)
|
- [Median of Stream of Integers using Heap](https://www.baeldung.com/java-stream-integers-median-using-heap)
|
||||||
- [Kruskal’s Algorithm for Spanning Trees](https://www.baeldung.com/java-spanning-trees-kruskal)
|
- More articles: [[<-- prev]](/../algorithms-miscellaneous-4) [[next -->]](/../algorithms-miscellaneous-6)
|
||||||
- [Balanced Brackets Algorithm in Java](https://www.baeldung.com/java-balanced-brackets-algorithm)
|
|
||||||
- [Efficiently Merge Sorted Java Sequences](https://www.baeldung.com/java-merge-sorted-sequences)
|
|
||||||
- [Introduction to Greedy Algorithms with Java](https://www.baeldung.com/java-greedy-algorithms)
|
|
||||||
- [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher)
|
|
||||||
- More articles: [[<-- prev]](/../algorithms-miscellaneous-4)
|
|
||||||
|
|
|
@ -25,12 +25,6 @@
|
||||||
<artifactId>commons-math3</artifactId>
|
<artifactId>commons-math3</artifactId>
|
||||||
<version>${commons-math3.version}</version>
|
<version>${commons-math3.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>${lombok.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>pl.allegro.finance</groupId>
|
<groupId>pl.allegro.finance</groupId>
|
||||||
<artifactId>tradukisto</artifactId>
|
<artifactId>tradukisto</artifactId>
|
||||||
|
|
|
@ -2,3 +2,9 @@
|
||||||
|
|
||||||
- [Boruvka’s Algorithm for Minimum Spanning Trees](https://www.baeldung.com/java-boruvka-algorithm)
|
- [Boruvka’s Algorithm for Minimum Spanning Trees](https://www.baeldung.com/java-boruvka-algorithm)
|
||||||
- [Gradient Descent in Java](https://www.baeldung.com/java-gradient-descent)
|
- [Gradient Descent in Java](https://www.baeldung.com/java-gradient-descent)
|
||||||
|
- [Kruskal’s Algorithm for Spanning Trees](https://www.baeldung.com/java-spanning-trees-kruskal)
|
||||||
|
- [Balanced Brackets Algorithm in Java](https://www.baeldung.com/java-balanced-brackets-algorithm)
|
||||||
|
- [Efficiently Merge Sorted Java Sequences](https://www.baeldung.com/java-merge-sorted-sequences)
|
||||||
|
- [Introduction to Greedy Algorithms with Java](https://www.baeldung.com/java-greedy-algorithms)
|
||||||
|
- [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher)
|
||||||
|
- More articles: [[<-- prev]](/../algorithms-miscellaneous-5)
|
||||||
|
|
|
@ -18,10 +18,35 @@
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>${guava.version}</version>
|
<version>${guava.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-commons</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${org.assertj.core.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-math3</artifactId>
|
||||||
|
<version>${commons-math3.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<guava.version>28.1-jre</guava.version>
|
<guava.version>28.1-jre</guava.version>
|
||||||
|
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||||
|
<junit.platform.version>1.6.0</junit.platform.version>
|
||||||
|
<commons-math3.version>3.6.1</commons-math3.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package com.baeldung.algorithms.minheapmerge;
|
package com.baeldung.algorithms.minheapmerge;
|
||||||
|
|
||||||
public class HeapNode {
|
public class HeapNode {
|
||||||
|
|
||||||
int element;
|
int element;
|
||||||
int arrayIndex;
|
int arrayIndex;
|
||||||
int nextElementIndex = 1;
|
int nextElementIndex = 1;
|
||||||
|
|
||||||
public HeapNode(int element, int arrayIndex) {
|
public HeapNode(int element, int arrayIndex) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.arrayIndex = arrayIndex;
|
this.arrayIndex = arrayIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,88 +1,88 @@
|
||||||
package com.baeldung.algorithms.minheapmerge;
|
package com.baeldung.algorithms.minheapmerge;
|
||||||
|
|
||||||
public class MinHeap {
|
public class MinHeap {
|
||||||
|
|
||||||
HeapNode[] heapNodes;
|
HeapNode[] heapNodes;
|
||||||
|
|
||||||
public MinHeap(HeapNode heapNodes[]) {
|
public MinHeap(HeapNode heapNodes[]) {
|
||||||
this.heapNodes = heapNodes;
|
this.heapNodes = heapNodes;
|
||||||
heapifyFromLastLeafsParent();
|
heapifyFromLastLeafsParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void heapifyFromLastLeafsParent() {
|
void heapifyFromLastLeafsParent() {
|
||||||
int lastLeafsParentIndex = getParentNodeIndex(heapNodes.length);
|
int lastLeafsParentIndex = getParentNodeIndex(heapNodes.length);
|
||||||
while (lastLeafsParentIndex >= 0) {
|
while (lastLeafsParentIndex >= 0) {
|
||||||
heapify(lastLeafsParentIndex);
|
heapify(lastLeafsParentIndex);
|
||||||
lastLeafsParentIndex--;
|
lastLeafsParentIndex--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void heapify(int index) {
|
void heapify(int index) {
|
||||||
int leftNodeIndex = getLeftNodeIndex(index);
|
int leftNodeIndex = getLeftNodeIndex(index);
|
||||||
int rightNodeIndex = getRightNodeIndex(index);
|
int rightNodeIndex = getRightNodeIndex(index);
|
||||||
int smallestElementIndex = index;
|
int smallestElementIndex = index;
|
||||||
if (leftNodeIndex < heapNodes.length && heapNodes[leftNodeIndex].element < heapNodes[index].element) {
|
if (leftNodeIndex < heapNodes.length && heapNodes[leftNodeIndex].element < heapNodes[index].element) {
|
||||||
smallestElementIndex = leftNodeIndex;
|
smallestElementIndex = leftNodeIndex;
|
||||||
}
|
}
|
||||||
if (rightNodeIndex < heapNodes.length && heapNodes[rightNodeIndex].element < heapNodes[smallestElementIndex].element) {
|
if (rightNodeIndex < heapNodes.length && heapNodes[rightNodeIndex].element < heapNodes[smallestElementIndex].element) {
|
||||||
smallestElementIndex = rightNodeIndex;
|
smallestElementIndex = rightNodeIndex;
|
||||||
}
|
}
|
||||||
if (smallestElementIndex != index) {
|
if (smallestElementIndex != index) {
|
||||||
swap(index, smallestElementIndex);
|
swap(index, smallestElementIndex);
|
||||||
heapify(smallestElementIndex);
|
heapify(smallestElementIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getParentNodeIndex(int index) {
|
int getParentNodeIndex(int index) {
|
||||||
return (index - 1) / 2;
|
return (index - 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getLeftNodeIndex(int index) {
|
int getLeftNodeIndex(int index) {
|
||||||
return (2 * index + 1);
|
return (2 * index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getRightNodeIndex(int index) {
|
int getRightNodeIndex(int index) {
|
||||||
return (2 * index + 2);
|
return (2 * index + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapNode getRootNode() {
|
HeapNode getRootNode() {
|
||||||
return heapNodes[0];
|
return heapNodes[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void heapifyFromRoot() {
|
void heapifyFromRoot() {
|
||||||
heapify(0);
|
heapify(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(int i, int j) {
|
void swap(int i, int j) {
|
||||||
HeapNode temp = heapNodes[i];
|
HeapNode temp = heapNodes[i];
|
||||||
heapNodes[i] = heapNodes[j];
|
heapNodes[i] = heapNodes[j];
|
||||||
heapNodes[j] = temp;
|
heapNodes[j] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int[] merge(int[][] array) {
|
static int[] merge(int[][] array) {
|
||||||
HeapNode[] heapNodes = new HeapNode[array.length];
|
HeapNode[] heapNodes = new HeapNode[array.length];
|
||||||
int resultingArraySize = 0;
|
int resultingArraySize = 0;
|
||||||
|
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
HeapNode node = new HeapNode(array[i][0], i);
|
HeapNode node = new HeapNode(array[i][0], i);
|
||||||
heapNodes[i] = node;
|
heapNodes[i] = node;
|
||||||
resultingArraySize += array[i].length;
|
resultingArraySize += array[i].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
MinHeap minHeap = new MinHeap(heapNodes);
|
MinHeap minHeap = new MinHeap(heapNodes);
|
||||||
int[] resultingArray = new int[resultingArraySize];
|
int[] resultingArray = new int[resultingArraySize];
|
||||||
|
|
||||||
for (int i = 0; i < resultingArraySize; i++) {
|
for (int i = 0; i < resultingArraySize; i++) {
|
||||||
HeapNode root = minHeap.getRootNode();
|
HeapNode root = minHeap.getRootNode();
|
||||||
resultingArray[i] = root.element;
|
resultingArray[i] = root.element;
|
||||||
|
|
||||||
if (root.nextElementIndex < array[root.arrayIndex].length) {
|
if (root.nextElementIndex < array[root.arrayIndex].length) {
|
||||||
root.element = array[root.arrayIndex][root.nextElementIndex++];
|
root.element = array[root.arrayIndex][root.nextElementIndex++];
|
||||||
} else {
|
} else {
|
||||||
root.element = Integer.MAX_VALUE;
|
root.element = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
minHeap.heapifyFromRoot();
|
minHeap.heapifyFromRoot();
|
||||||
}
|
}
|
||||||
return resultingArray;
|
return resultingArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +1,22 @@
|
||||||
package com.baeldung.algorithms.minheapmerge;
|
package com.baeldung.algorithms.minheapmerge;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class MinHeapUnitTest {
|
public class MinHeapUnitTest {
|
||||||
|
|
||||||
private final int[][] inputArray = { { 0, 6 }, { 1, 5, 10, 100 }, { 2, 4, 200, 650 } };
|
private final int[][] inputArray = { { 0, 6 }, { 1, 5, 10, 100 }, { 2, 4, 200, 650 } };
|
||||||
private final int[] expectedArray = { 0, 1, 2, 4, 5, 6, 10, 100, 200, 650 };
|
private final int[] expectedArray = { 0, 1, 2, 4, 5, 6, 10, 100, 200, 650 };
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenSortedArrays_whenMerged_thenShouldReturnASingleSortedarray() {
|
public void givenSortedArrays_whenMerged_thenShouldReturnASingleSortedarray() {
|
||||||
int[] resultArray = MinHeap.merge(inputArray);
|
int[] resultArray = MinHeap.merge(inputArray);
|
||||||
|
|
||||||
assertThat(resultArray.length, is(equalTo(10)));
|
assertThat(resultArray.length, is(equalTo(10)));
|
||||||
assertThat(resultArray, is(equalTo(expectedArray)));
|
assertThat(resultArray, is(equalTo(expectedArray)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-boot-1</artifactId>
|
<artifactId>parent-boot-2</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../parent-boot-1</relativePath>
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package com.baeldung;
|
package com.baeldung;
|
||||||
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.*;
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
|
import org.apache.shiro.authc.IncorrectCredentialsException;
|
||||||
|
import org.apache.shiro.authc.LockedAccountException;
|
||||||
|
import org.apache.shiro.authc.UnknownAccountException;
|
||||||
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
import org.apache.shiro.mgt.DefaultSecurityManager;
|
import org.apache.shiro.mgt.DefaultSecurityManager;
|
||||||
import org.apache.shiro.mgt.SecurityManager;
|
import org.apache.shiro.mgt.SecurityManager;
|
||||||
import org.apache.shiro.realm.Realm;
|
import org.apache.shiro.realm.Realm;
|
||||||
import org.apache.shiro.realm.text.IniRealm;
|
|
||||||
import org.apache.shiro.session.Session;
|
import org.apache.shiro.session.Session;
|
||||||
import org.apache.shiro.subject.Subject;
|
import org.apache.shiro.subject.Subject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
package com.baeldung;
|
package com.baeldung;
|
||||||
|
|
||||||
import org.apache.shiro.authc.*;
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
|
import org.apache.shiro.authc.AuthenticationInfo;
|
||||||
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
|
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||||
|
import org.apache.shiro.authc.UnknownAccountException;
|
||||||
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
import org.apache.shiro.authz.AuthorizationInfo;
|
import org.apache.shiro.authz.AuthorizationInfo;
|
||||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||||
import org.apache.shiro.realm.jdbc.JdbcRealm;
|
import org.apache.shiro.realm.jdbc.JdbcRealm;
|
||||||
import org.apache.shiro.subject.PrincipalCollection;
|
import org.apache.shiro.subject.PrincipalCollection;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class MyCustomRealm extends JdbcRealm {
|
public class MyCustomRealm extends JdbcRealm {
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package com.baeldung.shiro.permissions.custom;
|
package com.baeldung.shiro.permissions.custom;
|
||||||
|
|
||||||
import com.baeldung.MyCustomRealm;
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.*;
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
|
import org.apache.shiro.authc.IncorrectCredentialsException;
|
||||||
|
import org.apache.shiro.authc.LockedAccountException;
|
||||||
|
import org.apache.shiro.authc.UnknownAccountException;
|
||||||
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
import org.apache.shiro.config.Ini;
|
import org.apache.shiro.config.Ini;
|
||||||
import org.apache.shiro.mgt.DefaultSecurityManager;
|
import org.apache.shiro.mgt.DefaultSecurityManager;
|
||||||
import org.apache.shiro.mgt.SecurityManager;
|
import org.apache.shiro.mgt.SecurityManager;
|
||||||
import org.apache.shiro.realm.Realm;
|
|
||||||
import org.apache.shiro.realm.text.IniRealm;
|
import org.apache.shiro.realm.text.IniRealm;
|
||||||
import org.apache.shiro.session.Session;
|
|
||||||
import org.apache.shiro.subject.Subject;
|
import org.apache.shiro.subject.Subject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
## Atomikos
|
## Atomikos
|
||||||
|
|
||||||
This module contains articles about Atomikos
|
This module contains articles about Atomikos
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [Guide Transactions Using Atomikos]()
|
- [A Guide to Atomikos](https://www.baeldung.com/java-atomikos)
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
### Relevant Articles:
|
|
||||||
|
|
||||||
- [Building Java Applications with Bazel](https://www.baeldung.com/bazel-build-tool)
|
|
|
@ -12,4 +12,5 @@ This module contains articles about core Groovy concepts
|
||||||
- [Closures in Groovy](https://www.baeldung.com/groovy-closures)
|
- [Closures in Groovy](https://www.baeldung.com/groovy-closures)
|
||||||
- [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date)
|
- [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date)
|
||||||
- [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io)
|
- [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io)
|
||||||
- [[More -->]](/core-groovy-2)
|
- [Convert String to Integer in Groovy](https://www.baeldung.com/groovy-convert-string-to-integer)
|
||||||
|
- [[More -->]](/core-groovy-2)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java14.helpfulnullpointerexceptions;
|
package com.baeldung.java14.npe;
|
||||||
|
|
||||||
public class HelpfulNullPointerException {
|
public class HelpfulNullPointerException {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java14.helpfulnullpointerexceptions;
|
package com.baeldung.java14.npe;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
|
@ -5,5 +5,5 @@ This module contains articles about sorting arrays in Java
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
|
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
|
||||||
- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array)
|
- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array)
|
||||||
- [How to Reverse an Array in Java](http://www.baeldung.com/java-invert-array)
|
- [How to Reverse an Array in Java](https://www.baeldung.com/java-invert-array)
|
||||||
- [Arrays.sort vs Arrays.parallelSort](https://www.baeldung.com/java-arrays-sort-vs-parallelsort)
|
- [Arrays.sort vs Arrays.parallelSort](https://www.baeldung.com/java-arrays-sort-vs-parallelsort)
|
||||||
|
|
|
@ -5,4 +5,5 @@ This module contains articles about Map data structures in Java.
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap)
|
- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap)
|
||||||
- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
|
- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
|
||||||
|
- [The Map.computeIfAbsent() Method](https://www.baeldung.com/java-map-computeifabsent)
|
||||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)
|
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Using a Mutex Object in Java](https://www.baeldung.com/java-mutex)
|
- [Using a Mutex Object in Java](https://www.baeldung.com/java-mutex)
|
||||||
|
- [Testing Multi-Threaded Code in Java](https://www.baeldung.com/java-testing-multithreaded)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,38 @@
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../../parent-java</relativePath>
|
<relativePath>../../parent-java</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.thread-weaver</groupId>
|
||||||
|
<artifactId>threadweaver</artifactId>
|
||||||
|
<version>0.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.tempus-fugit</groupId>
|
||||||
|
<artifactId>tempus-fugit</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.multithreadedtc</groupId>
|
||||||
|
<artifactId>multithreadedtc</artifactId>
|
||||||
|
<version>1.01</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jcstress</groupId>
|
||||||
|
<artifactId>jcstress-core</artifactId>
|
||||||
|
<version>0.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>core-java-concurrency-2</finalName>
|
<finalName>core-java-concurrency-2</finalName>
|
||||||
|
@ -24,6 +56,51 @@
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<compilerVersion>${javac.target}</compilerVersion>
|
||||||
|
<source>${javac.target}</source>
|
||||||
|
<target>${javac.target}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>main</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<finalName>jcstress</finalName>
|
||||||
|
<transformers>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>org.openjdk.jcstress.Main</mainClass>
|
||||||
|
</transformer>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||||
|
<resource>META-INF/TestList</resource>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<javac.target>1.8</javac.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.baeldung.concurrent;
|
package com.baeldung.concurrent;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import edu.umd.cs.mtc.MultithreadedTestCase;
|
import edu.umd.cs.mtc.MultithreadedTestCase;
|
||||||
|
@ -25,9 +26,10 @@ public class MyCounterMultithreadedTCUnitTest extends MultithreadedTestCase {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void finish() {
|
public void finish() {
|
||||||
assertEquals(2, counter.getCount());
|
assertEquals(2, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void testCounter() throws Throwable {
|
public void testCounter() throws Throwable {
|
||||||
TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000);
|
TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000);
|
|
@ -6,6 +6,7 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class MyCounterSimpleUnitTest {
|
public class MyCounterSimpleUnitTest {
|
||||||
|
@ -18,7 +19,8 @@ public class MyCounterSimpleUnitTest {
|
||||||
assertEquals(500, counter.getCount());
|
assertEquals(500, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
@Ignore
|
||||||
|
@Test
|
||||||
public void testCounterWithConcurrency() throws InterruptedException {
|
public void testCounterWithConcurrency() throws InterruptedException {
|
||||||
int numberOfThreads = 100;
|
int numberOfThreads = 100;
|
||||||
ExecutorService service = Executors.newFixedThreadPool(10);
|
ExecutorService service = Executors.newFixedThreadPool(10);
|
||||||
|
@ -34,7 +36,8 @@ public class MyCounterSimpleUnitTest {
|
||||||
assertEquals(numberOfThreads, counter.getCount());
|
assertEquals(numberOfThreads, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
@Ignore
|
||||||
|
@Test
|
||||||
public void testSummationWithConcurrencyAndWait() throws InterruptedException {
|
public void testSummationWithConcurrencyAndWait() throws InterruptedException {
|
||||||
int numberOfThreads = 2;
|
int numberOfThreads = 2;
|
||||||
ExecutorService service = Executors.newFixedThreadPool(10);
|
ExecutorService service = Executors.newFixedThreadPool(10);
|
|
@ -3,6 +3,7 @@ package com.baeldung.concurrent;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ public class MyCounterTempusFugitUnitTest {
|
||||||
|
|
||||||
private static MyCounter counter = new MyCounter();
|
private static MyCounter counter = new MyCounter();
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
@Concurrent(count = 2)
|
@Concurrent(count = 2)
|
||||||
@Repeating(repetition = 10)
|
@Repeating(repetition = 10)
|
|
@ -2,6 +2,7 @@ package com.baeldung.concurrent;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.google.testing.threadtester.AnnotatedTestRunner;
|
import com.google.testing.threadtester.AnnotatedTestRunner;
|
||||||
|
@ -34,6 +35,7 @@ public class MyCounterThreadWeaverUnitTest {
|
||||||
assertEquals(2, counter.getCount());
|
assertEquals(2, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void testCounter() {
|
public void testCounter() {
|
||||||
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
|
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.baeldung.deadlockAndLivelock;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class DeadlockExample {
|
||||||
|
|
||||||
|
private Lock lock1 = new ReentrantLock(true);
|
||||||
|
private Lock lock2 = new ReentrantLock(true);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DeadlockExample deadlock = new DeadlockExample();
|
||||||
|
new Thread(deadlock::operation1, "T1").start();
|
||||||
|
new Thread(deadlock::operation2, "T2").start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation1() {
|
||||||
|
lock1.lock();
|
||||||
|
print("lock1 acquired, waiting to acquire lock2.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
lock2.lock();
|
||||||
|
print("lock2 acquired");
|
||||||
|
|
||||||
|
print("executing first operation.");
|
||||||
|
|
||||||
|
lock2.unlock();
|
||||||
|
lock1.unlock();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation2() {
|
||||||
|
lock2.lock();
|
||||||
|
print("lock2 acquired, waiting to acquire lock1.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
lock1.lock();
|
||||||
|
print("lock1 acquired");
|
||||||
|
|
||||||
|
print("executing second operation.");
|
||||||
|
|
||||||
|
lock1.unlock();
|
||||||
|
lock2.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String message) {
|
||||||
|
System.out.println("Thread " + Thread.currentThread()
|
||||||
|
.getName() + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sleep(long millis) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.baeldung.deadlockAndLivelock;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class LivelockExample {
|
||||||
|
|
||||||
|
private Lock lock1 = new ReentrantLock(true);
|
||||||
|
private Lock lock2 = new ReentrantLock(true);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
LivelockExample livelock = new LivelockExample();
|
||||||
|
new Thread(livelock::operation1, "T1").start();
|
||||||
|
new Thread(livelock::operation2, "T2").start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation1() {
|
||||||
|
while (true) {
|
||||||
|
tryLock(lock1, 50);
|
||||||
|
print("lock1 acquired, trying to acquire lock2.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
if (tryLock(lock2)) {
|
||||||
|
print("lock2 acquired.");
|
||||||
|
} else {
|
||||||
|
print("cannot acquire lock2, releasing lock1.");
|
||||||
|
lock1.unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("executing first operation.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lock2.unlock();
|
||||||
|
lock1.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation2() {
|
||||||
|
while (true) {
|
||||||
|
tryLock(lock2, 50);
|
||||||
|
print("lock2 acquired, trying to acquire lock1.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
if (tryLock(lock1)) {
|
||||||
|
print("lock1 acquired.");
|
||||||
|
} else {
|
||||||
|
print("cannot acquire lock1, releasing lock2.");
|
||||||
|
lock2.unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("executing second operation.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lock1.unlock();
|
||||||
|
lock2.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String message) {
|
||||||
|
System.out.println("Thread " + Thread.currentThread()
|
||||||
|
.getName() + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sleep(long millis) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryLock(Lock lock, long millis) {
|
||||||
|
try {
|
||||||
|
lock.tryLock(10, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryLock(Lock lock) {
|
||||||
|
return lock.tryLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.baeldung.lockfree;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
public class NonBlockingQueue<T> {
|
||||||
|
|
||||||
|
private final AtomicReference<Node<T>> head, tail;
|
||||||
|
private final AtomicInteger size;
|
||||||
|
|
||||||
|
public NonBlockingQueue() {
|
||||||
|
head = new AtomicReference<>(null);
|
||||||
|
tail = new AtomicReference<>(null);
|
||||||
|
size = new AtomicInteger();
|
||||||
|
size.set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(T element) {
|
||||||
|
if (element == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T> node = new Node<>(element);
|
||||||
|
Node<T> currentTail;
|
||||||
|
do {
|
||||||
|
currentTail = tail.get();
|
||||||
|
node.setPrevious(currentTail);
|
||||||
|
} while(!tail.compareAndSet(currentTail, node));
|
||||||
|
|
||||||
|
if(node.previous != null) {
|
||||||
|
node.previous.next = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
head.compareAndSet(null, node); //if we are inserting the first element
|
||||||
|
size.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T get() {
|
||||||
|
if(head.get() == null) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T> currentHead;
|
||||||
|
Node<T> nextNode;
|
||||||
|
do {
|
||||||
|
currentHead = head.get();
|
||||||
|
nextNode = currentHead.getNext();
|
||||||
|
} while(!head.compareAndSet(currentHead, nextNode));
|
||||||
|
|
||||||
|
size.decrementAndGet();
|
||||||
|
return currentHead.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return this.size.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Node<T> {
|
||||||
|
private final T value;
|
||||||
|
private volatile Node<T> next;
|
||||||
|
private volatile Node<T> previous;
|
||||||
|
|
||||||
|
public Node(T value) {
|
||||||
|
this.value = value;
|
||||||
|
this.next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node<T> getNext() {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrevious(Node<T> previous) {
|
||||||
|
this.previous = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
=========
|
|
||||||
|
|
||||||
## Core Java Concurrency Testing Examples
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
- [Testing Multi-Threaded Code in Java](https://www.baeldung.com/java-testing-multithreaded)
|
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>core-java-concurrency-testing</artifactId>
|
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
|
||||||
<name>core-java-concurrency-testing</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-java</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../../parent-java</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.13</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.googlecode.thread-weaver</groupId>
|
|
||||||
<artifactId>threadweaver</artifactId>
|
|
||||||
<version>0.2</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.tempus-fugit</groupId>
|
|
||||||
<artifactId>tempus-fugit</artifactId>
|
|
||||||
<version>1.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.googlecode.multithreadedtc</groupId>
|
|
||||||
<artifactId>multithreadedtc</artifactId>
|
|
||||||
<version>1.01</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjdk.jcstress</groupId>
|
|
||||||
<artifactId>jcstress-core</artifactId>
|
|
||||||
<version>0.5</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.1</version>
|
|
||||||
<configuration>
|
|
||||||
<compilerVersion>${javac.target}</compilerVersion>
|
|
||||||
<source>${javac.target}</source>
|
|
||||||
<target>${javac.target}</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>main</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<finalName>jcstress</finalName>
|
|
||||||
<transformers>
|
|
||||||
<transformer
|
|
||||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
|
||||||
<mainClass>org.openjdk.jcstress.Main</mainClass>
|
|
||||||
</transformer>
|
|
||||||
<transformer
|
|
||||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
|
||||||
<resource>META-INF/TestList</resource>
|
|
||||||
</transformer>
|
|
||||||
</transformers>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
|
||||||
</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<logger name="org.springframework" level="WARN" />
|
|
||||||
<logger name="org.springframework.transaction" level="WARN" />
|
|
||||||
|
|
||||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
|
||||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
|
||||||
|
|
||||||
<root level="INFO">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
|
@ -1,13 +0,0 @@
|
||||||
*.class
|
|
||||||
|
|
||||||
#folders#
|
|
||||||
/target
|
|
||||||
/neoDb*
|
|
||||||
/data
|
|
||||||
/src/main/webapp/WEB-INF/classes
|
|
||||||
*/META-INF/*
|
|
||||||
|
|
||||||
# Packaged files #
|
|
||||||
*.jar
|
|
||||||
*.war
|
|
||||||
*.ear
|
|
|
@ -29,6 +29,11 @@
|
||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>${commons.lang3.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- test scoped -->
|
<!-- test scoped -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
|
@ -40,6 +45,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<javax.mail.version>1.5.0-b01</javax.mail.version>
|
<javax.mail.version>1.5.0-b01</javax.mail.version>
|
||||||
|
<commons.lang3.version>3.10</commons.lang3.version>
|
||||||
<!-- testing -->
|
<!-- testing -->
|
||||||
<assertj-core.version>3.10.0</assertj-core.version>
|
<assertj-core.version>3.10.0</assertj-core.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Arithmetic {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(Arithmetic.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
int result = 30 / 0; // Trying to divide by zero
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
LOGGER.error("ArithmeticException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ArrayIndexOutOfBounds {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ArrayIndexOutOfBounds.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
int[] nums = new int[] { 1, 2, 3 };
|
||||||
|
|
||||||
|
try {
|
||||||
|
int numFromNegativeIndex = nums[-1]; // Trying to access at negative index
|
||||||
|
int numFromGreaterIndex = nums[4]; // Trying to access at greater index
|
||||||
|
int numFromLengthIndex = nums[3]; // Trying to access at index equal to size of the array
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
LOGGER.error("ArrayIndexOutOfBoundsException caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
class Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dog extends Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Lion extends Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClassCast {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ClassCast.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Animal animalOne = new Dog(); // At runtime the instance is dog
|
||||||
|
Dog bruno = (Dog) animalOne; // Downcasting
|
||||||
|
|
||||||
|
Animal animalTwo = new Lion(); // At runtime the instance is animal
|
||||||
|
Dog tommy = (Dog) animalTwo; // Downcasting
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
LOGGER.error("ClassCastException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class FileNotFound {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(FileNotFound.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(new File("/invalid/file/location")));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
LOGGER.error("FileNotFoundException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Handler globalExceptionHandler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
|
||||||
|
new GlobalExceptionHandler().performArithmeticOperation(10, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int performArithmeticOperation(int num1, int num2) {
|
||||||
|
return num1/num2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Handler implements Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);
|
||||||
|
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
LOGGER.info("Unhandled exception caught!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class IllegalArgument {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(IllegalArgument.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(-1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("IllegalArgumentException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class IllegalState {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(IllegalState.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
List<Integer> intList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
intList.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Integer> intListIterator = intList.iterator(); // Initialized with index at -1
|
||||||
|
|
||||||
|
try {
|
||||||
|
intListIterator.remove(); // IllegalStateException
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
LOGGER.error("IllegalStateException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
class ChildThread extends Thread {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ChildThread.class);
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("InterruptedException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InterruptedExceptionExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
ChildThread childThread = new ChildThread();
|
||||||
|
childThread.start();
|
||||||
|
childThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MalformedURL {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(MalformedURL.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
URL baeldungURL = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
baeldungURL = new URL("malformedurl");
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
LOGGER.error("MalformedURLException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NullPointer {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(NullPointer.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Person personObj = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String name = personObj.personName; // Accessing the field of a null object
|
||||||
|
personObj.personName = "Jon Doe"; // Modifying the field of a null object
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
LOGGER.error("NullPointerException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Person {
|
||||||
|
|
||||||
|
public String personName;
|
||||||
|
|
||||||
|
public String getPersonName() {
|
||||||
|
return personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonName(String personName) {
|
||||||
|
this.personName = personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NumberFormat {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(NumberFormat.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String str1 = "100ABCD";
|
||||||
|
|
||||||
|
try {
|
||||||
|
int x = Integer.parseInt(str1); // Converting string with inappropriate format
|
||||||
|
int y = Integer.valueOf(str1);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
LOGGER.error("NumberFormatException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ParseExceptionExample {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ParseExceptionExample.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
DateFormat format = new SimpleDateFormat("MM, dd, yyyy");
|
||||||
|
|
||||||
|
try {
|
||||||
|
format.parse("01, , 2010");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
LOGGER.error("ParseException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class StringIndexOutOfBounds {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(StringIndexOutOfBounds.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String str = "Hello World";
|
||||||
|
|
||||||
|
try {
|
||||||
|
char charAtNegativeIndex = str.charAt(-1); // Trying to access at negative index
|
||||||
|
char charAtLengthIndex = str.charAt(11); // Trying to access at index equal to size of the string
|
||||||
|
} catch (StringIndexOutOfBoundsException e) {
|
||||||
|
LOGGER.error("StringIndexOutOfBoundsException caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.baeldung.exceptions.rootcausefinder;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Period;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to find root cause exceptions.
|
||||||
|
*/
|
||||||
|
public class RootCauseFinder {
|
||||||
|
|
||||||
|
public static Throwable findCauseUsingPlainJava(Throwable throwable) {
|
||||||
|
Objects.requireNonNull(throwable);
|
||||||
|
Throwable rootCause = throwable;
|
||||||
|
while (rootCause.getCause() != null) {
|
||||||
|
rootCause = rootCause.getCause();
|
||||||
|
}
|
||||||
|
return rootCause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the age of a person from a given date.
|
||||||
|
*/
|
||||||
|
static class AgeCalculator {
|
||||||
|
|
||||||
|
private AgeCalculator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateAge(String birthDate) throws CalculationException {
|
||||||
|
if (birthDate == null || birthDate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Period
|
||||||
|
.between(parseDate(birthDate), LocalDate.now())
|
||||||
|
.getYears();
|
||||||
|
} catch (DateParseException ex) {
|
||||||
|
throw new CalculationException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate parseDate(String birthDateAsString) throws DateParseException {
|
||||||
|
|
||||||
|
LocalDate birthDate;
|
||||||
|
try {
|
||||||
|
birthDate = LocalDate.parse(birthDateAsString);
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
throw new InvalidFormatException(birthDateAsString, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (birthDate.isAfter(LocalDate.now())) {
|
||||||
|
throw new DateOutOfRangeException(birthDateAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CalculationException extends Exception {
|
||||||
|
|
||||||
|
CalculationException(DateParseException ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateParseException extends Exception {
|
||||||
|
|
||||||
|
DateParseException(String input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateParseException(String input, Throwable thr) {
|
||||||
|
super(input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InvalidFormatException extends DateParseException {
|
||||||
|
|
||||||
|
InvalidFormatException(String input, Throwable thr) {
|
||||||
|
super("Invalid date format: " + input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateOutOfRangeException extends DateParseException {
|
||||||
|
|
||||||
|
DateOutOfRangeException(String date) {
|
||||||
|
super("Date out of range: " + date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ch.qos.logback.classic.Level;
|
||||||
|
import ch.qos.logback.classic.Logger;
|
||||||
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
|
import ch.qos.logback.classic.spi.LoggingEvent;
|
||||||
|
import ch.qos.logback.core.Appender;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class GlobalExceptionHandlerUnitTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Appender<ILoggingEvent> mockAppender;
|
||||||
|
|
||||||
|
@Captor
|
||||||
|
private ArgumentCaptor<LoggingEvent> captorLoggingEvent;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
logger.addAppender(mockAppender);
|
||||||
|
|
||||||
|
Handler globalExceptionHandler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void teardown() {
|
||||||
|
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
logger.detachAppender(mockAppender);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenArithmeticException_thenUseUncaughtExceptionHandler() throws InterruptedException {
|
||||||
|
|
||||||
|
Thread globalExceptionHandlerThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
GlobalExceptionHandler globalExceptionHandlerObj = new GlobalExceptionHandler();
|
||||||
|
globalExceptionHandlerObj.performArithmeticOperation(99, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
globalExceptionHandlerThread.start();
|
||||||
|
globalExceptionHandlerThread.join();
|
||||||
|
|
||||||
|
verify(mockAppender).doAppend(captorLoggingEvent.capture());
|
||||||
|
LoggingEvent loggingEvent = captorLoggingEvent.getValue();
|
||||||
|
|
||||||
|
assertThat(loggingEvent.getLevel()).isEqualTo(Level.INFO);
|
||||||
|
assertThat(loggingEvent.getFormattedMessage()).isEqualTo("Unhandled exception caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.baeldung.exceptions.rootcausefinder;
|
||||||
|
|
||||||
|
import com.baeldung.exceptions.rootcausefinder.RootCauseFinder.CalculationException;
|
||||||
|
import com.baeldung.exceptions.rootcausefinder.RootCauseFinder.DateOutOfRangeException;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
import static com.baeldung.exceptions.rootcausefinder.RootCauseFinder.AgeCalculator;
|
||||||
|
import static com.baeldung.exceptions.rootcausefinder.RootCauseFinder.findCauseUsingPlainJava;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the {@link RootCauseFinder}.
|
||||||
|
*/
|
||||||
|
public class RootCauseFinderUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBirthDate_whenCalculatingAge_thenAgeReturned() {
|
||||||
|
try {
|
||||||
|
int age = AgeCalculator.calculateAge("1990-01-01");
|
||||||
|
Assertions.assertEquals(1990, LocalDate
|
||||||
|
.now()
|
||||||
|
.minus(age, ChronoUnit.YEARS)
|
||||||
|
.getYear());
|
||||||
|
} catch (CalculationException e) {
|
||||||
|
Assertions.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongFormatDate_whenFindingRootCauseUsingJava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("010102");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(findCauseUsingPlainJava(ex) instanceof DateTimeParseException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenOutOfRangeDate_whenFindingRootCauseUsingJava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("2020-04-04");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(findCauseUsingPlainJava(ex) instanceof DateOutOfRangeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullDate_whenFindingRootCauseUsingJava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge(null);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
assertTrue(findCauseUsingPlainJava(ex) instanceof IllegalArgumentException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongFormatDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("010102");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateTimeParseException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenOutOfRangeDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("2020-04-04");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateOutOfRangeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongFormatDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("010102");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(Throwables.getRootCause(ex) instanceof DateTimeParseException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenOutOfRangeDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("2020-04-04");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(Throwables.getRootCause(ex) instanceof DateOutOfRangeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Period;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to find root cause exceptions.
|
||||||
|
*/
|
||||||
|
public class RootCauseFinder {
|
||||||
|
|
||||||
|
public static Throwable findCauseUsingPlainJava(Throwable throwable) {
|
||||||
|
Objects.requireNonNull(throwable);
|
||||||
|
Throwable rootCause = throwable;
|
||||||
|
while (rootCause.getCause() != null) {
|
||||||
|
rootCause = rootCause.getCause();
|
||||||
|
}
|
||||||
|
return rootCause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the age of a person from a given date.
|
||||||
|
*/
|
||||||
|
static class AgeCalculator {
|
||||||
|
|
||||||
|
private AgeCalculator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateAge(String birthDate) throws CalculationException {
|
||||||
|
if (birthDate == null || birthDate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Period
|
||||||
|
.between(parseDate(birthDate), LocalDate.now())
|
||||||
|
.getYears();
|
||||||
|
} catch (DateParseException ex) {
|
||||||
|
throw new CalculationException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate parseDate(String birthDateAsString) throws DateParseException {
|
||||||
|
|
||||||
|
LocalDate birthDate;
|
||||||
|
try {
|
||||||
|
birthDate = LocalDate.parse(birthDateAsString);
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
throw new InvalidFormatException(birthDateAsString, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (birthDate.isAfter(LocalDate.now())) {
|
||||||
|
throw new DateOutOfRangeException(birthDateAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CalculationException extends Exception {
|
||||||
|
|
||||||
|
CalculationException(DateParseException ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateParseException extends Exception {
|
||||||
|
|
||||||
|
DateParseException(String input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateParseException(String input, Throwable thr) {
|
||||||
|
super(input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InvalidFormatException extends DateParseException {
|
||||||
|
|
||||||
|
InvalidFormatException(String input, Throwable thr) {
|
||||||
|
super("Invalid date format: " + input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateOutOfRangeException extends DateParseException {
|
||||||
|
|
||||||
|
DateOutOfRangeException(String date) {
|
||||||
|
super("Date out of range: " + date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
target/
|
|
||||||
.idea/
|
|
||||||
bin/
|
|
||||||
*.iml
|
|
|
@ -1,18 +0,0 @@
|
||||||
## Core Java Lang OOP (Part 2)
|
|
||||||
|
|
||||||
This module contains articles about Object-oriented programming (OOP) in Java
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
- [Generic Constructors in Java](https://www.baeldung.com/java-generic-constructors)
|
|
||||||
- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
|
|
||||||
- [Anonymous Classes in Java](https://www.baeldung.com/java-anonymous-classes)
|
|
||||||
- [Raw Types in Java](https://www.baeldung.com/raw-types-java)
|
|
||||||
- [Marker Interfaces in Java](https://www.baeldung.com/java-marker-interfaces)
|
|
||||||
- [Java equals() and hashCode() Contracts](https://www.baeldung.com/java-equals-hashcode-contracts)
|
|
||||||
- [Immutable Objects in Java](https://www.baeldung.com/java-immutable-object)
|
|
||||||
- [Inheritance and Composition (Is-a vs Has-a relationship) in Java](https://www.baeldung.com/java-inheritance-composition)
|
|
||||||
- [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors)
|
|
||||||
- [Static and Default Methods in Interfaces in Java](https://www.baeldung.com/java-static-default-methods)
|
|
||||||
- [Java Copy Constructor](https://www.baeldung.com/java-copy-constructor)
|
|
||||||
- [Abstract Classes in Java](https://www.baeldung.com/java-abstract-class)
|
|
||||||
- [[<-- Prev]](/core-java-modules/core-java-lang-oop)[[More -->]](/core-java-modules/core-java-lang-oop-3)
|
|
|
@ -1,51 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>core-java-lang-oop-2</artifactId>
|
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
|
||||||
<name>core-java-lang-oop-2</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-java</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../../parent-java</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- test scoped -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.assertj</groupId>
|
|
||||||
<artifactId>assertj-core</artifactId>
|
|
||||||
<version>${assertj-core.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>nl.jqno.equalsverifier</groupId>
|
|
||||||
<artifactId>equalsverifier</artifactId>
|
|
||||||
<version>${equalsverifier.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>core-java-lang-oop-2</finalName>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/resources</directory>
|
|
||||||
<filtering>true</filtering>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<!-- testing -->
|
|
||||||
<assertj-core.version>3.10.0</assertj-core.version>
|
|
||||||
<equalsverifier.version>3.0.3</equalsverifier.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,16 +0,0 @@
|
||||||
## Core Java Lang OOP (Part 3)
|
|
||||||
|
|
||||||
This module contains articles about Object-oriented programming (OOP) in Java
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
- [Pass-By-Value as a Parameter Passing Mechanism in Java](https://www.baeldung.com/java-pass-by-value-or-pass-by-reference)
|
|
||||||
- [Access Modifiers in Java](https://www.baeldung.com/java-access-modifiers)
|
|
||||||
- [Guide to the super Java Keyword](https://www.baeldung.com/java-super)
|
|
||||||
- [Guide to the this Java Keyword](https://www.baeldung.com/java-this)
|
|
||||||
- [Java ‘public’ Access Modifier](https://www.baeldung.com/java-public-keyword)
|
|
||||||
- [Composition, Aggregation, and Association in Java](https://www.baeldung.com/java-composition-aggregation-association)
|
|
||||||
- [Nested Classes in Java](https://www.baeldung.com/java-nested-classes)
|
|
||||||
- [A Guide to Inner Interfaces in Java](https://www.baeldung.com/java-inner-interfaces)
|
|
||||||
- [Java Classes and Objects](https://www.baeldung.com/java-classes-objects)
|
|
||||||
- [Java Interfaces](https://www.baeldung.com/java-interfaces)
|
|
||||||
- [[<-- Prev]](/core-java-modules/core-java-lang-oop-2)[[More -->]](/core-java-modules/core-java-lang-oop-4)
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>core-java-lang-oop-3</artifactId>
|
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
|
||||||
<name>core-java-lang-oop-3</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-java</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../../parent-java</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- logging -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
<version>${log4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency> <!-- needed to bridge to slf4j for projects that use the log4j APIs directly -->
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>log4j-over-slf4j</artifactId>
|
|
||||||
<version>${org.slf4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- test scoped -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.assertj</groupId>
|
|
||||||
<artifactId>assertj-core</artifactId>
|
|
||||||
<version>${assertj-core.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.h2database</groupId>
|
|
||||||
<artifactId>h2</artifactId>
|
|
||||||
<version>${h2.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>core-java-lang-oop-3</finalName>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/resources</directory>
|
|
||||||
<filtering>true</filtering>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<assertj-core.version>3.10.0</assertj-core.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,9 +0,0 @@
|
||||||
## Core Java Lang OOP (Part 4)
|
|
||||||
|
|
||||||
This module contains articles about Object-oriented programming (OOP) in Java
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
- [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding)
|
|
||||||
- [Methods in Java](https://www.baeldung.com/java-methods)
|
|
||||||
- [Java ‘private’ Access Modifier](https://www.baeldung.com/java-private-keyword)
|
|
||||||
- [[<-- Prev]](/core-java-modules/core-java-lang-oop-3)
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>core-java-lang-oop-4</artifactId>
|
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
|
||||||
<name>core-java-lang-oop-4</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-java</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../../parent-java</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<!-- logging -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
<version>${log4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency> <!-- needed to bridge to slf4j for projects that use the log4j APIs directly -->
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>log4j-over-slf4j</artifactId>
|
|
||||||
<version>${org.slf4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- test scoped -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.assertj</groupId>
|
|
||||||
<artifactId>assertj-core</artifactId>
|
|
||||||
<version>${assertj-core.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.h2database</groupId>
|
|
||||||
<artifactId>h2</artifactId>
|
|
||||||
<version>${h2.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>core-java-lang-oop-4</finalName>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/resources</directory>
|
|
||||||
<filtering>true</filtering>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<assertj-core.version>3.10.0</assertj-core.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
## Core Java Lang OOP - Constructors
|
||||||
|
|
||||||
|
This module contains article about constructors in Java
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
- [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors)
|
||||||
|
- [Java Copy Constructor](https://www.baeldung.com/java-copy-constructor)
|
||||||
|
- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>core-java-modules</artifactId>
|
||||||
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>core-java-lang-oop-constructors</artifactId>
|
||||||
|
<name>core-java-lang-oop-constructors</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${assertj-core.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<assertj-core.version>3.10.0</assertj-core.version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
|
@ -6,7 +6,7 @@ class BankAccount {
|
||||||
String name;
|
String name;
|
||||||
LocalDateTime opened;
|
LocalDateTime opened;
|
||||||
double balance;
|
double balance;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("%s, %s, %f", this.name, this.opened.toString(), this.balance);
|
return String.format("%s, %s, %f", this.name, this.opened.toString(), this.balance);
|
||||||
|
@ -47,14 +47,13 @@ class BankAccountCopyConstructor extends BankAccount {
|
||||||
this.opened = opened;
|
this.opened = opened;
|
||||||
this.balance = balance;
|
this.balance = balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BankAccountCopyConstructor(BankAccount other) {
|
public BankAccountCopyConstructor(BankAccount other) {
|
||||||
this.name = other.name;
|
this.name = other.name;
|
||||||
this.opened = LocalDateTime.now();
|
this.opened = LocalDateTime.now();
|
||||||
this.balance = 0.0f;
|
this.balance = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BankAccountChainedConstructors extends BankAccount {
|
class BankAccountChainedConstructors extends BankAccount {
|
||||||
public BankAccountChainedConstructors(String name, LocalDateTime opened, double balance) {
|
public BankAccountChainedConstructors(String name, LocalDateTime opened, double balance) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -65,4 +64,4 @@ class BankAccountChainedConstructors extends BankAccount {
|
||||||
public BankAccountChainedConstructors(String name) {
|
public BankAccountChainedConstructors(String name) {
|
||||||
this(name, LocalDateTime.now(), 0.0f);
|
this(name, LocalDateTime.now(), 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,20 +1,19 @@
|
||||||
package com.baeldung.constructors;
|
package com.baeldung.constructors;
|
||||||
|
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
public class ConstructorUnitTest {
|
public class ConstructorUnitTest {
|
||||||
final static Logger LOGGER = Logger.getLogger(ConstructorUnitTest.class.getName());
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenNoExplicitContructor_whenUsed_thenFails() {
|
public void givenNoExplicitContructor_whenUsed_thenFails() {
|
||||||
BankAccount account = new BankAccount();
|
BankAccount account = new BankAccount();
|
||||||
assertThatThrownBy(() -> {
|
Assertions.assertThatThrownBy(() -> {
|
||||||
account.toString();
|
account.toString();
|
||||||
}).isInstanceOf(Exception.class);
|
}).isInstanceOf(Exception.class);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +21,7 @@ public class ConstructorUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenNoArgumentConstructor_whenUsed_thenSucceeds() {
|
public void givenNoArgumentConstructor_whenUsed_thenSucceeds() {
|
||||||
BankAccountEmptyConstructor account = new BankAccountEmptyConstructor();
|
BankAccountEmptyConstructor account = new BankAccountEmptyConstructor();
|
||||||
assertThatCode(() -> {
|
Assertions.assertThatCode(() -> {
|
||||||
account.toString();
|
account.toString();
|
||||||
}).doesNotThrowAnyException();
|
}).doesNotThrowAnyException();
|
||||||
}
|
}
|
||||||
|
@ -33,7 +32,7 @@ public class ConstructorUnitTest {
|
||||||
BankAccountParameterizedConstructor account =
|
BankAccountParameterizedConstructor account =
|
||||||
new BankAccountParameterizedConstructor("Tom", opened, 1000.0f);
|
new BankAccountParameterizedConstructor("Tom", opened, 1000.0f);
|
||||||
|
|
||||||
assertThatCode(() -> {
|
Assertions.assertThatCode(() -> {
|
||||||
account.toString();
|
account.toString();
|
||||||
}).doesNotThrowAnyException();
|
}).doesNotThrowAnyException();
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
## Core Java Lang OOP - Generics
|
||||||
|
|
||||||
|
This module contains articles about generics in Java
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
- [Generic Constructors in Java](https://www.baeldung.com/java-generic-constructors)
|
||||||
|
- [Type Erasure in Java Explained](https://www.baeldung.com/java-type-erasure)
|
||||||
|
- [Raw Types in Java](https://www.baeldung.com/raw-types-java)
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>core-java-modules</artifactId>
|
||||||
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>core-java-lang-oop-generics</artifactId>
|
||||||
|
<name>core-java-lang-oop-generics</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.typeerasure;
|
||||||
|
|
||||||
|
public class Example {
|
||||||
|
|
||||||
|
public static <E> boolean containsElement(E [] elements, E element){
|
||||||
|
for (E e : elements){
|
||||||
|
if(e.equals(element)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue