Java Relection Instance checking for different classes - java

I have method which takes in Class references as arguments something like below:
getConfigModule(Class klass) {
//logic to check the class types
}
We are calling this method from other classes like below:
getConfigModule(ClassA.class);
getConfigModule(ClassB.class);
getConfigModule(ClassC.class);
I need to write some logic in the method to check whether "klass" is of a particular class type or not. For example to check "klass" is of type ClassA and ClassB.

Like ##RannLifshitz mentioned, the most straightforward way is to you if-then-else if or switch approach. If you know there are only 3 options and could bet nothing would be added then it's ok.
For long-term project the enum way could be used.
public enum PossibleClasses {
CLASS_A(ClassA.class), CLASS_B(ClassB.class);
Class klass;
PossibleClasses(Class klass) {
this.klass = klass;
}
static PossibleClasses fromClass(Class desiredClass) {
for (PossibleClasses current:PossibleClasses.values()) {
if (current.klass == desiredClass) {
return current;
}
}
// here you could implement logic regarding class inheritance or something else.
throw new IllegalArgumentException("Uknown class:"+desiredClass);
}
}
Then you compare with enum values instead of Class.
if (PossibleClasses.fromClass(klass) == CLASS_A) {
//do something
}
This will help when you will modify code. For example, if someone calls method with completely new class, he would get infromative exception. Also you could use some standard features for enums such as EnumSet to wite clear code like
// would be a field
private EnumSet<PossibleClasses> commonOption = EnumSet.of(CLASS_A, CLASS_B);
// somewhere inside code
if (commonOption.contains(PossibleClasses.fromClass(klass))) {
// instructions which are common for both classes
}
Again, playing with enums is good idea for long-term project. For startup or education/investigation project most probably you can't get benefits from those additional lines of code.

Use Foo.class.isAssignableFrom(klass) or klass.isAssignableFrom(Foo.class) if by same type you mean the class Foo is a superclass or superinterface of klass or the other way around.
If you want strict equality just use equals method.

Related

is there a way to cast to a type by using a string

I have a string that tells me what I want to cast my object to, Is there a way to cast to that object?
Here is some pseudo code that defines what I would like to do
public TypeToCastTo Cast(T object, String TypeToCastTo) {
switch (TypeToCastTo) {
case "foo":
return (foo)T;
case "otherType":
return (otherType)T;
...
}
}
edit
I wanted to create a game where I can click on a button to purchase something e.g. sword or armour which inherits from worldObject. I figure since I might be returning a weapon or armour class (which both inherit from worldObject) that it would make sense to return a worldObject and then downcast to the correct class (Based off it's name (String)).
edit 2:
As mentioned in the comments this is an XY problem. I was originally trying to make a function that would return the downcast type but in reality that doesn't make sense, since in the case it is used somewhere else, i will need a switch statement to determine what to do with the object anyway (at this point i can cast) so rather than having
public TypeToCastTo Cast(T object, String TypeToCastTo) {
switch (TypeToCastTo) {
case "foo":
return (foo)T;
...
}
}
And using my function to cast the WorldObject, I can have
Method DoingSomethingWithWorldObject(WorldObject T) {
switch(T.typeToCastTo) {
case "foo":
foo temp = (foo)T;
// code using temp
case "other":
other temp = (other)T;
// code using temp
...
}
}
although several people mentioned it was probably wrong the way i was thinking of doing it, Including the answer i have marked correct (Which answered my question even though i was asking the wrong question), The reason i actually understood this was because of a response that was deleted.
As mentioned in the comments, you can do this by using reflection with the Class.cast method:
public Object cast(Object object, String typeToCastTo) {
switch (typeToCastTo) {
case "foo":
return Foo.class.cast(object);
case "otherType":
return OtherType.class.cast(object);
}
}
However the return type of the method needs to be Object as you don't know the actual return type that is encoded in the typeToCastTo parameter.
That is it only makes at least some sense, if you have an instance of Class at hand:
Class<Foo> fooClass = (Class<Foo>) Thread.currentThread().getContextClassLoader().loadClass("my.foo.Foo");
Foo fooObject = foo.cast(object);
But all of this seems rather pointless...
Based on the comments. To invoke a parent class' private method, you don't need to cast:
Object object = new SubFoo();
Method privateFooMethod = Arrays.asList(ParentFoo.class.getDeclaredMethods())
.stream().filter(m -> m.getName().equals("privateFooMethod")).findAny()
.get();
privateFooMethod.setAccessible(true);
privateFooMethod.invoke(object);
But you should really think twice before using reflection to achieve something like this. This very much looks like a bad class/interface design resulting in weird solutions for rather basic needs.
Alternative approach (though I don't know if it's considered bad practice):
public TypeToCastTo Cast(T object, String TypeToCastTo) {
switch (TypeToCastTo) {
case "foo":
return new Foo(object);
case "otherType":
return new OtherType(object);
...
}
}
You'll need specific constructors with corresponding parameters (overloaded) for the different types you'd like to address though. Within those constructors you can control the exact "translations" from one type to another.

Java Method Return Type Specialisation

Suppose I have a collection which stores generic types, e.g.
public class MyCollection<T> {
public T getNext()
{
//Remove T from list
//Return T
}
}
I am using this collection to store subtypes, e.g.
public class NormalPerson extends Human {
public void beNice() { }
}
public class Murderer extends Human {
public void kill() { }
}
...
MyCollection<Human> people = new MyCollection<>();
people.add(new NormalPerson());
people.add(new Murderer());
I would like to call methods specific to each subtype. e.g.
Human person = people.getNext();
switch(person.getType()) {
case NORMAL:
person.beNice(); //Symbol not found
break;
case MURDERER:
person.kill(); //Symbol not found
break;
}
However I can't unless I cast, e.g.
switch(people.getNext().getType()) {
case NORMAL:
NormalPerson person = (NormalPerson)people.getNext();
person.beNice();
break;
Is casting the only way to have this work? Am I going about this the wrong way?
Thanks
If you want a Human to be able to do both actions, you need to declare this in Human.
A simpler approach is to have a generic act method which cause a Person to be nice and a murder to kill. This way the caller doesn't need to know what action the Human will take.
Compiler can only understand reference type. So that when you write Human, compiler will try to look for the method in the Human class which it will not be able to find as it is actually something else which implements Human and the method that is trying to be called is not in the Human itself.
What you can do is you can use instanceof operator to check what type of the object it actually is otherwise casting is the only way to go.
For e.g.
Human h=new Killer();
if(h instanceof Killer)
{
(Killer)h.kill();
}
Hope this helps.
You are going about it in the wrong way. The calling code shouldn't check or even care about the exact type of the object, it should be enough to know that it is s ome kind of Human.
A common way to solve this is to have a more generic name for the method, maybe Human#doAction(), and let each class extending Human define its specialized behavior by overriding that method. This way you can call the same method no matter which Human you have, which greatly simplifies your code.

What is this design (or anti-) pattern and more importantly is there a better way?

I'm receiving from a webservice a list of key-value pairs, and have inherited the following code:
public String iconValue = null;
... (over 50 class variables assigned in MyObject constructor below)
public MyObject(List<Attribute> attrs) {
String attrName, attrValue;
for (Attribute a : attrs) {
try
{
attrName = a.getName();
attrValue = a.getValue();
if (attrValue == null || "".equals(attrValue.trim()))
continue;
if (ICONS.equals(attrName)) {
//Do something including assignment
this.iconValue = attrValue;
}
else if (URL.equals(attrName))
{
//Do something including assignment
}
else if (...) A giant list of over 50 different attributes hardcoded
{
//Do something including assignment
}
...
So,except for keeping a hashmap - is there a better way than the above to keep hard coded variables within the class and use this "when-if" pattern.
Also,does this pattern have a name?
One way I can think about is to use ENUMs and dynamically dispatch the works to each of the ENUM object, instead of doing a huge if else, esp. since ENUMs can be looked up by their names.
That would be like a strategy pattern.
For example:
Implement an ENUM to have a method doJob() for each of the instances;
Use the valueOf() method to dispatch the works.
Code sample:
public enum Strategies {
URL {
#Override
public void doJob(MyObject mo) {
// do the work
}
},
ICONS {
#Override
public void doJob(MyObject mo) {
// another work
}
};
public abstract void doJob(MyObject mo);
}
And when using it,
try {
Strategies.valueOf(attrName).doJob();
} catch (IllegalArgumentException e) {
// ENUM does not exist, illegal parameter
}
If you want to take a different action for each possible value of attribute, you will end up with something about that verbose, I'm afraid. Some improvements though:
If you are using Java7 or above, you can now use switch statements with Strings (link)
If you are not, you could create an Enum that has a static method that returns an Enum element you could switch on. It's no performance improvement, but it might help with readability of your code.
Does this pattern have a name?
Nope.
In Java 7 you can express that as:
switch (attrName) {
case ICONS:
//Do something including assignment
break;
case URL:
//Do something including assignment
break;
// and so on
}
... provided that ICONS, URL and the other strings are compile-time constants.
That is more concise and more robust. It is also (probably) more efficient because the switch can most likely be implemented using hashing.
I don't think it has a name, but you could call it "using polymorphism wrong" (if type safety is a concern). It depends on whether you have a well defined data contract or not. Is the data you're receiving a proper object, or just "random" data?
If it's a proper object I would create a concrete representation and use something like Dozer (or if you don't want to be tied down wit dependency, roll your own mapper using reflection) to convert between them.
If it's more or less random data, I'd just use a Map, or similar data structure.

How to create an object in a utility class based on if statement in Java? (Or based on a particular string)

I would have a string that is parsed into an array, as shown here:
class Example extends ParentClass {
private String[] array;
public static Example parseString(String lineToParse) {
array = lineToParse.split("\");
}
public ObjectType1() { // arguments: String, String, String
}
public ObjectType2() { // arguments: String, String, String, double, double
}
}
What I'm wondering is could I do this?
if (array[0].equals("Test")) {
public ObjectType1()
}
Or is there a better way to do this?
I want to create various objects with different arguments each, and the first argument (array[0]) will be applicable to each object, so I was wondering if I could create objects within an if statement like this, or a switch (not sure if that would work either).
I believe a factory method would be useful for you, one that returns instances of classes according to the parameter received:
// ObjectType1, ObjectType2, ObjectType3 inherit from ObjectType
static ObjectType getInstance(String[] array) {
if (array[0].equals("Test"))
return new ObjectType1(array);
else if (array[0].equals("Test2"))
return new ObjectType2(array);
else
return new ObjectType3(array);
}
For the record, actually you can define a class inside a method, this is valid code in Java ... of course, that's hardly a good thing to do:
// ObjectType1, ObjectType2 inherit from ObjectType
public ObjectType example(String[] array) {
if (array[0].equals("Test")) {
class ObjectType1 {
ObjectType1(String[] array) {
}
}
return new ObjectType1(array);
}
else {
class ObjectType2 {
ObjectType2(String[] array) {
}
}
return new ObjectType2(array);
}
}
"Creating" an object means "instantiating it", with new:
ObjectType1 foo = new ObjectType1(...);
You can do that anywhere it's legal to instantiate a class, including in an if statement.
You cannot define classes in arbitrary locations, however.
If you just want to call a method (which should start with a lower-case letter if you want Java developers to understand what you're trying to do), you can call it from anywhere, including inside if statements.
This sounds like you may want to use a [static factory method][1].
[1]: http://en.m.wikipedia.org/wiki/Factory_method_pattern
I guess that you want to dynamically create objects based on a configuration file?
There are lots of ways to achieve this. One simple way is to use reflection to create the objects. Then you do not need any if/switch statements, and if you want to create a new type of object your code does not need to be changed.
Here are some examples for using reflection: Reflection API Code Samples

abstract method of a set length array in java?

i am trying to create a abstract array method that specify's that this abstract object of an array can only hold 3 items.
Now i have tried doing something like this public abstract BaseAdapter[3] adapters(); but it complains with an error that it cant be done this way.
is their another way or do i need to just do public abstract BaseAdapter[] adapters();?
That will work fine but the sub class can still pass an array larger than 3 items
You could solve it like this:
Create an abstract helper method (which you can override) named createAdapters() with return type BaseAdapter[]
protected abstract BaseAdapter[] createAdapters();
In your super-class you have a final method adapters that does the following:
public final BaseAdapter[] adapters() {
BaseAdapter[] adapters = createAdapters();
if (adapters.length != 3)
throw new Exception("Error: Please return 3 adapters.");
return adapters;
}
Another alternative would be to create a simple class called BaseAdapterTriple (perhaps with a more descriptive name) containing the three BaseAdapters, and use that as return value.
As far as I'm aware there is no way to place restrictions like that on objects in a method signature. Either use exceptions in implementing methods, or use custom classes.
You seem to misunderstand the meaning of the abstract modifier in Java.
abstract applies to classes and methods, not to fields / variables, so what you are trying cannot work.
Please describe what you want to accomplish, then we can help :-).
See e.g. http://download.oracle.com/javase/tutorial/java/IandI/abstract.html for an explanation of abstract.
No, you can't do this neither with arrays nor lists. You can throw an exception if number exceeds 3 and document this behavior.
If you want an adapters() method which can only return 3 BaseAdapter at most and having subclasses to implement the "return" themselves while respecting the 3max contract, you should do the verification in your adapters() method, and invoke an abstract method.
For example :
abstract class YourAbstractClass{
public BaseAdapter[] adapters(){
BaseAdapter[] adapters = internalAdapters();
if(adapters.length > 3){
throw new IllegalStateException();
}
return adapters;
}
protected abstract BaseAdapter[] internalAdapters();
}
aioobe's answer is a good approach to take, but I'd also suggest something a little bit different:
If you are requiring a method to return an array of a certain size, you might want to question why an array is the appropriate return type for this method in the first place, rather than using a simple POJO which can easily encapsulate the idea of "3 BaseAdapters", i.e.:
public class ThreeAdapters {
BaseAdapter getAdapter1() { ...}
BaseAdapter getAdapter2() { ...}
BaseAdapter getAdapter3() { ...}
}
It's a lot clearer to everyone involved if you encapsulate the idea of "return 3 adapters" into it's own class so that this can be used as the return type (of course, you may find a more appropriate name for the class).
In Java, the size of an array is not part of its type. Or to put it another way, all array types with a given base type are the same. Furthermore, you cannot a method signature that places restrictions on the size of an array typed parameter or result.
This means that you are left with the coding the method to test (in your case) the length of the array it is about to return. This is probably not going to help you much, since I assume that you are trying leverage static typing to enforce the "tripleness" of your arrays. From this perspective #matt b's answer is on the money, though you could make do it in a way that still gives you arrays (of length 3):
public class AdapterTriple {
private Adapter[] adapters;
/**
* This constructor may throw an exception
*/
public AdapterTriple(Adapter[] adapters) {
if (adapters.length != 3) {
throw new IllegalArgumentException("array length is wrong");
}
this.adapters = adapters;
}
/**
* This constructor won't throw an exception (apart from Errors)
*/
public AdapterTriple(Adapter adapter1, Adapter adapter2, Adapter adapter3) {
this.adapters = adapters = new Adapters[] {
adapter1, adapter2, adapter3};
}
/**
* #return an array of 3 adapters.
*/
public Adapter[] {
return adapters;
}
}
In summary, you cannot enforce array size constraints statically in Java. You have to do it dynamically, but you can take steps to make runtime errors unlikely.

Categories