I have been trying to create a robust code that prints out any Java class for debugging. For that, I use reflections.
In order to protect against recursive definition such as "Boolean contains static final Boolean TRUE", I ignore fields equal to their parents.
I use String += just out of laziness. It doesn't have to be efficient.
Yet, is there a nicer way to do recursive description of objects with reflections?
public String reflectionShowFields(Object parentObject) {
String stringData = "";
for (Field field:parentObject.getClass().getFields()) {
try {
Class<?> type = field.getType();
String typeSimpleName = type.getSimpleName();
Object fieldValue = field.get(parentObject);
String fieldName = field.getName();
if (type.isPrimitive() || type.isEnum() || CharSequence.class.isAssignableFrom(type)) {
stringData += String.format("%s: %s\n", fieldName, fieldValue);
} else if (Iterable.class.isAssignableFrom(type)) {
stringData += String.format(">>> %s[%s]: \n", fieldName, typeSimpleName);
for (Object item:(Iterable)fieldValue) {
stringData += reflectionShowFields(item);
}
stringData += String.format("<<< %s[%s]: \n", fieldName, typeSimpleName);
} else if (!fieldValue.equals(parentObject)) {
stringData += String.format(">>> %s[%s]: %s \n--------\n", fieldName, typeSimpleName, fieldValue.toString());
stringData+= reflectionShowFields(fieldValue);
stringData += String.format("<<< %s[%s]: \n", fieldName, typeSimpleName);
}
} catch (IllegalAccessException ignored) {}
}
return stringData;
}
You could use Apache commons-lang ReflectionToStringBuilder https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/ReflectionToStringBuilder.html
I don't think this is going to work.
Ignoring fields "that are equal to their parents" won't work. What if you have an A that refers to a B that refers back to the A.
You want to know about the cycles, and also the shared nodes in a DAG.
Iterating an Iterable can have side-effects, or it might never terminate, or it might throw exceptions.
Producing a readable rendering of an arbitrary graph is likely to really hard.
This is going to be an order of magnitude slower than a hand-built toString() method.
But think about it this way. If this was a good idea, there would be high profile 3rd-party libraries that did this kind of thing. And we'd all be using them already. It turns out that there ARE 3rd-party libraries, but you'd hardly call them high profile.
Incidentally, you could use JAXB or a JSON binding to render your POJOs as text. That achieves the same ends ...
Finally, your example of Boolean with a static field of type Boolean is not apropos. You wouldn't want to render static fields when displaying an instance.
Related
First of all, I know it's plenty of already asked (and generically answered) questions around here about how good of a practice it is to use Java Reflection, but I'm specifically wondering how bad it is in a specific context that is AWS Lambda.
I'm thrilled and amazed on the power of Java Reflection and I wrote some utility methods to more easily and (code length) efficiently execute some tasks in my serverless architecture, in particular when I have to deal with Dynamo DB queries.
I think that AWS Dynamo DB sdk lacks of some powerful facilities and that the DynamoDBMapper class is far from the perfection, but it still might be because of some lack of knowledge by myself.
Going straight to the point, and thinking on a sentence I've heard yesterday about lambda, "you don't pay for the code storage", I'd like to know, from your experience, if I'd rather write tons of boilerplate code or using reflection is good enough.
Here's an explanatory enough example, that I use to get the real attributeName of a field or a method from a class mapping a DynamoDBTable:
private static <T extends Bean, A extends Annotation> String getBeanKeyAttributeName(Class<T> tClass,
Class<A> annClass) {
Field field = Arrays.stream(tClass.getDeclaredFields()).filter(f -> f.isAnnotationPresent(annClass)).findAny()
.orElse(null);
if (field != null) {
String s = getAttributeName(annClass, field.getAnnotation(annClass));
if (s != null)
return s;
return field.getName();
}
Method method = Arrays.stream(tClass.getDeclaredMethods()).filter(f -> f.isAnnotationPresent(annClass))
.findAny().orElse(null);
if (method == null)
throw new IllegalArgumentException();
String key = method.getName();
if (key.startsWith("get")) {
key = key.replaceFirst("get", "");
key = (key.charAt(0) + "").toLowerCase() + key.substring(1);
}
String s = getAttributeName(annClass, method.getAnnotation(annClass));
if (s != null)
return s;
return key;
}
private static <A extends Annotation> String getAttributeName(Class<A> annClass, A annotation) {
try {
Method attributeNameMethod = annClass.getMethod("attributeName");
attributeNameMethod.setAccessible(true);
String s = (String) attributeNameMethod.invoke(annotation);
if (!s.isEmpty())
return s;
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
EDIT: I might have not been very precise in describing my question. There is not an actual problem, I'm wondering if the usage of the reflection might uselessly slow down my lambda invocation and if anybody has every made some tests and report some results.
as the title states.
I wish to transform this code into lambda would that be possible?
crashFile.forEach(new Consumer<String>() {
String lastLine;
#Override
public void accept(String line) {
if((title == null || title.equals("")) && line.contains("at")) {
title = lastLine;
}
lastLine = line;
}
});
It's not directly possible, no.
Lambdas can't have state (outside of whatever state they capture from their surrounding context). Even if they could, it'd be a bit awkward to access it, because this refers to the surrounding context (that is, to the object whose method the lambda is defined in), not the lamdba's instance. That's specified in JLS 15.27.2.
You could do something like declaring an AtomicReference<String> right before the lambda, and then using it to manage the lastLine state; but that would probably be an abuse of lambdas, more than an idiomatic use of them. Lambdas are really designed to be pretty stateless, except insofar as they capture their surrounding context's state (which is why 15.27.2) specifies that this references that context, instead of the lambda).
You can't have encapsulated fields but you can have a reference to an array of 1
String[] lastLine = { null };
crashFile.forEach(line -> {
if((title == null || title.equals("")) && line.contains("at")) {
title = lastLine[0];
}
lastLine[0] = line;
});
System.out.println("The last line was " + lastLine[0]);
I'm writing a function where I'm essentially doing the same thing over and over. I have the function listed below
public String buildGarmentsString(List<Garment> garments)
{
StringBuilder garmentString = new StringBuilder(10000);
for(int i=0;i<4;i++)
{
garmentString.append(this.garmentProductId(i,garments.get(i).getProductId()));
garmentString.append(this.garmentColor(i,garments.get(i).getColor()));
for(int j=0;j<garments.get(i).getSizes().size();j++)
{
//check xxsml
if(garments.get(i).getSizes().get(j).getXxsml() >0)
{
garmentString.append(this.garmentSizes(i, Size.xxsml(),garments.get(i).getSizes().get(j).getXxsml()));
}
//check xsml
if(garments.get(i).getSizes().get(j).getXsml() > 0)
{
garmentString.append(this.garmentSizes(i,Size.xsml(),garments.get(i).getSizes().get(j).getXsml()));
}
//check sml
if(garments.get(i).getSizes().get(j).getSml() > 0)
{
garmentString.append(this.garmentSizes(i,Size.sml(),garments.get(i).getSizes().get(j).getSml()));
}
//check med
if(garments.get(i).getSizes().get(j).getMed() > 0)
{
garmentString.append(this.garmentSizes(i,Size.med(),garments.get(i).getSizes().get(j).getMed()));
}
//check lrg
if(garments.get(i).getSizes().get(j).getLrg() > 0)
{
garmentString.append(this.garmentSizes(i,Size.lrg(),garments.get(i).getSizes().get(j).getLrg()));
}
//check xlrg
if(garments.get(i).getSizes().get(j).getXlg() > 0)
{
garmentString.append(this.garmentSizes(i,Size.xlg(),garments.get(i).getSizes().get(j).getXlg()));
}
//check xxlrg
if(garments.get(i).getSizes().get(j).getXxl() >0)
{
garmentString.append(this.garmentSizes(i,Size.xxlg(),garments.get(i).getSizes().get(j).getXxl()));
}
//check xxxlrg
if(garments.get(i).getSizes().get(j).getXxxl() >0)
{
garmentString.append(this.garmentSizes(i,Size.xxxlg(),garments.get(i).getSizes().get(j).getXxxl()));
}
}
}
}
This is my garmentSizes function:
public String garmentSizes(int garmentNumber, String size,int numberToSend)
{
String garmentSizes = "&garment["+garmentNumber+"][sizes]["+size+"]="+numberToSend;
return garmentSizes;
}
I'm trying to figure out how I can get this done with a lot less code. I've read that with functional programming you can do things like pass in functions to parameters to other functions. After doing some reading online, I think I want to do something like this but I'm not sure how or what the best approach would be.
I have done some reading here on stack overflow and I've seen people mention using either the Command pattern or FunctionalJava or LambdaJ for trying to approximate this feature in Java. I've read over the documentation for the two libraries and read the Wikipedia Article on the Command Pattern, but I'm still not sure how I would use any of those to solve my particular problem. Can somebody explain this to me? As somebody that has never done any functional programming this is a bit confusing.
You could use local variables to decrease the amount of repetition. Say bySize = garments.get(i).getSizes().get(j) for example.
instead of size.getXxsml(), size.getXsml() etc. you could use an enum for sizes and loop on sizes.
The whole thing would then look like:
for(int j=0;j<garments.get(i).getSizes().size();j++) {
bySize = garments.get(i).getSizes().get(j);
for (Size s : Size.values()) {
if (bySize.get(s) > 0) {
garmentString.append(garmentSizes(i, s, bySize.get(s)));
}
}
}
The bySize.get(s) method could be implemented either with a switch that directs to the right method or directly in the enum and you could get rid of the getXsml etc. methods.
The only thing which differs between all your checks is this:
getXxsml/xxsml, getXsml/xsml, getSml/sml, etc.
If you could pass these values (as strings) to some upper-level method, and if
that upper-level method could eval i.e. execute these strings, then you can just
have an array of these values and pass that array to that upper-level method.
In Java, you can do something similar with reflection.
All these checks could indeed be simplified to much less
code through the use of reflection.
Look at:
java.lang.Class
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Constructor
and you will see what I mean.
From your code it appears that some Class has the following methods:
xxsml(), xsml(), sml(), med(), ..., xxxlg()
to get the amounts (?) available for each size.
You can design your data better, like this:
Have a "Size" type, that enumerates all sizes (could be Enum or some class with attribute String key)
Have a method that returns a List of all known sizes.
replace the above methods with amountFor(Size) This could be backed by a Map<Size, Integer>
For backward compatibility, you could rewrite the old methods along the lines:
int xxsml() {
return amountFor(Size.XXSML); // assuming you have a singleton instance
// for each well known size
}
Of course, in getGarmentString, you would then loop through the List of all known sizes:
for (Size sz : Size.getAllKnownSizes()) {
if (garments.get(i).getSizes().get(j).amountFor(sz) > 0) {
... do whatever must be done here
}
}
I'm looking for a design pattern or even advice on some code that I saw the other day. The general structure is this (pseudo code):
public String getUrl(){
Person person= new Person();
StringBuilder builder = new StringBuilder();
if(person.getName() != null){
builder.append(",_name=");
builder.append(person.getName());
}
if(person.getLastName() != null){
builder.append(",_lastName=");
builder.append(person.getName());
}
if(person.getPostCode() != null){
builder.append(",_postCode=");
builder.append(person.getPostCode());
}
// So on and so forth
return builder.toString();
}
Now the problem is that I don't have control over Person class (I'm just given it via an API call). I was thinking to use reflection and a map like so:
Map<String, String> methodNameToUrlParameter; //Pre Build this map with method name and the actual parameter key
Map<String, String> urlParameterToValue;
Method[] methods = person.getMethods();
for(Method method: methods ){
String result = (String) method.invoke(person, null);
if(result != null){
String urlParam = methodNameToUrlParameter.get(method.getName());
urlToValue.put(urlParam, result );
}
}
Then I can go on my merry way. But this doesn't seem too great to me and I don't really know all too much about reflection, any ideas? Remember, I have no control over the Person class and it just has getters since it's immutable.
Thanks.
Edit:
What I am asking is there a better way to represent the flow of logic here with out using a too many if statements that do null checks. Perhaps a design pattern that I do not know about.
2nd Edit:
There's maybe like 20 if-null checks, which made things ugly. Is there a way todo it without none?
Use either Apache Commons ToStringBuilder or Guava's MoreObjects.ToStringHelper. Or get inspired by them.
For a minor change with better readability, you could pull the redundant code into its own method:
void AddField(StringBuilder builder, String value, String fieldName) {
if (value != null) {
builder.append(",_");
builder.append(fieldName);
builder.append("=");
builder.append(value);
}
}
which would simplify your code sample to the following:
public String getUrl(){
Person person= new Person();
StringBuilder builder = new StringBuilder();
AddField(builder, person.getName(), "name");
AddField(builder, person.getLastName(), "lastName");
AddField(builder, person.getPostCode(), "postCode");
// So on and so forth
return builder.toString();
}
I keep on copy-pasting the following in my programs. I'm wondering if anyone of you uses similar code, perhaps in a library to achieve the same.
#Override
public String toString() {
String ret = prefix;
boolean first = true;
for (Component child : children) {
if (!first) {
ret += " " + separator + " ";
} else {
first = false;
}
ret += child.getName();
}
return ret + postfix;
}
PS: One could use StringBuilder instead of String. Got that.
Apache commons provides a number of join methods in the StringUtils class.
This page also has a lot of interesting suggestions on the best way to implement such a method: http://snippets.dzone.com/posts/show/91
Nope. The only thing I can think of is it abstract that " " away into a final field in the toString() function. The reason that we don't have anything nicer is because the foreach construct doesn't care about the position, only that it will print sequentially.
That being said, avoid copy and paste at all costs. Make your own library if need be. Allow it to take a parameter of an interface which indicates if it is the first, and go from there.