I am facing a use case where I would like to declare a static finalfield with an initializer statement that is declared to throw a checked exception. Typically, it'd look like this:
public static final ObjectName OBJECT_NAME = new ObjectName("foo:type=bar");
The issue I have here is that the ObjectName constructor may throw various checked exceptions, which I don't care about (because I'd know my name is valid, and it's allright if it miserably crashes in case it's not). The java compiler won't let me just ignore this (as it's a checked exception), and I would prefer not to resort to:
public static final ObjectName OBJECT_NAME;
static {
try {
OBJECT_NAME = new ObjectName("foo:type=bar");
} catch (final Exception ex) {
throw new RuntimeException("Failed to create ObjectName instance in static block.", ex);
}
}
Because static blocks are really, really difficult to read. Does anyone have a suggestion on how to handle this case in a nice, clean way?
If you don't like static blocks (some people don't) then an alternative is to use a static method. IIRC, Josh Bloch recommended this (apparently not in Effective Java on quick inspection).
public static final ObjectName OBJECT_NAME = createObjectName("foo:type=bar");
private static ObjectName createObjectName(final String name) {
try {
return new ObjectName(name);
} catch (final SomeException exc) {
throw new Error(exc);
}
}
Or:
public static final ObjectName OBJECT_NAME = createObjectName();
private static ObjectName createObjectName() {
try {
return new ObjectName("foo:type=bar");
} catch (final SomeException exc) {
throw new Error(exc);
}
}
(Edited: Corrected second example to return from method instead of assign the static.)
Your code is perfectly valid. I don't find it difficult to read. Other ways would only make it more worse. They're only difficult to read for starters, because most of them are not familiar with that. Just follow the standard conventions with regard to ordering of the elements in the code. E.g. do not put static initializers halfway or at the whole bottom of the code and also do not have multiple of them spreading over the class. Just put one at top, after static declarations.
static blocks aren't difficult to read. So I'd recommend that solution.
However, you can wrap your object in another object, for example
ObjectNameWrapper which shares an interface with your ObjectName, and whose constructor calls your ObjectName constructor, hiding all checked exceptions that occur. But again, I'd go for the static option.
You can use a method annotated with Lombok's #SneakyThrows
public static final ObjectName OBJECT_NAME = createObjectName();
#SneakyThrows(SomeException.class)
private static ObjectName createObjectName() {
return new ObjectName("foo:type=bar");
}
This annotation makes a checked exception behaves like an unchecked one.
Related
I have a factory class which constructor takes two parameter. Depending on that parameters the factory creates four different types of classes or throws IllegalArgumentExceptions in case of invalid arguments.
First I need to test if the appropirate class is created depending on the given parameters.
Second I need to verify the correct Exception in case of invalid parameters.
For testing the correct class is build in the factory I can fake the expected class and verify their instantiation.
But I don't know how to deal with #Tested to set up specific parameters in the constructor.
I coudn't find any usable hint neither in the JMockit documentation nor by searching the internet.
Below is a sample factory class and a sample of a class created by the factory (the others are similar).
public class WorkerFactory {
private Worker worker;
public WorkerFactory(final String type, final String subtype) {
if(type == null) throw new IllegalArgumentException("type");
if(subtype == null) throw new IllegalArgumentException("subtype");
if(type.equals("One")) {
if(subtype.equals("A")) worker = new One_A();
else if(subtype.equals("B")) worker = new One_B();
else throw new IllegalArgumentException("subtype");
}
else if(type.equals("Two")) {
if(subtype.equals("A")) worker = new Two_A();
else if(subtype.equals("B")) worker = new Two_B();
else throw new IllegalArgumentException("subtype");
}
else throw new IllegalArgumentException("type");
}
public Worker getWorker() { return worker; }
}
public interface Worker {
public void doWork();
}
public class One_A implements Worker {
public void doWork() {
System.out.println(getClass().getName());
}
}
And a very stupid skeleton for the requiered test BUT without using JMockit.
package application;
import org.junit.Test;
public class WorkerFactoryTest {
WorkerFactory cut;
#Test
public final void testWorkerFactory() {
cut = new WorkerFactory("One", "A");
cut.getWorker().doWork();
cut = new WorkerFactory("One", "B");
cut.getWorker().doWork();
cut = new WorkerFactory("Two", "A");
cut.getWorker().doWork();
cut = new WorkerFactory("Two", "A");
cut.getWorker().doWork();
}
#Test
public final void testWorkerFactoryExceptions() {
try {
cut = new WorkerFactory("Three", "C");
} catch (Exception e) {
e.printStackTrace();
}
try {
cut = new WorkerFactory("One", "C");
} catch (Exception e) {
e.printStackTrace();
}
}
}
``
EDIT (2020.07.02):
The assertThrows(..) from JUnit is one way to verify exceptions. But I use still the old style try/catch variant encapsulated in functions like verifyNoException(errorMessage) with a fail(...) if i caught one or verifyXyzException(expectedExceptionMessage) with a fail(...) if I cought none. This gives me a better control over the exceptions I catch by even a good readability. A time ago i read about some drawbacks about assertThrows over the old fashin style but I can't remeber what they are.
Putting constructor logic in an init(..) method as suggested by JMockit is what I do indeed (the given example did not for simplification). But I still want to test the constructor and not the private initializer method(s). Also I prefere a design where a object gets fully initialized by constructor parameters because I don't like the (boring and ugly) setter calls.
And verifying the parameters passed in is even a good one in my opinion.
The #Tested annotation is useful in 90% of scenarios - empty constructor or constructors where all the args can be passed mocks via #Injectable. That's not the scenario you are in due to you trying to test the permutations through your constructor.
As an aside, JMockit is poking you and saying you might want to reconsider your design. For example, shift that constructor logic to an "init(..)" method (call it whatever) and you'd find things easier to work with, and likely a better overall design. Likewise, constructors-throwing-exceptions is poor design, which the init(..) would get you away from. But I digress...
Your testWorkerFactory(..) is fine as-is. There's no easy way to do permutations of constructor arguments, so what you've got is fine. Brute force is fine. Everything doesn't have to be JMockit, JUnit is still OK.
For testWorkerFactoryExceptions, I'd make use of assertThrows(..) as it is much cleaner and guarantees that you receive the expected throw.
I have a class looks like this
class Some {
private enum Inner {
}
}
And I'm trying to find the Inner class in a initialization block of my test class.
class SomeTest {
private static final Class<?> INNER_CLASS;
{
for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals("Inner")) {
INNER_CLASS = declaredClass;
// Variable `INNER_CLASS` might be assigned in loop
// break? return?
}
}
throw new ExceptionInitializerError("failed to find Inner.class");
}
}
The compiler doesn't like this and I couldn't find any better way.
How can I solve this? Is there any good pattern for this?
static and instance initialization block cannot throw checked exceptions as there is no way to declare that those blocks throws these execeptions. Change ExceptionInitializerError to RuntimeException (or any subclass) and wrap your code in try-catch
Besides here, you are not returning nor breaking thus you always throw exception.
As for "breaking out" well simply yo dont. You have to write that block as it would be body of void method but with the restriction that you cannot use return anywhere.
There are a few problems with your code:
You have the exception name incorrect. The exception you are trying to throw is called ExceptionInInitializerError not ExceptionInitializerError. That is one reason why it won't compile.
Never1 throw Error or subclasses of Error.
If you need to throw an unchecked exception, throw RuntimeException. Or better still, pick something more specific or define and use your own custom (unchecked) exception class.
This should (probably) be a static initializer block, not a plain (instance) initializer. You want this code to be executed once ... not every time a SomeTest instance is created.
Bailing out of a static initializer block is something you want to avoid. It basically leaves you with a dead application ... because the enclosing class and any classes that depend on it become uninitializable.
Having said that, the following might be a more appropriate structure:
static {
BlahType tmp = null;
label: {
for (...) {
if (...) {
tmp = ...;
break label;
}
}
throw new SomeException(...);
}
FINAL_VAR = tmp;
}
Note that we need to do the final assignment to FINAL_VAR in a way that ensures that it is definitely assigned. (My guess is that is a second reason you were getting compilation errors.)
And a more natural way to write the above would be:
static {
BlahType tmp = null;
for (...) {
if (...) {
tmp = ...;
break;
}
}
if (tmp == null) {
throw new SomeException(...);
}
FINAL_VAR = tmp;
}
1 - Maybe a bit too strong. I would say that throwing AssertionError is OK ... assuming that you intend for it never be caught / recovered from. In this case, recovery is moot anyway.
Use intermediate variable before final assignment.
class SomeTest {
private static final Class<?> INNER_CLASS;
static {
Class<?> innerClass = null;
for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals("Inner")) {
innerClass = declaredClass;
}
}
if (innerClass == null) {
throw new ExceptionInitializerError("failed to find Inner.class");
}
INNER_CLASS = innerClass;
}
}
There are couple of issues:
The exception is always thrown
You are assigning to a final variable in a loop
The initialization block is not static and assigning to a static final variable
Check this out:
class SomeTest {
private static final Class<?> INNER_CLASS;
static {
Class<?> foundClass = null;
for (final Class<?> declaredClass : Some.class.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals("Inner")) {
foundClass = declaredClass;
// Variable `INNER_CLASS` might be assigned in loop
// break? return?
}
}
INNER_CLASS = foundClass;
// throw new Exception("failed to find Inner.class");
}
}
I have a singleton class
public class SingletonText {
private static final CompositeText text = new CompositeText(new TextReader("text/text.txt").readFile());
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}}
And TextReader constructor that could throw FileNameEception
public TextReader(String filename) throws FileNameException{
if(!filename.matches("[A-Za-z0-9]*\\.txt"))
throw new FileNameException("Wrong file name!");
file = new File(filename);
}
How can I rethrow it to main and catch it there?
Main class
public class TextRunner {
public static void main(String[] args) {
// write your code here
SingletonText.getInstance().parse();
System.out.println("Parsed text:\n");
SingletonText.getInstance().print();
System.out.println("\n\n(Var8)Task1:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[AEIOUaeiou].*", new FirstLetterComparator());
System.out.println("\n\n(Var9)Task2:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[A-Za-z].*", new LetterColComparator());
System.out.println("\n\n(Var16)Task3:");
String result = SubStringReplace.replace(SingletonText.getInstance()
.searchSentence(".*IfElseDemo.*"), 3, "EPAM");
System.out.println(result);
}}
Static block is executed only when class is loaded for the first time, so you can have something as below which will allow you to re-throw the exception. In you main method, you will surround getInstance() invocation in a try-catch block and then in catch you can do whatever you are looking for.
In case of exception, this exception will be thrown and re-thrown (from you static block) only once, at time of class loading. What #Alexander Pogrebnyak has said is also true.
Looking at the code you have provided, since you are always reading text/text.txt files so below approach will work. In case you are looking to read different files and then re-throwing exception then that becomes all together a different story, and you hadn't asked that part neither the code you have provided shows the same. In any case, if that's what you are looking for then:
you need to create a singleton object of your CompositeText class.
create a setter method will create an object TextReader class using the file name string passed.
that setter method will have the try-catch block, and in the catch block you will re-throw the exception so that you can catch again in main method.
P.S.: since static blocks are executed only once when class is loaded and class is loaded only once per JVM (until you have custom class loaders and overriding the behavior) so this ensures that this singleton is thread-safe.
Code:
public class SingletonText {
private static CompositeText text = null;
static{
try {
text = new CompositeText(new TextReader("text/text.txt").readFile());
} catch (FileNameException e) {
// TODO: re-throw whatever you want
}
}
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}
}
try to lazy initialze the singleton.
something like this:
public class SingletonText {
private static CompositeText text;
public SingletonText() {
}
public static CompositeText getInstance() {
if (text ==null) {
text = new CompositeText(new TextReader("text/text.txt").readFile());
}
return text;
}
}
Also, you need to declare the constructor private, and if it multi-threaded application you need to synchronized the new statement with double check locking. see this in wiki:
https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
Enjoy..
You will get java.lang.ExceptionInInitializerError when your singleton static initializer will fail.
As a cause it will have your FileNameException.
If you don't do anything, default exception handler will print the whole stack trace to standard error.
I never really thought about this before but looking at the following code
public class SomeJavaProgram {
private static String runMe() {
throw new RuntimeException("hi tadsfasdf");
}
private static String name = runMe();
public static void main(String[] args) {
System.out.println("hi there.");
}
}
I never did statics like this in a main before but then I entered scala, and if you have subclasses that start adding defs, exceptions can be thrown before main is even called.
So, in java(not scala), is there a way to catch these exceptions(if I am the superclass and subclasses end up having a static field that throws an exception or static initializer block)....how can I catch all these?
I of course do rely on ONE single definition not throwing which is the
private Logger log = createLoggerFromSomeLoggingLib();
But after that, ideally I would want all exceptions to be logged to the logged file rather than stderr.
That said, I am glad I have always kept the stderr/stdout files along with my logging files now.
Use the static initializer:
private static String name;
static {
try {
name = runMe();
} catch (RuntimeException e) {
// handle
}
}
Oftentimes in my unit tests I have fixtures that are read from resource files and stored into a static attribute on the test class:
public class TestFoo {
private static String fileContents;
#BeforeClass
public static void setup() throws IOException {
fileContents = ... read TestFoo.class.getResourceAsStream("filename") ...
}
}
Which works, but the problem I have is that I generally don't like non-final static data in my tests as it allows for the possibility of one test case to affect the output of another (in the above example if one test reassigned fileContents to something else, then there would be side-effects in other tests that make use of the fixture data).
If I add the final modifier though, then the assignment has to happen at declaration, which is a problem when the initialization is non-trivial (such as in the above example where a checked exception could be triggered by the initialization code). An alternative is to use a static initializer block:
public class TestFoo {
private final static String fileContents;
static {
try {
fileContents = ... read TestFoo.class.getResourceAsStream("filename") ...
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
But I don't particularly like this approach due to the verbosity of having to write a try/catch.
Which approach is more common/idiomatic Java, or is there a better/more typical way to have a static final resource initialized?
I'd use #BeforeClass because it's less verbose. If you fear that someone might accidentally overwrite the value, you could also use #Before. Unless the file is very large, the runtime overhead is probably negligible.