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'm very new to Java so it makes it hard for me to explain what I'm trying to do.
I have an abstract class that invokes several object constants like this:
public abstract class Enchantment implements Keyed {
/**
* Provides protection against environmental damage
*/
public static final Enchantment PROTECTION_ENVIRONMENTAL = new EnchantmentWrapper("protection");
In a different file I can access this perfectly fine with Enchantment value = Enchantment.PROTECTION_ENVIRONMENTAL;
However, I'm trying to use a string variable for this instead. Something like this:
String str = "PROTECTION_ENVIRONMENTAL";
Enchantment value = Enchantment.str;
Obviously that won't work. So I did a bunch of research and learned I need to use reflection for this. Using this source code's docs I figured I was looking for field data. So I tried both:
Field fld = Enchantment.class.getField("PROTECTION_ENVIRONMENTAL");
Field fld = Enchantment.class.getDeclaredField("PROTECTION_ENVIRONMENTAL");
But these returned me a NoSuchFieldException. As I was on it, I've tried both getMethod() and getDeclaredMethod() just as well equally with no luck.
I'm now at the point that these are probably "object constants"? I'm not sure how to call them. But I'm definitely at a loss on how to get this to work now and after everything I've tried myself, I figured it was time to ask for some help here.
That one comment is spot on: you absolutely do not use reflection here.
There are only two valid reasons to use reflection:
you are creating a framework that has to deal with classes it doesn't know about
you have for some other reason to deal with classes you don't know about at compile time
But your code perfectly knows about that Enchantment class, its capabilities, and so on. Therefore reflection is the wrong approach. You figured it yourself: it is damn hard to get right, and damn right to get it wrong in some subtle ways. And when you get it wrong, it always blows up at runtime. Reflection code compiling means nothing. It always waits for you to run it to throw up in your face.
So to answer your question by not answering it: use a Map. Like:
Map<String, Enchantment> enchantmentsByConstantName = new HashMap<>();
enchantmentsByConstantName.put("PROTECTION_ENVIRONMENTAL", PROTECTION_ENVIRONMENTAL);
Alternatively, these constants could go into an enum, as outlined in the other answer, but in a sightly different way:
enum EnchantmentHolder {
PROTECTION_ENVIRONMENTAL(new EnchantmentWrapper("protection")),
ANOTHER_ENCHANTMENT(...)
A_THIRD_ENCHANTMENT(...)
...;
private Enchantment enchantment;
private EnchantmentHolder(Enchantment enchantment) {
this.entchantment = entchantment;
}
public Enchantment getEntchantment() { return entchantment; }
You may want to look into enumerations if you know they're going to be constant values;
public enum Enchantment {
PROTECTION_ENVIRONMENTAL {
public void cast() {
// do enum-specific stuff here
}
},
ANOTHER_ENCHANTMENT {
public void cast() {
// do enum-specific stuff here
}
},
A_THIRD_ENCHANTMENT{
public void cast() {
// do enum-specific stuff here
}
};
public abstract void cast();
}
enums can be treated like classes and have methods and properties. You can also convert to and from strings Enchantment.valueOf("PROTECTION_ENVIRONMENTAL") but that's generally if you are reading from a configuration file - in code you'd reference the value directly.
Once you have the Field, you need to call Field.get(Object) with an instance (in this case the class). Something like,
Class<?> cls = Enchantment.class;
try {
Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
System.out.println(f.get(cls));
} catch (Exception e) {
e.printStackTrace();
}
Since you want the Enchantment, you could then test that the instance you get is assignable to Enchantment. Something like,
Class<? extends Enchantment> cls = Enchantment.class;
try {
Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
Object obj = f.get(cls);
if (cls.isAssignableFrom(obj.getClass())) {
Enchantment e = cls.cast(obj);
System.out.println(e);
}
} catch (Exception e) {
e.printStackTrace();
}
But the enum approach is better.
This question already has answers here:
Can we call a static method with a null object in Java? If so, how?
(4 answers)
Closed 4 years ago.
I have the following class, which is used for controlling some debugging and beta testing options in various places in my Android app. It just contains some flags and some logic to (de)serialize it to/from JSON.
public class DevConfiguration {
public boolean dontSendSMS;
public static String toJsonString(DevConfiguration devConfiguration) {
JSONObject json = new JSONObject();
if( devConfiguration != null ) {
try {
json.put("dontSendSMS", devConfiguration.dontSendSMS);
} catch (JSONException e) {
e.printStackTrace();
}
}
return json.toString();
}
public static DevConfiguration fromJsonString(String jsonString) {
if( jsonString.isEmpty() )
return null;
DevConfiguration result = new DevConfiguration();
try {
JSONObject jsonObj = new JSONObject(jsonString);
result.dontSendSMS = jsonObj.optBoolean("dontSendSMS", false);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Now, in one of my services I receive a serialized DevConfiguration object in an Intent, and might later pass it on to another service:
serviceIntent.putExtra("dev_conf", DevConfiguration.toJsonString(mDevConfiguration));
I choose to make the toJsonString() method static, so that I don't risk invoking it on a null instance. However, it's still possible to make a mistake somewhere and invoking the static method on an instance - potentially a null instance!
mDevConfiguration.toJsonString(mDevConfiguration);
There is a Lint warning in Android Studio, but still it's a potential NullPointerException bug waiting to happen. I thought it might be possible to hide it by defining a similar private method but with a different signature
/** Hide instance implementation **/
private String toJsonString(Object o){ return ""; }
but of course calling it with a DevConfiguration parameter will invoke the static method anyway, and the IDE doesn't give any more warnings than before either.
Is there any way to "hide" the static method from instance variables?
EDIT
Comments make it clear that invoking a static method on a null instance is perfectly legal. However, the question is not "How do I prevent a NullPointerException when invoking a static method on a null instance?", but the more general "How can I prevent invoking a static method on an instance of my class?".
In other words - is there any way to prevent the compiler from compiling if one accidentally tries to invoke a static method on an instance?
Calling a static method on a variable with null value will not raise NullPointerException. Following code will print 42 even though variable i is null.
public class Test {
public static void main(String... args) {
Integer i = null;
System.out.println(i.parseInt("42"));
}
}
When calling static methods by variable, what really matters is the declared type of the variable and not the referenced type of its value. This is related to the fact that static methods in java are not polymorphic.
„How can I prevent invoking a static method on an instance of my class?"
Calling static methods by variable is just a regular language feature defined in the Java spec. I’d be surprised if there were any method to suppress it in general.
If I had to do it for a selected class, I would probably migrate static methods to a separate „companion” utility (as described in another answer).
But having such static (factory) methods in your class is a perfectly fine idiom (see for example: Joshua Bloch, „Effective Java”, Item 1: Consider static factory methods instead of constructors). I wouldn’t easily give up on it.
I see a few ways you could do this:
Use a Utils class:
public class Utils {
public static String toJsonString(DevConfiguration devConfiguration) {
JSONObject json = new JSONObject();
if( devConfiguration != null ) {
try {
json.put("dontSendSMS", devConfiguration.dontSendSMS);
} catch (JSONException e) {
e.printStackTrace();
}
}
return json.toString();
}
public static DevConfiguration fromJsonString(String jsonString) {
if( jsonString.isEmpty() )
return null;
DevConfiguration result = new DevConfiguration();
try {
JSONObject jsonObj = new JSONObject(jsonString);
result.dontSendSMS = jsonObj.optBoolean("dontSendSMS", false);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Now you can just makes calls to Utils.method() and avoid confusion.
Use Kotlin
Kotlin actually makes it really hard (if not impossible) to call a static method on a dynamic receiver. It won't show in the method suggestions, and will underline in red if you type it manually. It might not even compile, although I haven't gotten that far.
Kotlin also has built-in null protection: instance?.method(). The ? means method() just won't execute if instance is null.
Just don't call a static method on a dynamic receiver. If you do it by accident, go back and fix it. You shouldn't be relying on Java to work around your syntax errors for you.
Finally, why even do this? I highly doubt mDevConfiguration is ever null, unless you initialize it in a really weird spot. If it is, you may want to look at reorganizing your code. Because, again, you shouldn't be relying on Java to work around your syntax errors for you. Also, if it is null, it won't throw an NPE, at least in Java, since it doesn't need a dynamic receiver to run (this is probably different in Kotlin).
It's up to you to make code that works as it should, and implement the proper null checks, error handling, etc. If you miss something, it's no big deal; that's why you test your code and fix the crashes and bugs you catch before you release it. Anything you don't catch will be reported by the Google Play Console (if you publish there) or Firebase (if you implement that) or your users.
Sorry if the above sounds harsh, but I'm really having trouble seeing why you'd want to do this instead of just checking your code.
If you really want to keep this structure, at least make the constructor for DevConfiguration private:
public class DevConfiguration {
//...
private DevConfiguration() {}
//...
}
That way, only the static methods inside it can create an instance.
Let's say we have such a simple parser:
public class ResourceManager {
private final static Logger LOG = Logger.getLogger(ResourceManager.class);
public Museum parseJSONFile(String filePath) /*throws IOException ???? */ {
Museum museum = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
museum = objectMapper.readValue(new File(filePath), Museum.class);
} catch(IOException e) {
LOG.error(e);
}
return museum;
}
}
Should the exception be caught in method or in the calling code? Which variant is better?
Parser can't do anything with exception, so that's an exceptional situation for a parser and it can't produce any expectable result. Someone from the outside should handle it.
In particular, it should not return null as it will result in bunch of null-checks in calling code (which you can easily forget to put, or due to the lack of documentation on your implementation I just don't know whether I have to check for null without seeing the code). This is one of the problems that exceptions in Java were intended to solve. By declaring checked-exception in method signature, you're enforcing users of your parser to deal with fact that value might not come.
I m having a problem of calling a constructor with arguments from default constructor.
Class A {
private static Properties properties;
A(Properties property){
// do some checks
try{
load(property, fileName)
} catch(IOException e) {
throw new RuntimeException();
}
}
A(){
this(load(properties));
}
private static Properties load(Properties properties, String fileName ) throws IOException {
try {
properties.load(A.class.getClassLoader()
.getResourceAsStream(fileName));
} catch (IOException ioException) {
throw new IOException("Unable to process the properties File. " + fileName, ioException);
}
return properties;
}
}
My problem is: In Default constructor I wanted to use try/catch block and do the same operation of throwing a run time exception. Can you help me out as what can be done in this?
WRT this post: chaining constructors in Java without throwing exceptions from the default constructor
I have an option of putting try/catch inside another method. But is there any other way?
P.S: I do not want to use 'throws'
Java does not allow chained constructor calls to be enclosed within a try block, since such constructs could if not restricted allow an object whose base object threw an exception to end up being returned to calling code. This makes it difficult to express certain concepts involving resources like files [e.g. it would be helpful to have a constructor open a file before chaining to the parent and close it afterward, but there's no way to safely have a constructor take responsibility for a file which is opened before chaining to the parent]. The best one can do in Java is avoid public constructors which might throw exceptions and instead use factory methods which can be better equipped to handle them.
Option 1: Pass the other constructor a new empty instance of Properties:
class A
{
public A()
{
this(new Properties());
}
// rest of code...
}
Option 2: Pass the other constructor a null instance of Properties. You'll then have to guard against null in load(...), but you probably should be anyway:
class A
{
public A()
{
this(null);
}
// rest of code...
}
Option 3: Pass the other constructor a default instance of Properties:
class A
{
private static final Properties defaultProperties;
static
{
defaultProperties = new Properties();
// populate here however you wish
}
public A()
{
this(defaultProperties);
}
// rest of code...
}
My objective is to have a private static Properties object in my class, to act as defaults when creating other Properties objects needed by my application. The current implementation looks like this:
public class MyClass {
private static Properties DEFAULT_PROPERTIES = new Properties();
static {
try {
DEFAULT_PROPERTIES.load(
MyClass.class.getResourceAsStream("myclass.properties"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Looking at it, it works, but it doesn't feel right.
How would you do it?
There are basically two ways. First way is using the static block as you have shown (but then with an ExceptionInInitializerError instead of the RuntimeException). Second way is using a static method which you call immediately on declaration:
private static Properties DEFAULT_PROPERTIES = getDefaultProperties();
private static Properties getDefaultProperties() {
Properties properties = new Properties();
try {
properties.load(MyClass.class.getResourceAsStream("myclass.properties"));
} catch (IOException e) {
throw new ConfigurationException("Cannot load properties file", e);
}
return properties;
}
The ConfigurationException can just be your custom class extending RuntimeException.
I personally prefer the static block because it doesn't make sense having a method which is executed only once ever in its life. But if you refactor the method so that it takes a filename and can be reused globally, then that would be more preferred.
private static Properties DEFAULT_PROPERTIES = SomeUtil.getProperties("myclass.properties");
// Put this in a SomeUtil class.
public static Properties getProperties(String filename) {
Properties properties = new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(filename));
} catch (IOException e) {
throw new ConfigurationException("Cannot load " + filename, e);
}
return properties;
}
Instead of a generic RuntimeException, I would throw an ExceptionInInitializerError, which is ment for exacctly this purpose. From the API documentation: "Signals that an unexpected exception has occurred in a static initializer."
Seems acceptable to me; load in the static initialiser, it gets called only when the class is referenced, and is only called once. I like it. The only thing I'd do is make it final.
Well, aside from the exception. I'd try and avoid that somehow (I have in the back of my mind that you should avoid exceptions in those types of initialisers, but I could be wrong on that).