This question already has answers here:
How to test whether the value of a Java field gotten by reflection is null?
(4 answers)
Closed 5 years ago.
I have a huge class with members, and i want to check on each member if its null. I don't want to add it manually, just run a for loop (or something similar) which will go over all the fields without 'human' addition every time a field is added.
So far, i can go over the fields, and receive the name of the fields (which is what i need). However, there's nothing on Field that checks if the value of it is null.
Here's what i have so far :
private class Test {
String name1 = null;
String name2 = "test";
String name3 = null;
}
Test mainTest = new Test();
for (Field field : mainTest.getClass().getDeclaredFields()) {
if (field.isValueNull())
Log.i("test", field.getName() + " is missing ");
}
field.isValueNull() -> this is the method i'm looking for.
In this example, the print will be :
name1 is missing
name3 is missing
You can use the get() method of the Field object:
Test mainTest = new Test();
for (Field field : mainTest.getClass().getDeclaredFields()) {
if (field.get(mainTest) == null)
Log.i("test", field.getName() + " is missing ");
}
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
So im writing a Java programming, I have 2 classes, and a class test that uses these 2 classes. running eclipseIDE, it keeps telling me i have a NullPointerException at the "s+=c.getName() + " " +... "
this is a method in Student.
public String getCourses()
{
String s = "";
for(Course c: this.courses)
{
s+=c.getName() + " " + c.getID() + " " + c.getScore(this.id);
s+="\n";
}
return s;
}
it calls this method that is in the Course class.
public String getID()
{
return this.id;
}
i tried only doing getName(); it had no issue, however once i added getID() it became an issue. getName is the same type of code, it returns the "name" of the object as a string.
name and id is "initialized" via a constructor
Stacktrace:
Exception in thread "main" java.lang.NullPointerException
at hw6.Student.getCourses(Student.java:47)
at hw6.CourseStudent_test.main(CourseStudent_test.java:100)
this is the getScore method
public double getScore(String id)
{
int i = 0;
for(; i < this.students.length;i++)
{
if(this.students[i].getID() == id )
{
break;
}
}
return this.scores[i];
}
If the exception is occurring where your stacktrace + question says it is, then one of the elements in courses must be null.
Reasoning:
If the exception was thrown inside one of the Course method calls, then the stacktrace would show that method as the top stack frame.
If one of those 3 calls returned null, you wouldn't get an NPE. You would just get "null" in the resulting concatenation; see String concatenation with Null.
Found the issue, Because of the "For each " loop, when it gets to an Null object, it tries to run the getter methods, however each time it returns null, as there is no "value" for each variable within that object, so i just added a if condition to check if the object is "null"
I have a method:
public void extractStringFromField(Class<?> classToInspect) {
Field[] allFields = classToInspect.getDeclaredFields();
for(Field field : allFields) {
if(field.getType().isAssignableFrom(String.class)) {
System.out.println("Field name: " + field.getName());
// How to get the actual value of the string?!?!
// String strValue = ???
}
}
}
When this runs I get output like:
Field name: java.lang.String
Now how do I extract the actual string value into strValue, using reflection?
It looks like you need a reference to an instance of the class. You would want to call get and pass in the reference, casting the return to a String.
You can use get as follows:
String strValue = (String) field.get (objectReference);
In ideal situations,Class does not hold data. It merely holds the information about the structure and behavior of its instances and Instances of the Classes hold your data to use. So your extractStringFromField method can not extract values unless you pass any instances (from where it will actually extract values).
If the name of the parameter of the reference, you are passing to extract value is instance, then you can easily get what you want like bellow:
String strValue = (String)field.get(instance);
Just usefull example code for reflection fields:
Field[] fields = InsanceName.getDeclaredFields();
for (Field field : fields) { //array for fields names
System.out.println("Fields: " + Modifier.toString(field.getModifiers())); // modyfiers
System.out.println("Fields: " + field.getType().getName()); //type var name
System.out.println("Fields: " + field.getName()); //real var name
field.setAccessible(true); //var readable
System.out.println("Fields: " + field.get(InsanceName)); //get var values
System.out.println("Fields: " + field.toString()); //get "String" values
System.out.println(""); //some space for readable code
}
Just had the same issue. This Thread somewhat helped. Just for reference if somebody else stumbles upon this thread. I used the StringBuilder class to convert so basically:
StringBuilder builder = new StringBuilder();
builder.append(field.get(object))
Which has multiple advantages. One that you do not explicitly cast (which btw. causes problems with primitive types int vs. Integer) but also of being more efficient if you have multiple string operations sequentialy. In time critical code parts.
String strValue = field.getName().toString();
Full code looks like this:
public static void extractStringFromField(Class<?> Login) {
Field[] allFields = Login.getDeclaredFields();
for(Field field : allFields) {
String strValue = field.getName().toString();
// if(field.getType().isAssignableFrom(String.class)) {
System.out.println("Field name: " + strValue);
}
}
This question already has answers here:
I am getting the memory address from an arraylist, need info
(2 answers)
Closed 8 years ago.
Now, I want it to only print what it says, without the memory address as well. How would I achieve that?
public Telefonnummer[] getTelenummer() {
Telefonnummer[] tnummer = new Telefonnummer[nummerarray.size()];
nummerarray.toArray(tnummer);
System.out.println(Arrays.toString(tnummer) );
return tnummer;
}
Is the constructor and:
private static void kundSök() {
System.out.println("...? ");
String namn = keyboard.nextLine();
if (kunderna.containsKey(namn)) {
for (String k : kunderna.keySet()) {
Kund kund = kunderna.get(k);
System.out.println(kund);
System.out.println(kund.getTelenummer());
After i have added a person to the ArrayList etc it gives me an output of:
Sam wasdfgn
[123456: efdg]
[LTelefonnummer;#28d93b30
The last part, memory address bit, is the part I want to get rid of.
Yet again, how do i achieve that?
Edit: I tried to Override, but it did not do anything at all. Could there be another problem?
The default behaviour for toString is to print the type name (as L followed by the type name), followed by # and the hexString of the hashCode (which by default is the memory address for the object).
To change this, override the toString method for your Telefonnummer class.
public class Telefonnummer {
private String nummer;
...
#Override public String toString() {
return "Dial " + nummer + " for a good time";
}
}
Guava library has Joiner which can be used for that. See https://code.google.com/p/guava-libraries/wiki/StringsExplained
String str = Joiner.on(",").join(list);
You also have to have working toString function on class for elements of the list
This question already has answers here:
Running the same JUnit test case multiple time with different data
(9 answers)
Closed 9 years ago.
I need to test a method, eg:
public ObjRet foo(string input)
{
...
return objRet;
}
For the above method, one test case involves input = {null, " ", "", etc} which would return the same default object and there are other test cases
Do I need to have separate test cases for each input (even though I need to validate for same default object)
or can i do something like this,
#Test
void testing()
{
String[] inputs = {null, "", " "};
List<ObjRet> received = new List<ObjRet>();
for(string input : inputs)
received.add(foo(input));
for(ObjRet obj : received)
Assert.assertEquals(obj, default);
}
I just want to make sure that if its a good practice to use for loops for assertions
The JUnitParams library is the perfect way to create the type of parameterized test you're describing. I include it by default with every project because this pattern is so common. See http://code.google.com/p/junitparams/ for the complete documentation (it's so easy it all fits on one page).
With JUnitParams, each String included in the String[] passed to the #Parameters annotation is parsed as a CSV and is split on commas, then leading and trailing whitespace is removed from each token. The number of tokens must also match the number of arguments to the test method. Since you need to include a null, an empty string and a string that consists only of whitespace, you'll need to use a method to provide your parameters as follows:
private static final Object DEFAULT_VALUE = new String("It works!");
private static final Object OTHER_VALUE = new String("It's broken!");
private Object foo(String input) {
Object output = DEFAULT_VALUE;
if(input != null && !"".equals(input.trim())) {
output = OTHER_VALUE;
}
return output;
}
#SuppressWarnings("unused")
private Object[] parameters() {
return $(
new Object[] { null },
new Object[] { "" },
new Object[] { " " }
// ,"Other value"
);
}
#Test
#Parameters(method = "parameters")
public void testing(String input) {
Object obj = foo(input);
assertEquals(obj, DEFAULT_VALUE);
}
The three tests defined in your original question will pass with this example code, but if you uncomment the fourth value ("Other value"), then fourth test will (properly) fail.
I am currently implementing an Annotation that forces the fields to respect a condition through javassist. I would like to check if a field is initialized when it is being read... so, currently, I am getting the classes by loading them when they are loaded by the VM through a Translator.onLoad(ClassPool pool, String className), and using an ExprEditor on each class through overriding the edit(FieldAccess arg) method. Right now, I managed to inject code to check the condition by running the following method inside onLoad :
private void processFields(FieldsAndMethods data) {
final FieldsAndMethods copy = data;
Stack<CtClass> classes = data.getThisClass();
for(CtClass cc : classes ){
try {
cc.instrument(new ExprEditor(){
#Override
public void edit(FieldAccess arg) throws CannotCompileException{
try{
CtField field = arg.getField();
if(copy.getFields().contains(field) &&
field.hasAnnotation(Assertion.class)){
Assertion a =
((Assertion)field.getAnnotation(Assertion.class))
String condition = assertion.value();
String fieldName = field.getName();
String processCondition =
transformCondition(condition, fieldName);
if(arg.isWriter()){
String code = "{if(" + evaledCondition + ")" +
"$proceed($$) ;" +
"else throw new " +
"RuntimeException(\"The assertion " +
condition + " is false.\");}";
arg.replace(code);
}else if (arg.isReader()){
//Here is where I would like to check if the field
//has been initialized...
}
}catch(ClassNotFoundException e){
System.out.println("could not find Annotation " +
Assertion.class.getName() );
}catch(NotFoundException e){
System.out.println("could not find field " +
arg.getFieldName() );
}
}
});
} catch (CannotCompileException e) {
System.out.println("Could not interpret the expression");
System.out.println(e);
}
}
}
private String transformCondition(String condition, String fieldName){
return condition.replace(fieldName, "$1");
}
Could you point me in the right direction for finding out if a field has been initialized? Notice that a field can be either a primitive or not.
Thanks in advance.
Assumptions
I'll assume the following:
By field initialized we are talking about fields that are null.
Primitive types cannot be null so no bother to check them.
The code
This example verification will work for both static and non static fields.
I've also created the code String in several lines for better readability. Being arg a FieldAccess object, you can write the following:
if (arg.isReader() && !arg.getField().getType().isPrimitive()) {
String code = "{ java.lang.Object var = $proceed();"
+ "if(var == null) {"
+ "java.lang.System.out.println(\"not initialized " + arg.getFieldName() + "\");"
+ "}"
+ "$_=var;}";
arg.replace(code);
}
Code Explanation
As you can see, in this small example I've used a few javassist identifiers, for the complete reference about this please read the javassist official tutorial (I'm linking to the section about code modifications).
Here is what each identifier used means:
$proceed() : in the case of a field access this returns the value of the field.
$_ : this is an identifier that is mandatory when editing a FieldAccess in read mode. This token holds the value that will be used to set the field.
With this information it's easy to understand the code's idea:
Put the field value into an auxiliary object named var
Check if the field is null, if so print a warning with the field name
Set the fieldname with the value (either it's null or not);
I guess this already points you to the right direction. But let me know if you need anything else.