I have a java object, an instance of class Object - that's all I know about it. Now I need to create a list of Class-es that took participation in its creation, including its own class, all parent classes, all classes of its properties and methods. For example:
List obj = new ArrayList();
obj.add(new Integer(4));
obj.add(new Foo());
System.out.println(allRelatedClasses(obj));
Should output something like this:
Object, List, Collection, Iterable, Serializable, Cloneable, RandomAccess,
ArrayList, Integer, Foo
Is it possible at all?
The Reflections library can handle quite a bit of that.
In terms of "what took part in its creation", you'll need to pull that out of the bytecode. There are several libraries that can help with this, like ASM and BCEL. If you just need all dependencies, DepFind might be enough.
If you need to limit yourself to what you said, "what's involved in its creation", then you'd only want the classes involved in the ctor and methods the ctor calls.
If a class uses any reflection, however, all bets are off--those types of dependencies are difficult to track down, and it's difficult/impossible to identify what's actually used.
Sure, you can do it using reflection. obj.getClass() returns your own class, obj.getClass().getParent() returns its parent. Then you can call getParent() in loop until you arrive to Object.
The same is with interfaces, fields, methods, annotations. Just do not forget that you should call getDeclaredMethods() and getDeclaredFields() to get all methods and fields including private. And you have to call setAccessible(true) to deal with private members.
1 hour of work and you are done. Go! Good luck.
Related
I have the interface of an object. I don't know if the implementation is serializable or not. Nor Cloneable.
And I don't have getters of object properties, actually, I don't know the properties either.
Can I still clone the object?
I mean, can I do something like:
public void copyMyObject(MyObject myObject){
this.copyOfMyObject = ...//? can I make a deep copy?
}
I guess not...but maybe I am missing something.
Well ... it depends.
You can serialize an object if the object's actual class implements Serializable ... and the rest1. The actual type may be different to the (static) type of the variable where you are getting the object's reference from.
But if not, then you are not missing something. Deep copying an object that doesn't implement its own deep copy methods, getters and setters, or some form of serialization, would involve some extremely nasty coding2.
You are better off designing your classes so that they can be serialized / cloned. Or, so that you don't need to clone them.
Note that there are a few Java classes that would be impossible to clone correctly even by "nasty" means. Examples include Thread, Socket, Class, ClassLoader and some key awt classes. So if your (hypothetical) application design depended on (say) being able to clone a running thread, that design would not be implementable.
1 - Instance fields that are not transient and not null need to be serializable as well. And so on.
2 - For example, you could conceivably make use of abstraction breaking reflection and use of the Unsafe to replicate what the object serialization implementation does under the hood ... without the Serializable type check. It is a bad idea though.
Let's say we have something like this:
public abstract class MyClass {
//Stuff in here
}
public class MyClassA extends MyClass {
private String thingie; //Along with getter/setters, of course
//Other stuff
}
public class MyClassB extends MyClass {
private List<Integer> thingies; //Again, getters and setters to go with
//Other stuff
}
Let's assume we have any number of classes that extend MyClass, each with it's own instance variable of a different type, although some may have the same type. This is an unfortunate necessity. Now, let's assume we have a Collection of MyClass. We have a collection filled with any number of child classes, each with an object contained within. Let's say I need to iterate over this Collection, retrieve said object from any number of elements, and perform actions upon it, store it, manipulate it, send it elsewhere, etc. These objects have nothing in common aside from extending Object.
I might be able to simply delegate these actions into the MyClass children themselves, use a visitor, etc, but this likely isn't feasible as these actions may be dependent upon other MyClass children in the Collection. A single MyClass child likely won't dictate the action to be taken all by itself, or even any single Collection of MyClass. Some of these actions may be cumulative and dependent upon a number of other potential cumulative factors.
Is there any "good" way to handle this, or am I just going to be cursed to the hell of ugly typechecking conditionals or something similar? I considered using Generics in MyClass and using concrete types on all of the children. This could simplify the retrieval of objects, but would still necessitate a large conditional block.
You discarded in your question the "good" way of doing it. Generics will not help in this case. Yes, you are going to be cursed to a nasty place for the ugly use of type checking. You can disguise the type checking using a common instance member called, say, category and its corresponding accessor getCategory defined in MyClass. And them do a switch if you can (instead of multiple ifs) on getCategory(). However, the people who will condemn you could dislike ifs and switches no matter if they are checking for types or not. And they could also be smart and understand what you are trying to do. Anything but
for(MyClass e: collection )
e.doYourAction();
is "bad".
Now, for software that seems to have no specification at all, you could be pardoned.
Is it possible to do something like this in Java?
Object[] objArray = { new Car(), new Human() }
I read that the array elements all have to be the same type but aren't these all of type Object ?
Yes, it's possible but not useful often and always dangerous.
If you want to put some objects into a collection (list or array), the type of the collection must allow for a common ancestor. Since Object is the common ancestor to all OO types in Java, you can put anything into it (and, with Java 6's autoboxing, even primitives).
The problems start when you work with the elements in the list. As long as you only need to call methods which the common ancestor type provides, everything is fine.
But eventually, you will want to call methods of the Car type and that means you'll have to identify the instances in the collection (which is somewhat slow and pretty clumsy in the code) and use casts (always a good sign for bad code).
You're correct, that works perfectly okay even though it's not considered to be good OO practice.
Inheritance is used to define a is-a relationship. Since every class in Java extends java.lang.Object (either directly or indirectly), a Car instance is-a Object instance, and a Human instance is-a Object instance.
So, of course, an array of objects can hold humans, cars, and every other kind of object.
Yes, it's possible to do something like that but its not very OO-like.
Make sure you do an explicit cast when accessing your objects, e.g.
Human h = (Human) objArray[1337];
Have Fun!
Yes, it is possible! Since Object is the upper class of all classes
So in java the way to initialise an interface, such as a collection or list, is to create an instance of a class that implements it, eg:
Collection<Object> moo = new ArrayList();
If I wanted to specify an implementation at a later time in my code, I was thinking of doing this by creating another class like:
class ListList extends ArrayList{
}
and then initialise the variable with
Collection<Object> moo = new ListList();
And then all that's required if I want to change the implementation later on is to change what ListList extends.
So, here's the question.. is there a better way of doing this (I still feel as though I'm inexperienced with this type of thing).
is there a better way of doing this
Yes: use a factory method:
public static Collection<Object> createCollection() {
return new ArrayList<Object>(); // change this later, if need be
}
Then, invoke the factory rather than instantiating:
Collection<Object> moo = createCollection();
Your suggestion of using a "dummy" subclass might appear attractive, but such abuses of inheritance invariably lead to pain and suffering later on. You really don't want to do that.
You could also do it that way
Collection<Object> coll=new ArrayList(){
//bla
};
The basic idea is a good one. Make your variable/field/... an instance of the interface and not of the concrete class you are using. This will force all your code to work against the interface (on the condition that you not start casting somewhere down your code path), and allows to replace the implementation later on with a different class if you feel the need for it.
One can start discussion about how you create that concrete class, like for example using a factory method as #skaffman suggested in his response. However, this might depend on the situation. If it is just for a one-time use like initializing a field you can just create the instance without bothering about factory methods.
I have seen that if I have interface named interfaceABC.
Example:
public class ABController extends AbstractCOntroller {
private interfaceABC inter;
I am confused that why we make object from interface not from class that implemented it.
private interfaceABC inter;
i am confused that why we make object from interface not from class that implemented it
We haven't created an object/instance yet. We simply declared a variable to hold it. We don't make objects from interfaces (you have to use a concrete class to do that), but we will often use interface types instead of the actual concrete class for variable declarations, method parameter types, and method return types.
Take this for exmaple:
List<Example> examples = new ArrayList<Example>();
...
public List<Example> getExamples() { return examples; }
Using the interface List here instead of the concrete class ArrayList follows a common best practice: to use interfaces instead of concrete classes whenever possible, e.g. in variable declarations, parameters types, and method return types. The reason this is considered a best practice is:
Using the interface for declarations and for return types hides an implementation detail, making it easier to modify in the future. For example, we may find that the code works better using a LinkedList rather than ArrayList. We can easily make this change in one place now, just where the list is instantiated. This practice is especially key for method parameter types and method return types, so that external users of the class won't see this implementation detail of your class and are free to change it without affecting their code.
By using the interface, it may be clearer to a future maintainer that this class needs some kind of List, but it does not specifically need an ArrayList. If this class relied on some ArrayList-specific property, i.e. it needs to use an ArrayList method, than using ArrayList<Example> examples = ... instead of List<Example> examples = ... may be a hint that this code relies on something specific to an ArrayList.
It may simplify testing/mocking to use the more abstract List than to use the concrete class ArrayList.
We haven't made an object, we've made a reference.
By using a reference to the interface rather than a concrete class, we are free to swap in a different implementation of the interface, with no changes to this code. This improves encapsulation, and also facilitates e.g. testing (because we can use mock objects). See also dependency injection.
This is actually very useful. Take the example that we're using a list.
public class A {
private List<String> list;
public A(List<String> list) {
this.list = list;
}
}
This allows class A to work with all operations defined by the list interface. The class constructing A can now give any implementation without changing the code of class A, hence promoting encapsulation, code reuse, testing etc. For instance:
new A(new ArrayList<String>());
For a private field, it does not really matter too much, as that's an implementation detail anyway. Many people will still on principle use the interface everywhere they can.
On the other hand, protected fields (and of course the parameters of public methods) form an API that becomes much more flexible by using interfaces, because that allows subclasses/clients to choose which implementation class they want to use, even classes they supply themselves and which didn't even exist when the API was created.
Of course, if you have a public set method or constructor that sets the private field, then you have to use the interface type for the field as well.
Imagine a gift-wrapping stall in a shop that has a machine which will wrap any box.
The machine is simply designed and built to wrap a rectangular box, it shouldn't matter whether there's chocolate in the box or a toy car. If it mattered, the machine would quite obviously be flawed.
But even before you get to that stall, you have to buy that gift: so the cashier scans the barcode first. The barcode scanner is another example of the same principle: it will scan anything as long as it has a recognisable barcode on it. A barcode scanner that only scanned newspapers would be useless.
These observations led to the concept of encapsulation in software design, which you can see in action when a class refers to an object by an interface only, and not its concrete class.