I have some class storing keys with important information. No one else is allowed to create a key, since a key relys on static information (like certain directory structures etc.).
public final class KeyConstants
{
private KeyConstants()
{
// could throw an exception to prevent instantiation
}
public static final Key<MyClass> MY_CLASS_DATA = new Key<MyClass>("someId", MyClass.class);
public static class Key<T>
{
public final String ID;
public final Class<T> CLAZZ;
private Key(String id, Class<T> clazz)
{
this.ID = id;
this.CLAZZ = clazz;
}
}
}
This example is simplyfied.
I wanted to test the consequences of a wrong key (exception handling, etc.) and instantiated the class via reflection in a JUnit test case.
Constructor<?> c = KeyConstants.Key.class.getDeclaredConstructor(String.class, Class.class);
c.setAccessible(true);
#SuppressWarnings ("unchecked")
KeyConstants.Key<MyClass> r = (KeyConstants.Key<MyClass>) c.newInstance("wrongId", MyClass.class);
Then I asked myself how could I prevent further instantiation of the key class (i. e. preventing further object creating via reflection)?
enums came to my mind, but they don't work with generics.
public enum Key<T>
{
//... Syntax error, enum declaration cannot have type parameters
}
So how can I keep a set of n instances of a generic class and prevent further instantiation?
So how can I keep a set of n instances of a generic class and prevent
further instantiation?
If you truly want to use this pattern, then no one (including you) should be able to instantiate a Key object. In order to keep a set of n instances in a class with this pattern, you could have a private constructor, a static method for access and a SecurityManager to prevent reflection. And since you want to be able to access the keys as pubic constants, I would try something like this..
public class KeyConstants{
// Here are your n instances for public access
public static final int KEY_1 = 1;
public static final int KEY_2 = 2;
.
.
.
public static final int KEY_N = 'n';
// now you can call this method like this..
// Key mKey = KeyConstants.getKey(KeyConstants.KEY_1);
public static Key getKey(int key){
List keys = Key.getInstances();
switch(key){
case KEY_1:
return keys.get(0);
case KEY_2:
return keys.get(1);
.
.
.
case KEY_N:
return keys.get(n);
default:
// not index out of bounds.. this means
// they didn't use a constant
throw new IllegalArgumentException();
}
}
static class Key<T>{
private static List<Key> instances;
private String ID;
private Class<T> CLAZZ;
private Key(String id, Class<T> clazz){
this.ID = id;
this.CLAZZ = clazz;
}
public static List<Key> getInstances(){
if(instances == null){
instances = new ArrayList<Key>();
//populate instances list
}
return instances;
}
}
}
Use SecurityManager to prevent reflection access.
//attempt to set your own security manager to prevent reflection
try {
System.setSecurityManager(new MySecurityManager());
} catch (SecurityException se) {
}
class MySecurityManager extends SecurityManager {
public void checkPermission(Permission perm) {
if (perm.getName().equals("suppressAccessChecks"))
throw new SecurityException("Invalid Access");
}
}
This will throw a SecurityException anytime someone attempts to access a private variable or field in your class (including access attempts via reflection).
I'm not sure I fully understand your question, but if a private constructor is not sufficient, can you use a more dynamic approach and throw an exception in the constructor after a signal is given? For example:
public static class Key<T>
{
private static boolean isLocked = false;
// Call this method when you want no more keys to be created
public static void lock() { isLocked = true; }
...
private Key(String id, Class<T> clazz)
{
if (isLocked) throw new IllegalStateException("Cannot create instances of Key");
this.ID = id;
this.CLAZZ = clazz;
}
}
Then - and this is the disadvantage - you will have to call Key.lock() once you want to prevent more instances being created.
As you showed in your code to prevent instantiating KeyConstants you can throw some Exception inside private-non-argument constructor.
Harder part is way to block creating KeyConstants.Key constructor from outside of KeyConstants class.
Some wild idea
Maybe create Exception in your constructor and check how its stack trace looks like. When I add this code to constructor
private Key(String id, Class<T> clazz) {
StackTraceElement[] stack = new Exception().getStackTrace();
for (int i=0; i<stack.length; i++){
System.out.println(i+") "+stack[i]);
}
this.ID = id;
this.CLAZZ = clazz;
}
and create instance of Key with reflection like
Constructor<?> c = KeyConstants.Key.class.getDeclaredConstructor(
String.class, Class.class);
c.setAccessible(true);
KeyConstants.Key<MyClass> r = (KeyConstants.Key<MyClass>) c
.newInstance("wrongId", MyClass.class);
I get
0) KeyConstants$Key.<init>(Test.java:38)
1) sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
2) sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
3) sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
4) java.lang.reflect.Constructor.newInstance(Constructor.java:525)
so maybe just if 4th element of stack is java.lang.reflect.Constructor.newInstance throw Exception to prevent executing rest of constructors code like:
if (stack.length>=4 && stack[4].toString().startsWith("java.lang.reflect.Constructor.newInstance")){
throw new RuntimeException("cant create object with reflection");
}
I came across some Multiton patterns recently, where I tried to handle problems with unique enum keys, that gave me the idea of another approach.
The keys can be used for information flow as I intended, or even as keys for typesafe heterogeneous container, where they can perform compile-time casting.
Key-defining class
public class KeyConstants
{
public static final KeysForIntegers SOME_INT_KEY = KeysForIntegers.KEY_2;
public static final KeysForStrings SOME_STRING_KEY = KeysForStrings.KEY_1;
public interface Key<Type>
{
public Class<Type> getType();
}
/* Define methods that classes working with the keys expect from them */
public interface KeyInformation
{
public String getInfo1();
// and so on...
}
public enum KeysForStrings implements Key<String>, KeyInformation
{
KEY_1("someId");
public final String ID;
private KeysForStrings(String id)
{
ID = id;
}
#Override
public String getInfo1()
{
return "Good piece of information on " + ID + ".";
}
#Override
public Class<String> getType()
{
return String.class;
}
}
public enum KeysForIntegers implements Key<Integer>, KeyInformation
{
KEY_2("bla");
public final String ID;
private KeysForIntegers(String id)
{
this.ID = id;
}
#Override
public String getInfo1()
{
return "Some info on " + ID + ".";
}
#Override
public Class<Integer> getType()
{
return Integer.class;
}
}
}
Example key-using class
public class KeyUser
{
public static void main(String[] args)
{
KeysForIntegers k1 = KeyConstants.SOME_INT_KEY;
KeysForStrings k2 = KeyConstants.SOME_STRING_KEY;
processStringKey(k2);
useIntKey(k1);
Integer i = useIntKey(KeyConstants.SOME_INT_KEY);
processStringKey(KeyConstants.SOME_STRING_KEY);
}
/* My methods should just work with my keys */
#SuppressWarnings ("unchecked")
public static <TYPE, KEY extends Enum<KeysForIntegers> & Key<TYPE> & KeyInformation> TYPE useIntKey(KEY k)
{
System.out.println(k.getInfo1());
return (TYPE) new Object();
}
public static <KEY extends Enum<KeysForStrings> & KeyInformation> void processStringKey(KEY k)
{
System.out.println(k.getInfo1());
// process stuff
}
}
I have another approach, you can bound an interface in a way to only be implemented by enum.
With that approach you have a fixed set of instances at compile time.
If you want to add lazy loading, the enums implementing it should be proxies that load the desired object if it is requested. The class or classes that are hidden behind the proxies should only be visible to them, so that they have exclusive access to the constructor.
public class User {
public static <S> S handleKey(FixedInstanceSet<S,?> key) {
return key.getKey();
}
}
interface FixedInstanceSet<S, T extends Enum<T> & FixedInstanceSet<S,T>>
{
public S getKey();
}
enum StringKeys implements FixedInstanceSet<String, StringKeys> {
TOP, DOWN, LEFT, RIGHT;
#Override
public String getKey() { return null; }
}
enum IntKeys implements FixedInstanceSet<Integer, IntKeys > {
TOP, DOWN, LEFT, RIGHT;
#Override
public Integer getKey() { return null; }
}
/*
* Bound mismatch: The type NotWorking is not a valid substitute for the bounded
* parameter <T extends Enum<T> & FixedInstanceSet<S,T>> of the type
* FixedInstanceSet<S,T>
*/
//class NotCompiling implements FixedInstanceSet<String, NotCompiling> {
//
// #Override
// public String getKey() { return null; }
//}
If I understand you correctly, you don't want your class to be instantiated.
You can set the default constructor to private
private Key() throws IllegalStateException //handle default constructor
{
throw new IllegalStateException();
}
This will prevent its improper instantiation.
Update:
added throw IllegalStateException
Related
I have a common process with different progress values and step number, depending on the user.
To solve this I've made an interface :
public interface Progress {
int getTotalStepNumber();
int getIndex();
String getMessage();
#Override
String toString();
}
So a step process implementation is like this, litteraly, it is an enumeration of the steps for this process :
public enum ProgressImplementationOfProcessOne implements Progress {
STEP_ONE(1, "Step one message."),
STEP_TWO(2, "Step two message.");
// ... etc. with more steps
/**
* Number of steps for this process.
*/
private static final int STEPS = 2;
private int index;
private String message;
ProgressImplementationOfProcessOne(int index, String message) {
this.index = index;
this.message = message;
}
#Override
public int getTotalStepNumber() { return STEPS; }
#Override
public int getIndex() { return this.index; }
#Override
public String getMessage() { return this.message; }
#Override
public String toString() { return this.message; }
}
But then I thought it would be nice to find the corresponding step from implementation as well, with the method valueOf() of enumerations. So I added the following lines to my interface :
default Progress valueOf(String s) {
for (Progress progress : this.getValues()) {
if (progress.getMessage().equals(s)) {
return progress
}
}
return null;
}
default Progress valueOf(int i) {
for (Progress progress : this.getValues()) {
if (progress.getIndex() == this.getIndex()) {
return progress;
}
}
return null;
}
Since there is no getValues() method in the interface Progress I added the following method to it (thinking "the enum implementation will handle it natively").
default List<Progress> getValues() { return null; }
But I don't understand why I get this error for each ProgressImplementation :
This static method cannot hide the instance method from Progress..
I know I could do it by creating an additional class ProgressStep which replace an enum value, and replace enum by classes with attributes and so on, but since enum can handle multiple values I thought it could have been easier with it.
Simply rename the valueOf to something like valueOfEnum, as valueOf is already specified by java.lang.Enum.
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
The comment on that method contains following section:
Note that for a particular enum type T, the implicitly declared public static T valueOf(String) method on that enum may be used instead of this method to mapfrom a name to the corresponding enum constant. All theconstants of an enum type can be obtained by calling the implicit public static T[] values() method of that type
Emphasis mine
As you can see, valueOf(String s) is already declared on every enum class which in turn is the reason, you can't have it in an interface on any enum
This is a continuation from what I was working in Passing 1 to many parameters of same object type
I've gotten good feedback on that , I believe i have the improved the design . The whole code is at https://github.com/spakai/flow_input_builder
The requirement is simple : -
I need to build a set of input for different workflows using 1 or more outputs from previous workflows
I have a set of interfaces
public interface SwfInput {
}
public interface SwfOutput {
}
public interface Workflow<I extends SwfInput, O extends SwfOutput> {
public O execute(I input);
}
public interface Builder<I extends SwfInput> {
public I build();
}
Now , Say I have 3 flows which gets executed in sequence FlowA->FlowB->FlowC
FlowC needs mandatory output from FlowB but only optionally from FlowA
so I have a implementation for FlowCBuilder
public class FlowCInputBuilder implements Builder<FlowCInput> {
private final FlowBOutput mandatoryflowBOutput;
private FlowAOutput optionalflowAOutput;
public FlowAOutput getOptionalflowAOutput() {
return optionalflowAOutput;
}
public FlowCInputBuilder setOptionalflowAOutput(FlowAOutput optionalflowAOutput) {
this.optionalflowAOutput = optionalflowAOutput;
return this;
}
public FlowCInputBuilder(FlowBOutput mandatoryflowBOutput) {
this.mandatoryflowBOutput = mandatoryflowBOutput;
}
#Override
public FlowCInput build() {
FlowCInput input = new FlowCInput();
input.setMandatoryFromFlowB(mandatoryflowBOutput.getOutput1FromB());
if (optionalflowAOutput != null) {
input.setOptionalFromFlowA(optionalflowAOutput.getOutput2FromA());
}
return input;
}
}
one test i have written shows an example usage
FlowBOutput mandatoryflowBOutput = new FlowBOutput();
mandatoryflowBOutput.setOutput1FromB("iNeedThis");
FlowAOutput optionalflowAOutput = new FlowAOutput();
FlowCInput input = new FlowCInputBuilder(mandatoryflowBOutput)
.setOptionalflowAOutput(optionalflowAOutput)
.build();
I have not used static inner class for the Builder pattern.
Any suggestions are welcomed.
You should use static inner class. The key point of using this approach is that, the inner can directly access private properties of the object being constructed. This helps eliminating duplicated code since the builder does not need to maintain a long list of temporary state for the constructing. So, your code can be rewritten like this:
public class FlowCInput {
private int output1FromB; // suppose that it is int
private String output2FromA; // suppose that it is String
private FlowCInput() { }
//...
public static class FlowCInputBuilder implements Builder<FlowCInput> {
private final FlowCInput result;
public FlowCInputBuilder(FlowBOutput mandatoryflowBOutput) {
result = new FlowCInput();
// output1FromB is private but still accessed from here
result.output1FromB = mandatoryflowBOutput.getOutput1FromB();
}
public FlowCInputBuilder setOptionalflowAOutput(FlowAOutput optionalflowAOutput) {
// same for output2FromA
result.output2FromA = optionalflowAOutput.getOutput2FromA();
return this;
}
#Override
public FlowCInput build() {
return result;
}
}
}
As you see, the builder now holds only a FlowCInput object, it does not unnecessarily hold mandatoryflowBOutput and optionalflowAOutput as before.
What's the proper way to ensure a value only gets set once, although the time it will be set is unknown (ie: not in the constructor). I could do a null check or keep track of a flag and throw an exception - but what exception should I throw? It's for a small, localized library and I prefer not to create my own ValueAlreadyAssigned exception for such a seemingly generic case.
In the setter. Do it like this:
private foo bar;
public void setFoo(foo bar) {
if (this.bar == null) {
this.bar = bar;
} else {
System.out.println("Don't touch me!");
// J/K Throw an IllegalStateException as Michal Borek said in his answer.
}
}
The method could throw IllegalStateException, since it's javadocs say:
Signals that a method has been invoked at an illegal inappropriate
time.
IMHO definition of your own exception is not a big deal especially if it extends RuntimeException. So I'd suggest you to define ValueAlreadySetException extends IllegalStateException and use it.
The next point is the logic into each setter you have to duplicate according to #Renan's suggestion. I'd suggest you the following. Define special generic container and use it:
public class SetOnceContainer<T> {
private Class<T> type;
private String name;
private T value;
private boolean set = false;
public SetOnceContainer(Class<T> type, String name) {
this.type = type;
this.name = name;
}
public void set(T value) {
if (set) {
throw new ValueAlreadySetException(name);
}
this.value = value;
this.set = true;
}
public T get() {
return value;
}
}
Please pay attention that this implementation supports null values too.
Now you can use it as following:
public MyClass {
private SetOnceContainer<Integer> number = new SetOnceContainer<Integer>(Integer.class, "number");
private SetOnceContainer<String> text = new SetOnceContainer<String>(String.class, "text");
public void setNumber(int value) {
number.set(value);
}
public void setText(String value) {
text.set(value);
}
public Integer getNumber() {
return number.get();
}
public String getText() {
text.get();
}
}
The implementation is encapsulated into once point. You can change it in once place if you need. Null values are supported too. The setters and getters are just a little bit more complicated than regular.
Suppose you create a class names Person using the builder pattern, and suppose the Builder class contains methods body(), head(), arms() and of course build() and you consider methods head() and build() obligatory for the user of this class.
We would like to somehow mark these methods obligatory, if possible using annotations. If a user of this class tries to build a Person instance but forgot to call either of these methods, we would like to get some kind of warning - either from the java compiler, or maybe from Eclipse or Maven, which we use to build our projects - any of them would do.
Is it possible to do? Which way would you suggest?
Here is an example with using different types to make some parts mandatory (it also makes the order you call the methods mandatory):
package test;
import test.StepOne.StepThree;
import test.StepOne.StepTwo;
import test.StepOne.LastStep;
public class TestBuilder {
public static void main(String[] args) {
String person1 = PersonBuilder.newInstance().head("head").body("body").arm("arm").leg("leg").build();
String person2 = PersonBuilder.newInstance().head("head").body("body").arm("arm").build();
}
}
interface StepOne {
// mandatory
StepTwo head(String head);
interface StepTwo {
// mandatory
StepThree body(String body);
}
interface StepThree {
// mandatory
LastStep arm(String arm);
}
// all methods in this interface are not mandatory
interface LastStep {
LastStep leg(String leg);
String build();
}
}
class PersonBuilder implements StepOne, StepTwo, StepThree, LastStep {
String head;
String body;
String arm;
String leg;
static StepOne newInstance() {
return new PersonBuilder();
}
private PersonBuilder() {
}
public StepTwo head(String head) {
this.head = head;
return this;
}
public LastStep arm(String arm) {
this.arm = arm;
return this;
}
public StepThree body(String body) {
this.body = body;
return this;
}
public LastStep leg(String leg) {
this.leg = leg;
return this;
}
public String build() {
return head + body + arm + leg;
}
}
Edit
The OP was so impressed with this answer that he wrote it up fully in a blog. It's such a clever take on the builder pattern that a full treatment deserves to be referenced here.
I believe the correct use of the builder pattern would solve the issue you're having.
I would create class PersonBuilder which would contain the methods setBody() and setArms() and every other optional parameter setter method. The constructor of the builder would take the required parameters. Then the method build() would return the new instance of Person.
public class PersonBuilder
{
private final Head head;
private Body body;
private Arms arms;
public PersonBuilder(Head head)
{
this.head = head;
}
public void setBody(Body body)
{
this.body = body;
}
public void setArms(Arms arms)
{
this.arms = arms;
}
public Person build()
{
return new Person(head, body, arms);
}
}
Alternatively you could pass the Head parameter to the method build() but I prefer passing it in the constructor instead.
No way with the compiler.
You can do is throw a runtime exception from the build() method that the builder is not properly initialized (and have a test that is invoked in the maven test phase)
But you can also have build(..) accept a HeadDetails object. That way tou can't invoke build without specifying the obligatory parameters.
Why not calling body(), head(), arms() in the build()-Method if it is really mandatory and returning Person in the build() method?
[edit]
Short example:
public class Builder {
private final String bodyProp;
private final String headProp;
private final String armsProp;
private String hearProps;
public Builder(String bodyProp, String headProp, String armsProp) {
super();
this.bodyProp = bodyProp; // check preconditions here (eg not null)
this.headProp = headProp;
this.armsProp = armsProp;
}
public void addOptionalHair(String hearProps) {
this.hearProps = hearProps;
}
public Person build() {
Person person = new Person();
person.setBody(buildBody());
// ...
return person;
}
private Body buildBody() {
// do something with bodyProp
return new Body();
}
public static class Person {
public void setBody(Body buildBody) {
// ...
}
}
public static class Body {
}
}
Maybe inside of build() you could check if all the required methods have been called. Behaps the Person instance has some internal sanity check which is triggered by build().
Of course this checks runtime behaviour and is no static analysis as you describe it.
isn't possible to call these methods in Person's constructor ?
I have encountered a weird problem in my app (java).
I have an enum. Something like that
public enum myEnum implement myIntrface{
valueA(1),valueb(2),valuec(3),valued(4)
private int i;
// and then - a constructor
public MyEnum(int number){
i = number;
}
private MyObj obj = new MyObj;
// getter and setter for obj
}
and in another class I have this
MyEnum.valueA.setObj(new Obj(...))
in briefe - I have an enum with a private instance member that has a set and a get.
So far so good -
The only thing that amazes me is that later on I look at the value of the MyEnum.valueA().obj is null.
there is nothing that updates the value to null, I have even gave it a default value in the constructor and I still see it null later.
any suggestions?
Enums should be un-modifiable classes so you shouldn't really be doing this. If your looking to modify the state of a type based object like an enum you should use an final class approach with embedded constants. Below is an example of a class based approach with a modifiable name an a un-modifiable name...
public final class Connection {
public static final Connection EMAIL = new Connection("email");
public static final Connection PHONE = new Connection("phone");
public static final Connection FAX = new Connection("fax");
/**/
private final String unmodifiableName; //<-- it's final
private String modifiableName;
/*
* The constructor is private so no new connections can be created outside.
*/
private Connection(String name) {
this.unmodifiableName = name;
}
public String getUnmodifiableName() {
return unmodifiableName;
}
public String getModifiableName() {
return modifiableName;
}
public void setModifiableName(String modifiableName) {
this.modifiableName = modifiableName;
}
}
The purpose of enums is to represent constant values. It does not make any sense to set the fields of a constant value.
You should declare your fields as final, and use the constructor to initialize all of them.
For reference, the following code works as expected:
public class Test {
public static enum MyEnum {
valueA(1),valueb(2),valuec(3),valued(4);
private int i;
private Object o;
private MyEnum(int number) {
i = number;
}
public void set(Object o) {
this.o = o;
}
public Object get() {
return o;
}
}
public static void main(String[] args) {
System.out.println(MyEnum.valueA.get()); // prints "null"
MyEnum.valueA.set(new Integer(42));
System.out.println(MyEnum.valueA.get()); // prints "42"
}
}
the cause of this problem is the db40 framework . It loads an enum from the db using reflection. This is well documented .
http://developer.db4o.com/Forums/tabid/98/aft/5439/Default.aspx