I use a class that makes my Hibernate Query through a FilterCriterionList (sort of finder) and it's always worked perfectly until now and triggers a NullPointerException and I have absolutely no idea as to why it's triggered.
This is the method (in ReflectionUtil) that triggers the nullpointer with the following values (mind you that the other values thrown at it work perfectly and it's just these that seem to give an error):
type = interface java.util.List
fieldName = parameter
First it throws the NoSuchFieldException and on it's second run (as it's called again at field = getField(type.getSuperclass(), fieldName);) makes it throw a NullPointerException and just stop dead (all of this happens in my UnitTest, not a live environment yet).
public static Field getField(Class type, String fieldName) {
Field field = null;
try {
field = type.getDeclaredField(fieldName);
} catch (Exception e) {
if (!type.equals(Object.class)) {
field = getField(type.getSuperclass(), fieldName);
}
}
return field;
}
Any ideas as to why this happens (or what I can do to fix it?). I can't really show off more code as it's quite complicated and it's company code.
java.util.List is an interface, therefore calling getSuperclass() on it results in null.
The correct way to apply getField() recursively is the following:
} catch (Exception e) {
Class superclass = type.getSuperclass();
if (superclass != null) {
field = getField(superclass, fieldName);
}
}
You called like this:
getField(List.class, "parameter");
It would have never worked as List is an interface and it doesen't have any field called parameter. For the second call, its' null because interface List doesnet have a superclass.
From the Class.getSuperclass documentation
Returns the Class representing the
superclass of the entity (class,
interface, primitive type or void)
represented by this Class. If this
Class represents either the Object
class, an interface, a primitive type,
or void, then null is returned. If
this object represents an array class
then the Class object representing the
Object class is returned.
Related
Consider the following program
class A implements Cloneable {
String str = null;
public void set(String str)
{
this.str = str;
}
#Override
public A clone()
{
A a = null;
try {
a = (A) super.clone();
if(a.str!=null) {
System.out.println(a.str);
}
else {
System.out.println("null");
}
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return a;
}
public static void main (String args[])
{
A a = new A();
a.set("1234");
A b = a.clone();
}
}
Why output of above program is 1234 and not null.
I was expecting null, because of following understanding of mine.
super.clone() method will create a new object of parent type (Object in this case) in which attributes of parent class will be shallow copied.
When we do downcasting in our clone() method, then attributes defined in child class will get initialised with their default values, since this is a new object.
But after looking at the output, it seems like attribute values of current instance of child class (this) are getting copied to newly contructed object (after calling clone of parent class and downcasting).
Can someone please tell what is going on when we are downcasting?
1234 is the correct result... Let's see why:
Create a new A instance:
A a = new A();
Set value to A.str
a.set("1234");
Clone a
A b = a.clone();
First of all, note, we're using clone() method from instance a, so let's go there:
#Override
public A clone()
{
// create a NEW instance, it does not set a to null!!!
// to reference the caller (a.clone in main)
// you must use this keyword i.e: this.str = null
A a = null;
try {
// call Cloneable::clone() method
a = (A) super.clone();
// now a is filled with data of this instance so print 1234
if(a.str!=null) {
System.out.println(a.str);
}
// unused code in this case
else {
System.out.println("null");
}
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// return cloned instance
return a;
}
From the Object#clone documentation.
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression:
x.clone() != x
will be true, and that the expression:
x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the case that:
x.clone().equals(x)
will be true, this is not an absolute requirement.
As you can see, the typical case is that X.equals(XClone) == true.
This wont be the case for you, as A didn´t override the equals method.
Additonally:
The method clone for class Object performs a specific cloning operation.
[...]
this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
As this documentation states, the native implementation just creates a shallow copy of the object you are trying to clone. Due to that behaviour the correct output is 1234 and not null, as the fields in the class are just assigned to the cloned instance.
super.clone() method will create a new object of parent type (Object
in this case)
No. This is where you are going wrong. Object.clone() will create a new instance of the same runtime class as the runtime class of the object it is called on, which is A, not Object. And it will shallow-copy all of the fields of A in the object it is called on into the new object.
When we do downcasting in our clone() method, then attributes defined
in child class will get initialised with their default values, since
this is a new object.
That doesn't make any sense because casting references will never affect the state of the object that is pointed to. If the object that the reference points to was not already an instance of A, then the cast will throw a ClassCastException. If the cast succeeds then that means the object that the reference points to was already an instance of A, and you are simply pointing to that same object with a different type of reference. You will never get a "new object" with a cast.
Is it possible to get the type of a variable that is declared (but not instantiated) in Java?
for example:
public class Foo {
FooTwo foo2;
FooTwo foo3;
FooThree foo4;
public static void main(String[] args) {
if (foo2.getClass() == foo3.getClass()) {
System.out.println("foo2 is the same type as foo3");
}
if (foo3.getClass() == foo4.getClass()) {
System.out.println("foo3 is the same class as foo4");
}
}
}
With output:
foo2 is the same type as foo3
obviously the method getClass() does not work on an uninstantiated variable, so this code does not function. I am assuming that the information I am looking for is stored somewhere in the variable (pointer?) for type safety, and that it may be accessible. Is it possible to Achieve this comparison?
the reason:
I have a class with several declared variables. These variables are supposed to point to objects stored in an ArrayList in another class. I am trying to create a method that will take an initialized (but uninstantiated) variable as a parameter, scan the arraylist for an object matching the type of the initialized variable, and set the variable to the object (Make the variable point to the object).
ALSO: The point of the system is to remove coupling in the constructor of the class. The objects cannot be instantiated immediately or in the constructor.
To start with, you need to be aware of the difference between the type of an expression and the runtime-type of a value. Consider, for example, the following code:
List<String> list = new ArrayList<String>();
System.out.println(list.getClass());
The above code prints class java.util.ArrayList, not java.util.List<java.lang.String>, because getClass() returns the runtime-type of the object that list refers to, not the type of list itself.
So it doesn't make sense to call getClass() on an uninitialized variable, because there's no value for it to return the runtime-type of.
I am trying to create a method that will that will take an initialized (but uninstantiated) variable as a parameter, […] and set the variable to the object (Make the variable point to the object).
Since Java is a pass-by-value language, it doesn't expose a way to modify a variable that is passed in as a parameter. For example, consider this method:
public void doNothing(Object obj) {
obj = "obj";
}
The above method does absolutely nothing. It has a local variable obj, which originally contains whatever reference is passed in, and then is changed to refer to the string "obj" instead; but this change has no effect, because nothing actually uses the local variable obj after that point. In particular, this method does not have any effect on whatever reference was passed in.
The closest you can get is to use reflection; if your method takes an instance of type Field, it can both examine the declared type of the field, and set the field to a value of its choosing.
You can do something similar using reflection. Here is an example code snippet. But may be there is a better way to solve your problem if you explain your use case in a bit more in detail.
import java.lang.reflect.Field;
public class Foo {
static FooTwo foo2;
static FooTwo foo3;
static FooThree foo4;
public static void main(String[] args) {
try {
Field foo2Field = Foo.class.getDeclaredField("foo2");
Field foo3Field = Foo.class.getDeclaredField("foo3");
Field foo4Field = Foo.class.getDeclaredField("foo4");
if (foo2Field.getType().equals(foo2Field.getType())) {
System.out.println("foo2 is the same type as foo3");
}
if (foo3Field.getType().equals(foo4Field.getType())) {
System.out.println("foo3 is the same class as foo4");
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
// TODO handle this if this can happen
} catch (SecurityException e) {
e.printStackTrace();
// TODO handle this appropriately
}
}
}
class FooTwo {
}
class FooThree {
}
See Boolean#TYPE for an example of what I'm referring to.
All of the wrapper classes (Boolean, Double, Integer, etc) have a static Class field associated with them called TYPE. What is the meaning of this?
Specifically, here are a few soft tests:
System.out.println(Boolean.class == Boolean.TYPE);
System.out.println(Boolean.TYPE.isInstance(Boolean.valueOf(true)));
Both evaluate as false. (And as a side note, an .equals comparison is unnecessary since Class does not override equals from Object.)
Both Boolean.class and Boolean.TYPE are Class<Boolean> because they are == comparable without an error. Comparing two objects with differently declared generic types is illegal.
On further inspection, the TYPE fields are retrieved by calling a package-private native method Class#getPrimitiveClass along the lines of the following:
public static final Class<Boolean> TYPE = Class.getPrimitiveClass("boolean");
The comment on the method itself is not particularly informative either. It says it returns the VM's class object for the type which is fairly obvious since it is a native method.
I can't find any documentation on this beyond the Java docs' vague allusion to "representing the primitive type". Is there some kind of use for this field? It's unused in the wrapper classes themselves.
(Edited)
System.out.println(boolean.class == Boolean.TYPE);
Is true.
Also one use is then reflection:
try {
Constructor ctor = Boolean.class.getConstructor(Boolean.class);
} catch (Exception e) {
System.out.println("NoSuchMethodException gets thrown");
}
try {
Constructor ctor = Boolean.class.getConstructor(Boolean.TYPE);
System.out.println(ctor.newInstance(true));
} catch (Exception e) {
// (no exception thrown)
}
And I've found some SO threads that cite that, such as this one. I guess I came from the "wrong end" of Google so-to-speak to not find any results on it.
But considering the existence of the "primitive classes" (boolean.class, int.class etc.) that doesn't really explain the TYPE field existence. Basically it's "just there"? I still don't really get it.
The class representing the primitive type is useful in specifying or examining methods that take or return primitives. For example, if your class has a method that looks like this
class Test {
static int round(float val) {...}
}
and you wish to access this method through reflection, you would need to do this:
Method round = Test.class.getMethod("round", Float.TYPE);
You can examine the return type, too:
if (round.getReturnType == Integer.TYPE) {
System.out.println("Method 'round' returns an int.");
}
Using Float.class instead
Method round = Test.class.getMethod("round", Float.class);
would not work, because that would pull a different method - this one:
static int round(Float val) {...}
(Don't have the rep to comment, so must answer.)
To put it succinctly: Float.TYPE == float.class, and Float.class != float.class. Consider:
class Test {
void func() {
Class clazz;
// The two statements do the same thing. On my system, they even compile
// to the same bytecode.
clazz = Integer.TYPE; // explicitly asking for this
clazz = int.class; // must yield the same object as above.
// Both of these below are valid, as the `true' is autoboxed. In
// Java < 1.5, both had to be explicitly boxed
Test.class.getMethod("test", Boolean.class).invoke(this, true);
// calls method A
Test.class.getMethod("test", boolean.class).invoke(this, true);
// calls method B. Could also use getMethod("test", Boolean.TYPE)
}
void test(Boolean b) { System.out.println("Method A"); }
void test(boolean b) { System.out.println("Method B"); }
}
I would assume both int.class andInteger.TYPE have been around from the beginning of Java, though I may be wrong. Integer.TYPE can be initially assigned with Class.getPrimitiveClass("int").
I'm trying to build a generic class loader. I need to check classes that I load against a method argument to determine if they are of the same class.
The code mostly explains what I'm trying to do.
private static LinkedList<Object> loadObjectsInDirectory(Class class0, File dir) throws ClassNotFoundException {
LinkedList<Feature> objects = new LinkedList<Object>();
ClassLoader cl = new GenericClassLoader();
for(String s : dir.list()) {
Class class1 = cl.loadClass(s);
try {
Object x = class1.newInstance();
if (x instanceof (!!! class0 !!!) ) {
objects.add(x);
}
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
}
}
return objects;
}
How is this achieved?
Looks like you need the isAssignableFrom method
if (kelass.isAssignableFrom(klass)) {
objects.add(x);
}
JavaDoc
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.
Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion or via a widening reference conversion. See The Java Language Specification, sections 5.1.1 and 5.1.4 , for details.
public static <A, B> B convert(A instance,
Class<B> targetClass) throws Exception {
B target = (B)targetClass.newInstance();
for (Field targetField : targetClass.getDeclaredFields()) {
targetField.setAccessible(true);
Field field =
instance.getClass().getDeclaredField(targetField.getName());
field.setAccessible(true);
targetField.set(target, field.get(instance));
}
return target;
}
Above is the code I get from forum, When I try to reflect an single type object it works, but when I try on the complex type which mean inside ClassA I got ClassB object, I got the java.lang.NoSuchFieldException. Can anyone help me?
You have two different classes, with, most likely, different set of fields.
So if your Class A doesn't have the same fields as your class B, then the exception is thrown.
I'd suggest using BeanUtils.copyProperties(source, target) from apache commons-beanutils. You just create the second object yourself, and pass it to the method. It will not throw an exception if fields differ.
What is your ultimate goal with this piece of code?
Two suggestion:
(1) You can drop the downcast at the first line of the method:
B target = targetClass.newInstance();
(2) Add a try catch so that you can see the name of the missing field. This will help you sort out the issue you're having:
Field field = null;
try {
field = instance.getClass().getDeclaredField(targetField.getName());
}
catch(NoSuchFieldException e) {
throw new RuntimeException("Didn't find field named '" + targetField.getName() + "'");
}
...
Another answer.
If I understand your comment correctly it seems that you have inner classes: Class B (Target) is a class that is defined inside class A. Something like this:
class A {
int n;
class B {
int n;
}
}
Although these two classes seem to have the same fields, and therefore - should not inude a field not found error - they are not.
Inner classes (unless they are defined as static) has a hidden field inserted by the compiler. This field is of the type of the outer class and points to the object that created the inner class object. When using reflection this field is exposed. As A does not have such field, an exception is raised.