Equivalent to "Abc.class.getName()" for fields - java

In Java you can write:
System.out.println(Abc.class.getName());
It will always print the correct value, even if the class Abc is moved or renamed.
What is the closest you can get to that for field names?
In other words, what can I code that will always give me the "current" name of a field in a class, even if that field is renamed. Ideally, it would also fail to compile if the field is removed altogether. Or at least fail as soon as the class is accessed, during static initialisation.
I want this to simplify a "change tracking" system. It's not quite like "bean properties", because those names are NOT visible outside the class itself.
AFAIK, there is no "native" way to do this, but I'm hoping there might be some trick with annotations and/or reflection that does the job.
I'll write what I'm doing now (minimally simplified):
private static final String IS_SWAPPABLE = "isSwappable";
// ...
private boolean isSwappable;
// ...
public boolean isSwappable() {
if ((clientChanges != null) &&
clientChanges.containsKey(IS_SWAPPABLE)) {
return (Boolean) clientChanges.get(IS_SWAPPABLE);
}
return isSwappable;
}
public boolean setSwappable(final boolean newSwappable) {
if (isSwappable() != newSwappable) {
isSwappable = newSwappable;
onFieldChange(IS_SWAPPABLE, newSwappable);
return true;
}
return false;
}
What I would like is some "magic" that sets the value of IS_SWAPPABLE to "isSwappable" such that if isSwappable is renamed, then IS_SWAPPABLE will be updated appropriately.
OTOH, if there was a syntax like Abc.isSwappable (or Abc#isSwappable) or whatever, I would spare myself the constant, and just write that directly.
What I can do atm is (once) go over the constants (by using some clear naming convention), and make sure for each of them there is an instance field with the same name. But it doesn't really guaranties that IS_SWAPPABLE is used where isSwappable is used.

It looks very simple.
for (Field field : getClass().getFields()) {
System.out.println(field.getName());
}
Then you can mark fields with your own annotations and then read their values like this
for (Field field : getClass().getFields()) {
System.out.println(field.getName());
MyAnnotation annotation = field.getAnnotation( MyAnnotation.class );
System.out.println(annotation.value());
}

Related

Get Original Field Name on GraphQL

I'm using https://github.com/leangen/graphql-spqr with spring-boot java application. I can reach to alias name easily but how can I reach to original fieldName?
class Food {
#GraphQLQuery(name = "aliasNameX", description = "A food's name")
private String originalName;
...
}
....
#GraphQLQuery(name = "foods") // READ ALL
#Override
public List<Food> getFoods(#GraphQLEnvironment ResolutionEnvironment env) {
DataFetchingFieldSelectionSet selectionSet = env.dataFetchingEnvironment.getSelectionSet();
List<SelectedField> fields = selectionSet.getFields();
for (SelectedField f: fields)
{
System.out.println(f.getName());
}
return foodRepository.findAll();
}
When I run this code, Output looks like with alias fields: "aliasNameX", ..., but I need original name like "originalName". Is there a way to do it?
Solved, according to:
https://github.com/leangen/graphql-spqr/issues/381
Posting my original answer here as well.
You want the underlying field names, but from a level above. Still possible, but ugly :(
for (SelectedField selectedField : env.dataFetchingEnvironment.getSelectionSet().getImmediateFields()) {
Optional<Operation> operation = Directives.getMappedOperation(selectedField.getFieldDefinition());
String javaName = operation.map(op -> ((Member) op.getTypedElement().getElement()).getName()).orElse(null);
}
Be very careful though. If there's more than one Java element exposed per GraphQL field, getTypedElement().getElement() will explode. So to be sure you'd have to call getTypedElement().getElements() (plural) instead and decide what to do. ClassUtils#getPropertyMembers might also be useful, or the ClassUtils.findXXX family of methods.
You'd basically have to do this:
List<AnnotatedElement> elements = getTypedElement().getElements();
//Look for a field and use its name
Optional<String> field = Utils.extractInstances(elements, Field.class).findFirst().map(Field::getName);
//Look for a getter and find its associated field name
Optional<String> getter = Utils.extractInstances(elements, Method.class).findFirst().map(ClassUtils::getFieldNameFromGetter);
This API might have to change in future, as SDL-based tools are proliferating, so complex directives like the ones SPQR is using are causing problems...

A method of getting the value of fields without using reflection

I've been given a class with some 200 fields in which their values are read using reflection. It looks basically like this
for (Field f : this.getClass().getFields())
{
try
{
Object o = f.get(this);
if (f.getType() == String.class)
{
//do things with the string
}
}
catch (Exception ex)
{
logger.error("Cannot get value for field. {}", ex.getMessage());
}
}
This works very well for such an unwieldy amount of fields as I suppose is the point of reflection. I've been asked to refactor it because it's slow (is it?).
So far the only method I can come up with his an ungodly amount of hard coding, is there another quick method?
First you should verify with a profiler that it indeed is slow. Reflection is slower than accessing variables normally, but that doesn't necessarily mean that it's the source of slowness.
Provided that you're using setters to modify those values, you can refactor the class to update a Map<String,Object> whenever a setter is called. This provides faster access to the fields than reflection, but may not be possible depending on your use case.
Most of the time is spent in obtaining the Field objects (and possibly filtering them) The actual lookup can be pretty fast. I use ClassValue to cache this information and speed it up.
public enum StringFields {
INSTANCE;
final ClassValue<List<Field>> fieldsCache = new ClassValue<List<Field>>() {
#Override
protected List<Field> computeValue(Class<?> type) {
return Collections.unmodifiableList(
Stream.of(type.getFields())
.filter(f -> f.getType() == String.class)
.peek(f -> f.setAccessible(true)) // turn off security check
.collect(Collectors.toList()));
}
};
public static List<Field> getAllStringFields(Class<?> type) {
return INSTANCE.fieldsCache.get(type);
}
}
So far the only method I can come up with his an ungodly amount of hard coding, is there another quick method?
You can use reflection to get the getters of those fields and generate code which reads out those getters.
The code generation can then be part of a build step.

Checking for NullPointerException, correctness or personal belief?

In my code, I am making a lot of checks for null so that I don't get a NullPointerException usually i am just doing like this:
if(variable != null){
//do something with the variable
}
Is the following better in any way or is it just a matter or personal belief?
if( !variable.equals(null) ){
//do something with the variable
}
Is there a more efficient way to make this check?
Btw I do have done my research already but I cant seem to find concrete evidence to prove either point.
P.S This is a NOT duplicate of Avoiding != null statements, on that the best answer is that you should either use Assert, which cannot be used to run code rather than just display a message, or actually throw the exception which I dont want either. This post is addressing a different issue of the same subject.
if(!variable.equals(null) ){
//do something with the variable
}
If variable is null NPE occurs. First method is far better.
EDIT:
Using Optional:
Consider that you have Person object and want to getSalary(). Unfortunately age can be null - in that case you want default value. You can do Integer salary = Optional.ofNullable(person.getSalary()).orElse(2000). It will return salarty from person or 2000 in case salary is null.
Or you can use java.util.Optional from Java 8.
Very nice examples are on JavaCodeGeeks.
Optional is usually used in java.util.stream lambdas for "functional-style operations".
As others already said, the variant
if(!variable.equals(null))
can NPE itself when variable is null. Furthermore, you have to be sure that the equals method also is null-safe for all object types you use. Thus, if you absolutely need to check, use ==.
As for better solutions (we're going opinion-based here): I think that this ecessive null-checking is a sign of brittle software and suboptimal interface definition. What I currently try to do more and more is use the javax.validation annotation #NotNull to harden my interfaces and get rid off all these runtime checks:
private #NotNull String getName() {...} // guaranteed not to return null
...
if(getName() == null) { // superfluos, your IDE gives a shout if configurd correctly
...
}
... give it a shot :)
Edit (as an answer to the comment, as I need code-formatting):
Here's a complete cut&paste-example from my current eclipse setup:
package stuff;
import javax.validation.constraints.NotNull;
public class Try3 {
public #NotNull String getName() { return ""; }
public void test() {
if(getName() == null)
System.out.println("Cannot happen due to contract");
}
}
Ensure, that the imported type is indeed javax.validation.constraints.NotNull (as other frameworks also have a NotNull annotation, which may be defined in a different way). For eclipse, you also have to check "Enable annotation-based null analysis" in the project settings under JavaCompiler / Errors/Warnings and customize the annotations to use, as eclipse defaults to some home-brewed annotations. The customization can be accessed via the link "Configure" after the checkbox for using default annotations in the same settings page. Hope that helps!
There are two approaches:
public void calculate(Class variable) {
Assert.notNull(variable, "variable was null");
//calculations
}
//and
if (variable == null) {
//bad
} else {
calculate(variable);
}
The second one is the most common one. If your variable is a String consider using Guava.StringUtils with it's fantastic isBlank method which checks if the String is null or ""
Summarizing:
if (variable == null) {
//bad
} else {
//good
}
The above is standard approach. The better approach will be:
private boolean isNull(Class variable) {
return variable == null;
}
if (isNull(variable)) {
} else {
}
I used to do call the below method all the time which checks for nullpointer exception
public static boolean isAvailable(Object data) {
return ((data!=null) && (data.toString().trim().length() > 0));
}

Reducing the cyclomatic complexity, multiple if statements

I have the following code:
private Facility updateFacility(Facility newFacility, Facility oldFacility) {
if (newFacility.getCity() != null)
oldFacility.setCity(newFacility.getCity());
if (newFacility.getContactEmail() != null)
oldFacility.setContactEmail(newFacility.getContactEmail());
if (newFacility.getContactFax() != null)
oldFacility.setContactFax(newFacility.getContactFax());
if (newFacility.getContactName() != null)
oldFacility.setContactName(newFacility.getContactName());
// ......
}
There are around 14 such checks and assignments. That is, except for a few, I need to modify all the fields of the oldFacility object. I'm getting a cyclomatic complexity of this code 14, which is "greater than 10 authorized" as per SonarQube. Any ideas upon how to reduce the cyclomatic complexity?
At some point in your program, you will have to implement the logic:
If the new facility has a property defined, update the old facility accordingly
If not, do not override the previous value from the old facility.
Without having a global look at your project, what you can do is to move that logic inside the setters of each property:
public class Facility {
public void setSomething(String something) {
if (something != null) {
this.something = something;
}
}
}
This way, your update method would simply be:
private Facility updateFacility(Facility newFacility, Facility oldFacility) {
oldFacility.setSomething(newFacility.getSomething());
// etc for the rest
}
I think you can apply Builder Pattern to resolve the issue, it may help you remove the frustration in the loop of if statement. Please see this link for more detials
You can override hashCode and equals methods in Facility class and do as follows:
if(!newFacility.equals(oldFacility))
{
//only when something is changed in newFacility, this condition will be excecuted
oldFacility = newFacility;
}
return oldFacility;
//This is just and example, you can return newFacility directly
NOTE : You can include all params or only those which decide the uniqueness. Its up to you.
Hope this helps!
You could copy the fields for the oldFacility object that you don't want to modify to some other variables, then update the whole oldFacility object, and just replace the fields that you didn't want to change with the content stored in the other variables. i.e.
private Facility updateFacility(Facility newFacility, Facility oldFacility){
String contentNotToBeModified; // or whatever variable type
contentNotToBeModified = oldFacility.getCity();
// Do the same for all data that you want to keep
oldFacility = newFacility;
newFacility.setCity(contentNotToBeModified);
}
So copy the data that you want to keep out of oldFacility first, then substitute oldFacility for newFacility, and replace the required attributes of newFacility with the data from oldFacility.
The not null check seems pointless to me since the NullPointerException won't be thrown if you slightly modify your example like this:
private Facility updateFacility(Facility newFacility, Facility oldFacility) {
if (newFacility != null) {
oldFacility.setCity(newFacility.getCity());
oldFacility.setContactEmail(newFacility.getContactEmail());
oldFacility.setContactFax(newFacility.getContactFax());
oldFacility.setContactName(newFacility.getContactName());
...
}
This will assign null values to references which were referencing to nulls anyway and will not cause any issues.
Assuming you were doing something like newFacility.getCity().toString() then the checks would be useful.
You could use Java Reflection for avoiding that copy/paste/write-same-Problem:
public Facility updateFacility(Facility newFacility, Facility oldFacility)
{
String[] properties = {"City", "ContactEmail", "ContactFax", "ContactName"};
for(String prop : properties) {
try {
Method getter = Facility.class.getMethod("get"+prop);
Method setter = Facility.class.getMethod("set"+prop, getter.getReturnType());
Object newValue = getter.invoke(newFacility);
if (newValue != null)
setter.invoke(oldFacility, newValue);
} catch (NoSuchMethodException |
SecurityException |
IllegalAccessException |
InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
...
}
Now you can simple change the properties[] array when there are new properties in the Facility class which you want to update that way.
EDIT: If you use the return type of the getter method to find the setter method, it is not neccessary to assume that the properties of Facility are all of the same type.
CAVEATS: Be careful in method renaming! This code will lead to runtime errors if you rename or remove methods from the Facility class. If you have to possibility to change the code of the Facility class, you should consider using an annotation to indicate which properties should be updated.

JCodeModel and elseif

I'm generating Java source code with JCodeModel and want to get an "if-elseif" block like this:
if (foo){
} else if (bar) {
}
As far as I understand the according code would be something like this (where m is a JMethod):
JConditional cond = m.body()._if(JExpr.direct("foo"));
cond._elseif(JExpr.direct("bar"));
Seems to be straight forward, but the result is this:
if (foo) {
} else {
if (bar) {
}
}
You see the syntactic difference, it's not actually an "elseif". Semantically it's the same, I know, but I need it to be generated as shown before (it's part of educational software). Any way to do this?
Unfortunately you can not do this using JConditional because of its implementation. Have a look at the source of the method _elseif:
public JConditional _elseif(JExpression boolExp) {
return _else()._if(boolExp);
}
As you can see, this method just invoke _else() and then _if internally.
Actually _else() is JBlock which contains braces ({ ... }) by default. This property of JBlock can not be switched off manually because it doesn't contain such setter. braces could be switched off only through special constructor of JBlock:
public JBlock(boolean bracesRequired, boolean indentRequired) {
this.bracesRequired = bracesRequired;
this.indentRequired = indentRequired;
}
but you are not able to set you own object to _else field of JConditional object outwardly.
The only way is copy JConditional class implementation and generate your own, which will allow you such code manipulation.
UPD: Of course you can always use Reflection as workaround for manually switching flag bracesRequired of _else object to false.

Categories