Using Java reflection:
How can I get all the methods of a given object (private, protected, public etc)
And perhaps create a structural representation of the class
And finally, serialize the object into String or byte array
Does this idea look sound? or this won't get me anywhere?
What I'm trying to achieve is to be able to:
Serialize any java.lang.Object into byte array or String
Class / Objects that don't implement Serializable will be thrown into my application for serialization
Sounds complicated. Just use XStream.
String xml = new XStream().toXML(whatever);
Question 1: How to get all methods of a class.
getDeclaredMethods will provide you with access to all of the methods on a class.
Returns an array of Method objects reflecting all the methods declared
by the class or interface represented by this Class object. This
includes public, protected, default (package) access, and private
methods, but excludes inherited methods.
Example: Method[] methods = Integer.class.getDeclaredMethods();
Question 2: Create a Structural Representation of a Class
I'm not sure why you would need to do this since it already exists. You can always retrieve an object's class, which provides you with its structure.
To get all methods and fields for a class, use getDeclaredMethods and getDeclaredFields. I'm not sure if you can use it to re-compose a non serializable class though, and I'm not sure I would either. But maybe you can find some ideas here: How to serialize a non-serializable in Java?
Class.getDeclaredMethods() and Class.getDeclaredFields() return methods and fields with any visibility declared in current class only. These methods do not return inherited stuff. To do this you have to iterate over the class hierarchy and call these methods for each super class, i.e.:
List<Method> methods = new ArrayList<>();
List<Field> fields = new ArrayList<>();
for (Class c = clazz; c != null; c = c.getSuperClass()) {
methods.add(c.getDeclaredMethods());
fields.add(c.getDeclaredFields());
}
Related
I know that an annotation object is created implicitly by the JVM. Also, I know that all objects in java inherit the superclass Object. However, if by reflection you retrieve an annotation object, it doesn't seem to have the methods finalise() and clone() which are defined by the Object class in java. Does an annotation object indeed inherit the Object class? Is there a reason why an annotation object doesn't define those methods?
An example code snippet here:
Class<autobot> jane = autobot.class;
about frank = jane.getAnnotation(about.class);
frank.clone(); // This generates an error
frank.finalize(); // This generates an error
Where "autobot" is an annotated class and "about" is the annotation type.
It does. clone() and finalize() aren't public. This doesn't work either:
Object o = new Object();
o.clone(); // nope
o.finalize(); // nope
It may work on certain classes. For example, this DOES work:
ArrayList<String> o = new ArrayList<String>();
o.clone();
That's simply because class ArrayList itself has overridden the clone() method and made it public. You can override a method and make it more public (you can't make em less public).
The type def of an annotation doesn't make anything more public.
I have a class FTSFor rather I should say java enum which implements MEnum interface and SF interface as follows :
public enum FTSF implements MEnum<FTSF>, SF {
private static final Map<String, FTSF> cmap = MEnum.bCMap(FTSF.class);
.........
so on and so forth
Questions :
1) Since FTSF is a Java enum, that's why it can implement as many classes it want? I am slightly confused since implement keyword is usually used when a class implements an interface.
2) I know that one can pass class as an argument inside a method parameter,so above, when FTSF class is passed inside the bCMap method,i am trying to figure out what does gets passed as an argument inside bCMap method. Is it the class file that gets generated when we compile Java code?
1) Enums, just like any other class, can implement as many interfaces as you like. (I got a bit confused as you asked "why it can implement as many classes as it wants". A class can only implement interfaces, not classes. It can extend only one class. As you clarified in a later comment, both MEnum and SF are interfaces.)
2) When you compile a Java class, called T, the Java compiler creates a single object which is an instance of a generic class Class<T>. This is a special class which holds information about the class you've just written - such as its name, and the set of fields and methods it contains. It's part of a feature called Reflection. In this statement from your question:
private static final Map<String, FTSF> cmap = MEnum.bCMap(FTSF.class);
the expression FTSF.class is a reference to this single instance of class Class<FTSF>. So the method bCMap() is being passed a reference to this object; however, given the context, the most likely reason for passing this argument to the method is not because the method wants to know about the class, but because the class object is being used as a dummy argument to tell the compiler that the generic method bcMap returns a Map<String, FTSF> (instead of, for example, a Map<String, Object>).
1) Java classes can only extend one class, but they can implement as many as they want. It doesnt have to do with FTSF being an enum.
2) It is the Class object that represents the FTFS. You can also get it by calling getClass() as long as you arent in a subclass. It is useful for things like reflection. The documentation for it is here https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
Given, for example, a class like this:
public abstract class AbstractSomething {
public static volatile SingularAttribute<Somefield, AnotherField> myAttribute;
}
how can I get an instance of myAttribute via reflection. There are no implementing classes for AbstractSomething.
EDIT
No, we need an instance of the SingularAttribute<T, S>. And the reason we need to use reflection is becuase these classes are generated and passed into our method as a Class object. We have no way no know which AbstractSomething we are receiving. There are quite a few of them.
EDIT 2
Found out what the issue was. When a Hibernate context is present in the application, the interfaces on the abstract class are replaced with their implementation counterparts when accessing them.
No big deal actually, you can do something like this:
Field field = AbstractSomething.class.getField("myAttribute")
And then you can access it by invoking field.get(null) and field.set(null, value)
The real question is WHY do you want to use reflection, but I guess you have your reasons.
EDIT:
If you have a Class instance in before hand (lets call it classInstance) then you can do
Field field = classInstance.getField("myAttribute")
to get the Field that reificates the field you are looking for... and if you want all fields just invoke the getFields method.
You don't really need a concrete implementation nor an instance of the reificated class in question in order to access the static fields.
No need for reflection. The field belongs to the class, and no matter how many subclasses there are, there is only one instance of the AbstractSomething class, so just:
SingularAttribute<Somefield, AnotherField> attr = AbstractSomething.myAttribute;
If I have a class C which inherits class B and class B inherits class A, then
If I create an object of Class C, is the object of superclasses created?? If yes, how??
How to access the private members of class A??
Does the object of superclass created when object of derived class is created?
No.
The superclass constructor is used to initialize the superclass-defined state of the currebt object, but this does NOT amount to creating an instance of the superclass.
If I have a class C which inherits class B and class B inherits class A, then If I create an object of Class C, is the object of superclass created??
No. See above.
If you create an instance of C, you will have one object whose most-derived type is C. This object will also be an instanceof B, but it may not behave exactly like a regular B due to method overriding in C and other things.
If yes, how??
Moot.
How to access the private members of class A??
You cannot directly access the private members of a superclass from a subclass. That is what the private access modifier means. If you need to access them you need to use them, you either need to create non-private methods in the superclass to do this (e.g. getters and/or setters), or change the members' access.
(An alternative is to use reflection to override the private access modifiers, but you should only use that as a last resort. It is better to fix the superclass code to provide the required access ... or figure out away that the subclass doesn't need access at all.)
yes, the object of super class is created.
You cannot access the private members of your superclass or else they wont be private. you can have protected or public accessor methods in superclass and that could return the value of your private variables. OR, you could use reflection to access the private variables. But that you could use for anything, not only just superclass.
you can not access private variables outside of the class.
to access them,
1. you may make them public or protected but it is not a good idea.
2. you can write getter method for it which is again not a private method,It is good approach.
3. you may use reflection to access it.
provide more information to help you better
It depends on what language you are using. If you are using C++, you may be able to make the sub-class a friend of the super-class and then you could access its public members. If you you use Java, you could use reflection to locate the super object and reflect on that, but it would be more trouble than it would be worth.
Method[] theMethods = myClass.getMethods();
for( Method m : theMethods ){
...
}
Will the array include all the methods of the class? public, private, protected and all inherited?
Will I have access to all of them mainly the private and protected ones?
If not, how can I get all the methods of a class and also have access to all?
The Javadoc makes this pretty clear:
Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from superclasses and superinterfaces.
To get at non-public methods, use getDeclaredMethods.
To get all methods of a class you need to recursively call getDeclaredMethods() on the class and all it's superclasses. Depending on what you want to achive with it you might need to remove duplicates which can occur due to method overloading.
From the API doc:
Returns an array containing Method
objects reflecting all the public
member methods of the class or
interface represented by this Class
object, including those declared by
the class or interface and those
inherited from superclasses and
superinterfaces.
So it gets you only public methods. To get all methods, you have to use getDeclaredMethods() on the class and all its superclasses (via getSuperclass()).
In order to call non-public methods, you can use setAccessible(true) on the Method object (if the security manager allows it).