Accessing field in Java based on condition - java

I have to write a utility method that can get the particular variable value from an Object,
on evaluating some conditions.
Below are the requirements.
if "name" is coming as type call "getName" to get the Value.
If "subtype" is coming as type call "getSubType" to get the Subtype Value.
Current Solution:
public Object getFieldValue(String type, IDTO dto){
Method method = dto.getClass().getMethod("get"+createMethodName(type));
Object returnedObject = method.invoke(dto, null);
return returnedObject;
}
However, the operations are quite heavy and it is giving performance issues. Is there any alternative that can be chosen or any better way to do this.
Other points:
Interface IDTO has all the getter setters declared only. No fields declared in that.

If you need performance I would suggest to use code generation for the utility method doing the needed access to IDTO objects. Usually this would be integrated into the build. Your generated method could use a well performing switch statement for every 'type', for example:
/**
* Utility for generic access to IDTO object properties.
* GENERATED code, do not change! See template ....
*/
public Object getFieldValue(String type, IDTO dto){
switch (type) {
case "name" : return dto.getName();
case "subtype" : return dto.getSubtype();
...
}
// ERROR handling
throw new RuntimeException("unknown property");
}
To implement your generator code you could use reflection in the same way as you're code above already does.
For a more extensive usage of that approach I would suggest to introduce a simple template engine, see for example https://freemarker.apache.org

Related

How to type cast via reflection when the class is package private

First, this is similar to this question but there was never a satisfactory answer. Second: I know, I know, reflection is bad, but it is the only option I have.
Question: Given a class
package a.pkg.outside.my.code;
class ClassIWant { // Package private class
public ClassIWant instance() {...}
}
I want to call instance(), obtaining an instance of ClassIWant, and return a ClassIWant (not an Object).
I can successfully call instance via reflection and get my hands on an Object:
public class MyClass {
/* type var T will always take value ClassIWant. I can currently get
* get this to type check by using Class.cast and changing return
* type to T, but this doesn't solve my problem.
*/
public <T> ClassIWant callInstance() { // Here T is ClassIWant
Class<T> clazz = Class.forName("a.pkg.outside.my.code.ClassIWant");
Object result = _use reflection_;
return (ClassIWant) result; // Fails at runtime
}
}
The issue is that I don't have access to ClassIWant to cast, and the best I've been able to do is call clazz.cast(result). This returns type T, which doesn't quite do what I want.
It's not even clear to me that this is possible, but my program has been type checking and getting illegal access errors at runtime. This tells me that all the bits and pieces fit together on the type level, and that methods are all pointing to the right place.
Note: It may be possible to change my use case to not need an explicit ClassIWant, but this would probably be a fair amount of work (i.e., lots and lots of calls to reflection). For brevity I haven't included the use case---I'll treat this as a second question if need be.
Edit: Updated in response to Andy Turner's comment (thanks for the catch): in more detail, I'm not explicitly using T here, but I have access to it and I want to make that explicit

Why are no-arg constructors subject to being instantiated in an invalid state?

I was looking to JavaBean advtanges and disadvantages. In the disadvantages section, I came across this:
A class with a nullary constructor is subject to being instantiated in an invalid state.
Wikipedia - JavaBeans
What exactly does this mean? How does this opppse to constructors that have parameter arguments?
If such a class is instantiated manually by a developer (rather than automatically by some kind of framework), the developer might not realize that the class has been improperly instantiated.
A JavaBean framework may perform automatic operations on an instantiated JavaBean, for example, by calling methods, passing parameters to regular methods, etc. depending on what the JavaBean is designed to do, and how the framework is expected to process JavaBeans under its control.
The compiler can’t detect such a problem, and even if it’s documented, there’s no guarantee that the developer will see the documentation.
Rephrased: "Developers aren't always diligent, and even when they are, they're not always right."
Components designed explicitly for consumption by automated tools aren't always well designed for consumption by actual people.
Consider java.net.URL
Let's suppose it has a null constructor, and a setter for the actual url string, port, etc. When set up using the null constructor, it will be in an invalid state, and anyone trying to use that URL object will have a problem.
URL clearly doesn't have a null constructor. I used this just to highlight the point that for some objects, having a null constructor can initialize them in an invalid state
Consider a simple class that has a simple String attribute called name. It might have a public String getName() method to fetch the value of the attribute. Although the signature of that method says it returns a reference to a String object, the design of your class might be more restrictive than that. The design might state that the name may not be null, may not be empty, and must begin with an upper case character, and must be unique, for example. Any object of that class that was ever observed to have a name that did not conform to all those restrictions would be invalid.
The job of the constructor is to set up a new object in its initial state, which must be a valid state. Some of the kinds of restrictions on values are impossible for a constructor to meet without the constructor being given addition information about how to construct the object.
A constructor without arguments can not be given that information, so there are some kinds of restriction the design of a Java Bean can not apply, or can apply only if the constructor is exempt from them. Being exempt from them really means allowing the constructor to create invalid objects.
An object created by a nullary constructor will not set value to any of its properties. If a framework sets it, it will likely know which properties need to be set to what kind of values before the object can be used. However, a programmer, who is not familiar with the intention of the object, might not know or forget to set the properties to valid values. Even if there is documentation to stipulate what values need to be set for which parameters, a human programmer may not read that documentation or remember to follow all the rules.
For example, in the following code, if the object "data" is not set to a valid Enum type (such as null), an InvalidObjectException will be raised.
Object toJavaTypeData(Object data)
throws OpenDataException, InvalidObjectException {
try {
return Enum.valueOf(enumClass, (String) data);
} catch (IllegalArgumentException e) {
// missing enum constants
final InvalidObjectException ioe =
new InvalidObjectException("Enum constant named " +
(String) data + " is missing");
ioe.initCause(e);
throw ioe;
}
}

Compiletime validation of enum parameters

There is a constructor with three parameters of type enum:
public SomeClass(EnumType1 enum1,EnumType2 enum2, EnumType3 enum3)
{...}
The three parameters of type enum are not allowd to be combined with all possible values:
Example:
EnumType1.VALUE_ONE, EnumType2.VALUE_SIX, EnumType3.VALUE_TWENTY is a valid combination.
But the following combination is not valid:
EnumType1.VALUE_TWO, EnumType2.VALUE_SIX, EnumType3.VALUE_FIFTEEN
Each of the EnumTypes knows with which values it is allowed to be combined:
EnumType1 and the two others implement a isAllowedWith() method to check that as follows:
public enum EnumType1 {
VALUE_ONE,VALUE_TWO,...;
public boolean isAllowedWith(final EnumType2 type) {
switch (this) {
case VALUE_ONE:
return type.equals(Type.VALUE_THREE);
case VALUE_TWO:
return true;
case VALUE_THREE:
return type.equals(Type.VALUE_EIGHT);
...
}
}
I need to run that check at compile time because it is of extreme importance in my project that the combinations are ALWAYS correct at runtime.
I wonder if there is a possibility to run that check with user defined annotations?
Every idea is appreciated :)
The posts above don't bring a solution for compile-time check, here's mine:
Why not use concept of nested Enum.
You would have EnumType1 containing its own values + a nested EnumType2 and this one a nested EnumType3.
You could organize the whole with your useful combination.
You could end up with 3 classes (EnumType1,2 and 3) and each one of each concerned value containing the others with the allowed associated values.
And your call would look like that (with assuming you want EnumType1.VALUE_ONE associated with EnumType2.VALUE_FIFTEEN) :
EnumType1.VALUE_ONE.VALUE_FIFTEEN //second value corresponding to EnumType2
Thus, you could have also: EnumType3.VALUE_SIX.VALUE_ONE (where SIX is known by type3 and ONE by type1).
Your call would be change to something like:
public SomeClass(EnumType1 enumType)
=> sample:
SomeClass(EnumType1.VALUE_ONE.VALUE_SIX.VALUE_TWENTY) //being a valid combination as said
To better clarify it, check at this post: Using nested enum types in Java
So the simplest way to do this is to 1) Define the documentation to explain valid combinations and
2) add the checks in the constructor
If a constructor throws an Exception than that is the responsibility of the invoker. Basically you would do something like this:
public MyClass(enum foo, enum bar, enum baz)
{
if(!validateCombination(foo,bar,baz))
{
throw new IllegalStateException("Contract violated");
}
}
private boolean validateCombination(enum foo, enum bar, enum baz)
{
//validation logic
}
Now this part is absolutely critical. Mark the class a final, it is possible that a partially constructed object can be recovered and abused to break your application. With a class marked as final a malicious program cannot extend the partially constructed object and wreak havoc.
One alternative idea is to write some automated tests to catch this, and hook them into your build process as a compulsory step before packaging/deploying your app.
If you think about what you're trying to catch here, it's code which is legal but wrong. While you could catch that during the compilation phase, this is exactly what tests are meant for.
This would fit your requirement of not being able to build any code with an illegal combination, because the build would still fail. And arguably it would be easier for other developers to understand than writing your own annotation processor...
The only way I know is to work with annotations.
Here is what I do I mean.
Now your constructor accepts 3 parameters:
public SomeClass(EnumType1 enum1,EnumType2 enum2, EnumType3 enum3){}
so you are calling it as following:
SomeClass obj = new SomeClass(EnumTupe1.VALUE1, EnumTupe2.VALUE2, EnumTupe1.VALUE3)
Change the constructor to be private. Create public constructor that accept 1 parameter of any type you want. It may be just a fake parameter.
public SomeClass(Placeholder p)
Now you have to require to call this constructor while each argument is annotated with special annotation. Let's call it TypeAnnotation:
SomeClass obj = new SomeClass(TypeAnnotation(
type1=EnumType1.VALUE1,
type2=EnumTupe2.VALUE2,
type3=EnumTupe1.VALUE3)
p3);
The call is more verbose but this is what we have to pay for compile time validation.
Now, how to define the annotation?
#Documented
#Retention({RetentionPolicy.RUNTIME, RetentionPolicy.SOURCE})
#Target(PARAMETER)
#interface TypeAnnotation {
EnumType1 type1();
EnumType2 type3();
EnumType3 type3();
}
Please pay attention that target is PARAMETER and retention values are RUNTIME and SOURCE.
RUNTIME allows reading this annotation at runtime, while SOURCE allows creating annotation processor that can validate the parameters at runtime.
Now the public constructor will call the 3-parameters private construcor:
public SomeClass(Placeholder p) {
this(readAnnotation(EnumType1.class), readAnnotation(EnumType2.class), readAnnotation(EnumType3.class), )
}
I am not implementing readAnnotation() here: it should be static method that takes stack trace, goes 3 elements back (to caller of the public costructor) and parses annotation TypeAnnotation.
Now is the most interesting part. You have to implement annotation processor.
Take a look here for instructions and here for an example of annotation processor.
You will have to add usage of this annotation processor to your build script and (optionally) to your IDE. In this case you will get real compilation error when your compatibility rules are violated.
I believe that this solution looks too complicated but if you really need this you can do this. It may take a day or so. Good luck.
Well, I am not aware of a compile time check but I do not think it is possible because how can the compiler know which value will be passed to the constructor (In case the value of your enum variable is calculated in runtime (e.g. by an If clause) ?
This can only be validated on runtime by using a validator method as you implemented for the enum types.
Example :
If in your code you have something like this :
EnumType1 enumVal;
if (<some condition>) {
enumVal = EnumType2.VALUE_SIX;
} else {
enumVal = EnumType2.VALUE_ONE;
}
There is no way the compiler can know which of the values will be assigned to enumVal so it won't be able to verify what is passed to the constructor until the if block is evaluated (which can be done only in runtime)

help requested understanding Java Reflection --> Android ParcelableContainer

I'm, playing with the Android framework and try to get my mind deeper into Java. For This I read about Javas Generics and the Reflection API, while I'm not understanding it really.
Because I'm a lazy Dev ;) I tried to write an 'Parcelable-Container' in which I can put ANY Object I wish to get it Parcelable without the need to implement this for every Object again using methods of Java Reflection.
I write a test method like these:
public <T> void writeClassInformations(T t){
Class c = t.getClass();
System.out.println("DeclaredFields: ");
for (Field f : c.getDeclaredFields()){
System.out.println(f.toGenericString());
}
System.out.println("Fields: ");
for (Field f: c.getFields()){
System.out.println(f.toGenericString());
}
}
How can I get every member even if they are Objects or private Superclass members?
And another Question: The output is like this:
public int hello.test.Testclass.myID
how I get the value of 'myID'?
ADD:
I'm running in serious problems now. The Interface of Parcelable.Creator forces me to write a statement like: public static final Parcelable.Creator CREATOR =
new Parcelable.Creator<ParcelableBox<?>>()
Can I use ? somehow? Normally I use a constructor like ParcelableBox(E object). While it seems to me that I can't use Object methods on ? I even cannot pass it into a class variable like
public ParcelableBox<?> createFromParcel(Parcel source){
...
return new ParcelableBox<?>();
}
or ? myClass to use Reflection on it. Is this the end of javas reflection power? How can I get Class of ?
Reflection should be used sparingly, or not at all if it can be avoided, and especially not as a way to hack around good design principles. That being said, it can also be useful in certain situations ...
getDeclaredFields can return all types of fields while getFields only returns fields marked public.
The reason your test returns the same thing is that you're using getDeclaredFields in both statements.
how I get the value of 'myID'
You can only do that by operating on an instance of a class. E.g.,
T t = ...
Field field = t.getClass().getDeclaredField("myID");
field.setAccessible(true);
String value = (String) field.get(t);

abstracting code from two methods in Java, maybe use delegates?

I have two methods that do essentially the same thing, just with different types. I want to abstract out this functionality to some generic method and I think I could do it easily in C# with delegates, but I don't know the equivalent in Java. I'm just showing two of the methods here, but there are several (like eight) different makeWhateverRequest-style methods. Here are my methods:
public State makeGetRequest(User user, String name) {
Get request = Builder.getGetRequest(user, name);
GetResponse response = service.get(request);
return ResponseTypeFactory.getResponseType(response);
}
public State makePutRequest(User user, String name) {
Put request = Builder.getPutRequest(user, name);
PutResponse response = service.put(request);
return ResponseTypeFactory.getResponseType(response);
}
If there could be some delegate-like thing that would take a User and a String (as in the first line of each method), that would make that line abstractable to a generic method. However, note that the first line returns a different value (i.e., an instance of either Get or Put) and this value is used in the second line. The last line of each method is already the same, and uses polymorphism to figure out which version of getResponseType to call, so that's fine.
One difficulty is with the second line of each method where I need to call a different method. Perhaps I could have some interface that both Get and Put implement, then require a delegate-like thing that takes an instance of that interface. Then maybe both GetResponse and PutResponse could implement a different interface, and I could ensure there is a getResponseType that takes an instance of that interface.
Get and Put inherit from a common base class, Request. GetResponse and PutResponse inherit from a common base class, Response. I could probably make those base classes abstract and then, instead of having different interfaces, I could just have methods that take instances of the abstract base class necessary.
I'm not very familiar with Java, so I don't know the equivalent ways of doing things that I would do in C#. Thanks for the help.
Edit: here are my ideas for what interfaces might be necessary:
IRequest IResponse
| \ | \
Get Put GetResponse PutResponse
Then I would need these methods:
Builder.getRequest(User, String)
=> IRequest
service.getPut(IRequest)
=> IResponse
ResponseTypeFactory.getResponseType(IResponse)
=> State
I don't think there is a good way in Java to improve on what you have. You could do something with interfaces but it would be more verbose. If your methods really are only 3 lines each I would stick with what you have. The code is clear and the duplication is minimal.
Java typically uses single method interfaces and anonymous inner classes for the equivalent of delegates but they would definitely be too verbose for the examples you've posted.
Your edit is the answer if you want to make your code a little more generic. You will need to change the Builder.getRequest method so that it takes in a parameter that indicates whether a Get or a Put is what you require (unless that can be deduced from either the 'user' or 'name' parameter).
On an unrelated and potentially controversial note, you may want to consider using Dependency Injection instead of static methods for Builder and ResponseTypeFactory.
You can also consider to make use of an enum and a switch statement.
Basic example:
public enum RequestMethod { GET, PUT /* Add remaining here */ };
public State makeRequest(RequestMethod method, User user, String name) {
Object response;
switch (method) {
case GET:
response = service.get(Builder.getGetRequest(user, name));
break;
case PUT:
response = service.put(Builder.getPutRequest(user, name));
break;
// Add remaining cases here.
}
return ResponseTypeFactory.getResponseType(response);
}
I have implemented callback/delegate support in Java using reflection. Details and working source are available on my website. This would fit with what you are trying to do.

Categories