Reputation: 37
There is the following code:
public interface ISettings{
int value();
}
public record ExampleSet1 (int value) implements ISettings{}
public record ExampleSet2 (int value) implements ISettings{}
public class ExampleClass {
private final ExampleSet1 settingsGlobal;
public ExampleClass(ISettings settingsLocal) {
if (settingsLocal instanceof ExampleSet1 set) {
settingsGlobal = set;
} else {
throw new IllegalArgumentException("Settings type mismatch");
}
}
}
In the constructor, you need to check that settingsLocal corresponds to the settingsGlobal type. I would like to put the check in a separate method, but I can't get the settingsGlobal type to check it for compliance. There is an option to implement verification using getClass():
public class ExampleClass {
private final ExampleSet1 settingsGlobal;
public ExampleClass(ISettings settingsLocal) {
if (!validateSettings(settingsLocal)) {
throw new IllegalArgumentException("Settings type mismatch");
}
settingsGlobal = (ExampleSet1) settingsLocal;
}
private boolean validateSettings(ISettings settingsLocal) {
return settingsLocal.getClass().equals(settingsGlobal.getClass());
}
}
But I can't call the getClass() method for a variable that is not initialized.
This is a simplified example. In reality, there may be many classes that contain different types of settings (but they all support the ISettings interface). I wanted to implement validation in an abstract class, so as not to do this in every class used.
How can I check the compliance of the settingsGlobal type?
Upvotes: -3
Views: 58
Reputation: 11941
You can just move the if
check from your first snippet to a method, what exactly does not work there?
For the second snipped what you want is
private boolean validateSettings(ISettings settingsLocal) {
return settingsLocal.getClass().equals(ExampleSet1.class);
}
but the real question here is why your constructor accepts an ISettings
parameter if only instances of one specific subclass are valid.
I would change the constructor to
public ExampleClass(ExampleSet1 settingsLocal) {
Upvotes: 4
Reputation: 1
Your goal of validating the type of settingsLocal against the type of settingsGlobal in a separate method. Since settingsGlobal is not initialized when you want to perform the check, we can't use its getClass() method directly. However, we can still achieve what you want by using the class type directly. Here's a solution:
public class ExampleClass {
private final ExampleSet1 settingsGlobal;
public ExampleClass(ISettings settingsLocal) {
if (!validateSettings(settingsLocal)) {
throw new IllegalArgumentException("Settings type mismatch");
}
settingsGlobal = (ExampleSet1) settingsLocal;
}
private boolean validateSettings(ISettings settingsLocal) {
return settingsLocal instanceof ExampleSet1;
}
}
If you want to make this more flexible and allow the ExampleClass to work with different types of settings, you could use a generic type parameter:
public class ExampleClass<T extends ISettings> {
private final T settingsGlobal;
public ExampleClass(ISettings settingsLocal) {
if (!validateSettings(settingsLocal)) {
throw new IllegalArgumentException("Settings type mismatch");
}
@SuppressWarnings("unchecked")
T castedSettings = (T) settingsLocal;
settingsGlobal = castedSettings;
}
private boolean validateSettings(ISettings settingsLocal) {
return settingsLocal.getClass() == ExampleClass.this.getClass().getTypeParameters()[0].getGenericDeclaration();
}
}
Upvotes: -1