Let's say I have a situation as follows:
A class X has a field s of type S.
S is extended by two classes A and B both implementing some same methods/fields that we all know should then be implemented in S but, unfortunately, this is not the case.
Now I want to do something like this:
"A or B" downcast_field;
if(s instanceof A)
downcast_field = (A)s;
else if (s instanceof B)
downcast_field = (B)s;
//do something common for the two cases but that need methods implemented both in A and B
The problem is then having in advance a static type (out of the IFs) that allows me to call such methods.
I guess that due to bad design this is actually impossible and I have to write twice the same code, which is ugly, but perhaps there is a solution that I am not seeing right now.
If you can change A and B, then you can add the same interface to both. That would allow you to give this type to downcast_field and invoke methods.
If you can't change A and B, then you have two options:
You can write A2 and B2. Copy the code from A and B into the new types. That allows you to modify the code (unless you can't control the creation of those types). Alternatively, you could also now create S2 which extends S and put the common code in there and then extend A2/B2 from that.
Create an interface and then two implementations which just delegate the calls to the real type.
In this solution, you can
Wrapper downcast_field;
if(s instanceof A)
downcast_field = new AWrapper( (A)s );
else if (s instanceof B)
downcast_field = new BWrapper( (B)s );
downcast_field.foo();
You can make the two wrappers extend the same type and move common code there.
As far as i understand your situation is the following ?
public class S {
}
public class A extends S {
public void doSomething() {
System.out.println("A is doing something ...");
}
}
public class B extends S {
public void doSomething() {
System.out.println("B is doing something ...");
}
}
actually i think this design is rather bad. if you have a chance to
clean this up you should do this. if this is not an option the following
workaround is possible ... introduce an interface declaring the common API
and wrap your instances using this interface ...
public interface WrapperInterface {
void doSomething();
}
then you might use this like so
public class Main {
public static void main(String[] args) {
WrapperInterface a=wrap(new A());
WrapperInterface b=wrap(new B());
a.doSomething();
b.doSomething();
}
private static WrapperInterface wrap(final S s) {
WrapperInterface downcast_field=null;
if (s instanceof A)
downcast_field = new WrapperInterface() {
#Override
public void doSomething() {
((A) s).doSomething();
}
};
else if (s instanceof B) {
downcast_field = new WrapperInterface() {
#Override
public void doSomething() {
((B) s).doSomething();
}
};
}
return downcast_field;
}
}
I have class Animal and two subclasses Tiger and Eagle. Both of subclasses have hunt method which is pretty much the same. The only difference between them is type of Victims. Method hunt is using generic class Field<T> for seekeing victims. It looks like this:
Tiger
void hunt(){
Field<Cattle> field = new Field<Cattle>();
List<Cattle> list = field.getObjects();
...
Eagle
void hunt(){
Field<Rabbit> field = new Field<Rabbit>();
List<Rabbit> list = field.getObjects();
...
Is there any way to perform something like that?
void hunt(Object type){
Field<type> field = new Field<type>();
List<type> list = field.getObjects();
I know that I can get list full of Object type and use instanceof later, but here we come to second question:
Is it possible to call if( object instanceof instanceOfSomeClass)?
You can use generics to achieve what you want:
public class AnimalsGenerics<E> {
public void Hunt(E prey){
...
}
}
and implement your animals specifying the prey:
public class Tiger extends AnimalsGenerics<Buffalo> {
}
But my personal implementation would be using interfaces to specify what does the animal do, for example: what happens if the animal is not a hunter, for example an herbivorous, would you need to implement your animal class again? follow the principle of leaving the implementation to the interfaces and not the heritance would help you to have a cleaner code, my dessign would be:
To design the behaviour:
public interface CollectFoodBehaviour<E> {
void collectFood(E prey);
}
Class animal would be:
public class Animal<E> {
CollectFoodBehaviour<E> collectFoodBehaviour;
public void goToGetFood(E food){
collectFoodBehaviour.collectFood(food);
}
}
Implementing the hunting behaviour:
public class HuntAnimalsBehaviour<E> implements CollectFoodBehaviour<E> {
#Override
public void collectFood(E prey) {
//implemenet the generic hunting process
}
}
and an animal instance as an example:
public class Dog extends Animal<Rabbit> {
public Dog(){
this.collectFoodBehaviour = new HuntAnimalsBehaviour<Rabbit>();
}
}
Is it possible to call if( object instanceof instanceOfSomeClass)?
No, instanceof tests if an object is an instance of a class, not an instance of an instance (as if the left side is a non-static reference and the right side is static reference); You can, however, not declare your instance
// JButton b = new JButton();
// if (b instanceof Component) can be replced with
if (JButton.class.newInstance() instanceof Component)
// or
if (new JButton() instanceof Component)
if for some odd reason you find this useful.
If I understood correctly, you can use a generic method using following code:
If you pass the object class, not the instance, you can construct a Field instance using the Class passed as parameter.
public class MyAnimal {
public <T> void hunt(Class<T> type) {
Field<T> field = new Field<>();
List<T> list = field.getObjects();
if (type == Cattle.class) {
System.out.println("Type is a Cattle");
} else {
System.out.println("Type is not a Cattle, is a " + type.getName());
}
}
public static void main(String[] args) {
new MyAnimal().hunt(Cattle.class);
new MyAnimal().hunt(new Cattle().getClass());
}
}
About your second question, if you have the Class type, you can ask with a simple: type == MyClass.class.
So, I want to be able to get an instance of a subclass that is being run when it calls a method from the super class. For example, if I had this class:
public class A {
public void aMethod() {
//Here is where I want to see if class B is calling the code
}
}
public class B extends A {
}
public class C {
B b = new B();
b.aMethod();
}
And, like the comment says, I want to check, in aMethod, if class B, the subclass of class A, is calling the code.
As has been pointed out to you, there is almost never a good reason to do this and I agree that you should be using polymorphism instead. However, if you "need" to do this or just want to know how to go about doing something like this, you can use instanceof on this inside of the method:
class A {
public void aMethod() {
if (this instanceof B) {
System.out.println("I'm a B!");
}
}
}
public class B extends A {
public static void main(String[] args) {
B b = new B();
b.aMethod();
}
}
public class A {
public void aMethod() {
if(this.getClass() == B.class){
System.out.println("huhuhuuuuuuuuuuuuuuuuu");
}
}
}
public class B extends A {
}
public class C {
public static void main(String[] args) {
B b = new B();
b.aMethod();
}
}
Check here: How to get the caller class in Java
The 2nd part of the answer from #dystroy is probably a start.
Note that this finds a call at any depth:
for(final StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getClassName().equals(B.class.getName())) {
System.out.println("BINGO");
}
}
If you want to check only a limited depth, don't iterate through all of the array.
This can be useful e.g. if some framework forces you to have a special method or a no-arg constructor to be present, but you don't want any developer to call this method directly. (Yes, it is a hack, but sometimes odd frameworks force you to do odd things). Then you can have an assertion in the unwanted method that just throws an exception if it is called by the wrong corner of your code.
Anyway you should try do avoid things like this if possible.
I have this object which is an instance of a superclass. I want to know which subclass that object really is, so that I can decide what to do with it. There is this getClass() method but it's apparently not used for comparison issues. How can I get the sub-type of my object?
You may have a design flaw if you're trying to do this but instanceof.
public class MainClass {
public static void main(String[] a) {
String s = "Hello";
if (s instanceof java.lang.String) {
System.out.println("is a String");
}
}
}
See Beware of instanceof operator.
Class c = (your super class name).getClass();
if(c.getName == "your sub class name")
take action
public class ExampleClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
Horse hr1 = new Horse();
Horse hr2 = new Horse();
Horse hr3 = new Horse();
Horse hr4 = new Horse();
Set hrSet = new HashSet();
hrSet.add(hr1);
hrSet.add(hr2);
hrSet.add(hr3);
hrSet.add(hr4);
Horse hr;
String hor = "sher_pkg.Horse";
callHorse(hrSet,hor);
}
public static void callHorse(Set xSet,String clsName){
try {
Class hrt = Class.forName(clsName);
Iterator hritr = xSet.iterator();
while(hritr.hasNext()){
exam(hrt.cast(hritr.next()));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void exam(Object obj){ //I want to use exam(Horse hrr)
System.out.println(obj);
}
}
Here the argument for the exam function is an Object. But I want to have the argument be Horse... so what changes must be done in "exam(hrt.cast(hritr.next()))" method call? I don't want to explicitly use the class name Horse in callHorse()... So what am I supposed to do?
Thanks
Note: Code with sequences of "if (x instanceof MyClass) usually indicates that you are not using polymorphism enough. Code can usually be refactored to get rid of the need to test this. But I'll ignore this for the sake of answering the question asked.
You can do what you are trying to do, but not without some code changes. Method overloading cannot do what you need because in Java, method overloading is decided at compile time. Thus, if you have two methods in a class where both methods have the same name, same return type, but different parameter types, then any code invoking this overloaded method must make explicit which one will be invoked. Your current code does this with the types it provides due to the use of explicit casts but the fully dynamic version does not. If method overloading were decided at runtime, then your code would do what you want. But because it is decided at compile time, your code does not compile.
To solve your problem, you can use generics, or you can restructure your code. First I'll introduce a test harness that shows a very simplified version of what you're starting with:
public class Test {
public void test(Object obj) {
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
if (obj instanceof Cow) {
Cow c = (Cow) obj;
noise(c);
}
}
public void noise(Horse h) {
System.out.println("Neigh");
}
public void noise(Cow c) {
System.out.println("Moo");
}
public static void main(String[] args) {
Object o1 = new Horse();
Object o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
class Horse {}
class Cow {}
This code runs and does what you would expect. It prints "Neigh" followed by "Moo".
You are trying to replace
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
with
if (obj instanceof Horse) {
handleNoise(obj, Horse.class);
}
and then adding the method to handle it (simplified):
void handleNoise(Object obj, Class clazz) {
noise(clazz.cast(obj));
}
and as I said before, this doesn't work the overloading of noise is decided at compile time. The compiler sees that you are casting, but does not know at compile time what the type is. So it cannot pick an overloading and compilation fails.
The best way to solve this is by using polymorphism, because polymorphism is decided at runtime. That is, have all of those classes implement some interface and then move the code in question into the individual classes. Here is an example that does this:
public class Test {
public void test(Animal obj) {
obj.noise();
}
public static void main(String[] args) {
Animal o1 = new Horse();
Animal o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
interface Animal {
void noise();
}
class Horse implements Animal {
public void noise() {
System.out.println("Neigh");
}
}
class Cow implements Animal {
public void noise() {
System.out.println("Moo");
}
}
Notice how much simpler the test method is! If you can have each item implement an interface that handles what you call stringProp below, then you can simplify part way:
if (obj instanceof Cust) {
loopOverSet(c.getCustPhonSet());
} else if (obj instanceof Name) {
loopOverSet(c.getCustNameSet());
}
// and so on for the rest...
and then add the method:
void loopOVerSet(Set cxSet) {
if (cxSet != null && cxSet.size() > 0) {
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
((StringProp)cxSetIterator.next()).stringProp();
}
}
}
This assumes that the previously-overloaded methods stringProp have been moved into the individual classes CustPhone and CustName and so on and that these classes all implement some interface which I've called StringProp where this interface defines the method stringProp(). Since this code is using overriding instead of overloading it will be decided at runtime.
You might want to take a look at generics.
public static void callHorse(Set<Horse> xSet) {
Iterator<Horse> hritr = xSet.iterator();
while (hritr.hasNext()) {
exam(hritr.next());
}
}
public static void exam(Horse obj) { //I want to use exam(Horse hrr)
System.out.println(obj);
}
Of course in your example you could always just cast the objects. Why you don’t want to do that is beyond me.
When you say:
exam(Horse hrr)
you're telling the compiler that you want it to check all calls to exam() and make sure that each call provides a Horse object as an argument. However, in callHorse(), you're invoking exam() with a dynamically cast argument, and the compiler has no way to check the argument.
It's possible that you could work around this by using reflection and dynamically invoking the exam() method.
You could explicitly cast in the function call -
try {
Class hrt = Class.forName(clsName);
Iterator hritr = xSet.iterator();
while(hritr.hasNext()){
exam((Horse)hrt.cast(hritr.next()));
}
}
but I'm not really sure what you're trying to achieve here - If you're writing code that explicitly references Horses, why do you need to dynamically determine the class type from a string?
First things first,your set should be using either generics or explicitly defined as only holding Horse Objects.
(final Set xSet<Horse>, final String clsName){
...}
Fix that and you have fixed 90% of the issues.
It looks like your design is wrong for Java, and you can't directly do what you are asking for.
Perhaps you need to reshape your code to use the visitor pattern? Failing that, you need to explain your requirement instead of the solution that you want to use. In that way, we can tell you the proper Java solutions to your requirement.
I'm not sure it's possible or desirable to avoid having a reference to "Horse" in the callHorse method. Judging from the printstacktrace after a ClassNotFoundException, you throw a hard error if the class is not found for some reason.
Couldn't you, for the same reason, just cast to "Horse" and then catch the classcastexception if something in the Set is not a Horse?
Can you explain why it exactly is that you need to pass in the classname instead of the class?
Maybe you can also use method overloading, but I'd have to test this, because I'm not entirely sure what the precedence is in this case.
If you are doing a dynamic cast by using Class.cast() with an argument that you're passing to another function, then at compile time nothing is known about the type that you are passing. This is why you cannot use Horse as the argument type where you define the method, but then call the method using reflection in the way that you are. Your cast does very little except verify that -- as long as you don't get an Exception -- the set you pass in is entirely comprised of members of the Class you pass in the name of.
Note that the Class.cast() method was introduced in Java 5, meaning you have access to Generics if you have access to Class.cast(). Generics can help clean things up although they won't solve the problem you are trying to solve.
Using a Java 5 for loop you can rewrite your loop as follows:
public static void callHorse(Set<?> xSet, String clsName) {
try {
Class<?> hrt = Class.forName(clsName);
for (Object x : xSet) {
exam(hrt.cast(x));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
This version is less cluttered and makes your cast more obvious. You are casting to an entirely arbitrary type. The cast may be to any type as long as the class definition can be loaded from the classpath. Thus, if your exam() method takes an argument of Horse then the compiler knows that it cannot guarantee that the call will succeed and the code fails to compile.
Even if you try overloading, it won't work. That is, if you create the methods:
public static void exam(Object obj) {
System.out.println("Object " + obj);
}
public static void exam(Horse obj) {
System.out.println("Horse " + obj);
}
the exam(Object) method will always be the one invoked. Try it.
The bottom line is that what you're trying to do cannot be done. You need to give us more information about exactly what your goal is before we can help you.
Why not write it like this? What exactly are your requirements?
public static void main(String[] args) {
Set<Horse> horses = new HashSet<Horse>();
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
callHorse(horses);
}
public static void callHorse(Set<Horse> horses) {
for (Horse horse : horses) {
exam(horse);
}
}
public static void exam(Horse horse) {
System.out.println(horse);
}
Depending on what you do in the exam() method, it might also make sense to make it an instance method of Horse, like this:
public static void main(String[] args) {
Set<Horse> horses = new HashSet<Horse>();
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
examineHorses(horses);
}
public static void examineHorses(Set<Horse> horses) {
for (Horse horse : horses) {
horse.examine();
}
}
// in Horse.java
public class Horse {
public void examine() {
System.out.println(this);
}
...
}
Is your real goal to have multiple versions of the exam() method, that take different types as parameters, and dynamically select the version needed at runtime?
You can do this explicitly with reflection. Here's an example program.
import java.lang.reflect.*;
public class Test {
public static void exam( Object o ) {
System.out.println( "Object version called" );
}
public static void exam( Test t ) {
System.out.println( "Test version called" );
}
public static void main (String[] args) {
try {
// Create an instance of Test but reference it as an Object
Object untypedTest = new Test();
// Calling exam directly will invoke the Object version
exam( untypedTest );
// But if we use reflection to select the version of exam
// that takes the desired class name, we can invoke it without
// even explicitly casting
String className = "Test";
Class[] examMethodParams = { Class.forName( className ) };
Method examMethod = Test.class.getMethod( "exam", examMethodParams );
Object[] actualParams = { untypedTest };
examMethod.invoke( null, actualParams );
} catch (Exception e) {
e.printStackTrace();
}
}
}
HI,
After searching through i found that dynamic typecast at runtime can't be performed. So what i was trying to figure out seems to be absurd.
I was trying to reduce the cyclomatic complexity of a method1. I was trying to create a method2 which contains the generalized pattern of the repetition pattern found in method1 and calling the method2 from method1 wherever necessary...
the pattern was like this in the first method..
if (obj instanceof Cust)
{
Cust c = (Cust) obj;
Set cxSet = c.getCustPhonSet();
CustPhon cx;
if (cxSet != null && cxSet.size() > 0)
{
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
cx = (CustPhon) cxSetIterator.next();
this.stringProp(cx);
}
}
//....pattern continues here... CustPhon is replaced by various classes like CustNam etc... Also getCustPhonSet by getCustNamSet etc...
}
so i thought of writing a generalized method for the above pattern like this::
public void dynamicIteration(Set xlSet, String clsName)
{
if (xSet != null && xSet.size() > 0)
{
try{
Class clsinstance = Class.forName(clsName);
Iterator itr = generalSet.iterator();
while(itr.hasNext())
{
this.stringProp(clsinstance.cast(itr.next()));// See this is wrong.. thats y i posted here by using a simple Horse example
}
}catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
Calling method2 from method 1
//process customer email address
Set cxSet = c.getCustPhonSet();
className = "pkg.CustPhon";
dynamicIteration(cxSet,className);
// Similarly for other patterns
By this way i must be able to reduce the cyclomatic complexity
This is what i was trying to do..
Hey i think this would solve the problem. You need to decide upon which object it is, so that u can call the corresponding operation, right???
Since we use the overriding comcepts the very functionality that s required can be achieved.
What is given by Eddie may be the most appropriate solution for this i guess?
YOu override the method in the respective classes so that on calling it goes the corressponding method.
U got it?