My understanding is that every class in Java is a child of the Object superclass. Why, therefore, is it my compiler giving me errors for the following code:
public class ClassA {
public ClassA(){}
public String exampleMethod(String str){
//manipulate string
return str;
}
}
public class ClassB {
public ClassB(){}
public String exampleMethod(String str){
//manipulate string
return str;
}
}
public class Manager {
public Manager(){
execute(new ClassA());
execute(new ClassB());
}
public void execute(Object o){
o.exampleMethod("test");
}
}
If ClassA is a child of Object, why can I not call methods from the 'o' variable? I'm aware that I could just put ClassA & ClassB under a superclass, but I want to know why this fails.
Because Object class has not defined exampleMethod method, thus giving you errors. You should at least do a downcasting o ClassA or ClassB class to execute your code:
public void execute(Object o) {
//this makes the code compiles
((ClassA)o).exampleMethod("test");
}
Still, you have to make sure that the o parameter is an ClassA or ClassB instance before doing this downcasting or you could met the ClassCastException exception. You can achieve this by using instanceof:
public void execute(Object o) {
//this makes the code compiles
//and assures that you won't have a ClassCastException
if (o instanceof ClassA) {
((A)o).exampleMethod("test");
}
if (o instanceof ClassB) {
((B)o).exampleMethod("test");
}
}
Still, this is pretty clumsy. Since ClassA and ClassB classes shares a method with the same signature (same name, same parameters, same return type), you can use an interface that has this method and make ClassA and ClassB classes to implement it. For example:
interface IExample {
String exampleMethod(String str);
}
public class ClassA implements IExample {
//current implementation...
}
public class ClassB implements IExample {
//current implementation...
}
Then you can shorten the code in your Manager class to:
public void execute(Object o) {
if (o instanceof IExample) {
((IExample)o).exampleMethod("test");
}
}
Or even better:
public void execute(IExample o) {
o.exampleMethod("test");
}
This way you can pass an instance of ClassA or ClassB to the execute method and it will behave depending on the implementation that each class gave to the exampleMethod.
Actually, in some looser typed languages your approach would work. In Java you will need to modify the execute() method to something like:
public class Manager {
...
public void execute(Object o){
if (o instanceof ClassA) {
((ClassA) o).exampleMethod("test");
} else if (o instanceof ClassB) {
((ClassB) o).exampleMethod("test");
}
}
}
You approach fails because the class Object does not have a method called exampleMethod().
What would happen if you give e.g. Number to the method?
Unless you don't cast your object to A/B. The reference will remain be of Object class and Object class does not contain any method called exampleMethod(String str). Hence you need to cast it to the classes which have implemented the exampleMethod. You cna do something like this:
public void execute(Object o) {
if (o instanceof A) {
((A)o).exampleMethod("test");
}
if (o instanceof B) {
((B)o).exampleMethod("test");
}
}
Related
Essentially what I want to do is pass a class as a parameter so that I can preform an instanceof comparison.
public class MyClass
{
Object o = something;
public void myMethod(Class c)
{
if(o instanceof c)
{
do something
}
}
}
Where the parameter Class c is any class that I choose to pass in from else where. Essentially I want to be able to pass in any class and make a comparison.
Any help would be appreciated.
Thanks
You can call Class#isInstance(Object obj):
if(c.isInstance(o)) {
Determines if the specified Object is assignment-compatible with the object represented by this Class. This method is the dynamic equivalent of the Java language instanceof operator.
Just let the method accept Object. In Java all classes extend from Object.
public class MyClass
{
Object o = something;
public void myMethod(Object c)
{
if(o.isInstance(c))
{
do something
}
}
}
I am confused to undrestand when we should pass a class as an argument instead of its instance.
for example:
myMethod(classA.class);
Could you make an example of when and how we should pass a class as an argument?
A classic example is when creating an instance of a class through reflection:
//avoiding exception handling, leave that up to you
static <T> T make(Class<T> clazz) {
return clazz.newInstance();
}
//...
A a = make(A.class);
Also, when you want to make sure at compile time that some references belong to a specific class, as used in Collections#checkedXxx.
For example,If you want to encapsulate many fields' value to an entity such as the Hibernate framework's method "session.get(Class entityClass,String primaryKey)" .You need to define the entityClass so that Hibernate know how to encapsulate the query result into an entity.
A simple example to use Class as a argument:
public T getInstance(Class<T extends Serializable> clazz) throws Exception
{
// the ParameterType "T extend Serializable" means that:
// the argument clazz must be a sub of the Interface Serializable
if(null != clazz)
{
return clazz.newInstacne();
}
return null;
}
Lets consider that we have some Creator
abstract class Creator<T>
{
Creator(Class<T> c)
{
this.c = c;
}
T addMainElement(Object obj)
{
return c.cast(this);
}
private Class<T> c;
}
And some wrapper
class CreatorWrapper extends Creator<CreatorWrapper>
{
CreatorWrapper() {
super(CreatorWrapper.class);
}
CreatorWrapper addMinorElement(Object obj)
{
return this;
}
}
The main advantage of doing this that way is that we can use our creator like that
CreatorWrapper creator = new CreatorWrapper()
.addMainElement(someObj1)
.addMinorElement(someObj2);
We won't be able to do this if base class have no knowledge about child class.
And we won't be disturbed by "Unchecked cast from main.Creator to T" warning as we will be if we cast like that
return (T)this;
See Java Class.cast() vs. cast operator
Silly example:
public class PassClassExample {
public static class ClassValidator {
private Class theClass;
public ClassValidator(Class theClass) {
this.theClass = theClass;
}
public boolean instanceOf(Class someClass) {
return theClass == someClass;
}
}
public static void main (String [] args ) {
ClassValidator personValidator = new ClassValidator(Person.class);
Person you = new Person();
Animal me = new Animal();
System.out.println(personValidator.instanceOf(you.getClass()));
System.out.println(personValidator.instanceOf(me.getClass()));
}
public static class Person {
}
public static class Animal {
}
}
Will print out
true
false
Indicating you are a person and I am an animal :)
I have a base class called class Base and two children classes
class A extends Base
and
class B extends Base
I have a method foo in Base.
Rather than putting the implementation of foo in class A and class B, so that I can do
void foo (Object o)
{
// A's implementation
assert o instanceof A;
}
void foo (Object o)
{
// B's implementation
assert o instanceof B;
}
Is there anyway to put foo in Base, and still still be able to check for the runtime class? I've thought of something like this:
void foo (Object o)
{
// Check that o is instanceof a runtime class
assert o instanceof this.getClass(); // ????
}
Thanks.
You can implement your method like this:
public void foo() {
if (this instanceof A) {
// implementation for A
}
else if (this instanceof B) {
// implementation for B
}
}
But the point of polymorphism is to put the A implementation in A, so that this implementation can use A's private fields to implement the method (same for B, or course).
getClass().isInstance(o)
That said, perhaps you want to constrain the type in a way the compiler can check? Generics can do that:
class Base<T extends Base<B>> {
void foo(T o) { ... }
}
class A extends Base<A> {
#Override void foo(A o) { ... }
}
Then,
new B().foo(new A());
will not compile.
There is class method isAssignableFrom()
getClass().isAssignableFrom(o.getClass())
instanceof will not work since the parameter can not be 'dynamic'.
You could use the isInstance method of Class
void foo (Object o)
{
// Check that o is instanceof a runtime class
assert getClass().isInstance(o);
}
but this has at least one possible problem:
it will result in an AssertionException if this is an instance of a subclass of A and the object is just a direct instance of A!
In Java, you can check the class of an object using the instanceof operator:
object instanceof M
When you have a Class object, it would make sense to write:
object.getClass().isAssignableTo(MyClass.class)
http://www.ralfebert.de/blog/java/isassignablefrom/
I currently am working with a constructor which takes in of type object
I am then testing it's type based on instanceof
Public MyClass (Object obj)
{
if(obj instanceof CusClass1){
CusClass1 myObject = (CusClass1) obj;
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
if(obj instanceof CusClass2){
CusClass2 myObject = (CusClass2) obj;
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
}
Can this be offset to an initalise method called from within the constructor. The major problem is in the casting of the Object. I was always under the impression that repeated code is bad code. Can this be made more elegant?
A much better, more type-safe design would be to create multiple overloaded constructors. You would then not need any casts, and you would make it impossible to construct an object by passing it an object of an inappropriate type.
public MyClass(CusClass1 myObject) {
globalVar1 = myObject.getAttrib1();
globalVar2 = myObject.getAttrib2();
}
public MyClass(CusClass2 myObject) {
globalVar1 = myObject.getAttrib1();
globalVar2 = myObject.getAttrib2();
}
Do CusClass1 and CusClass2 have the same getAttrib1() and getAttrib2() methods? Then consider creating an interface that both these classes implement, and create a constructor that takes an object that implements that interface:
public interface Attribs {
String getAttrib1();
int getAttrib2();
}
public class CusClass1 implements Attribs {
// ...
}
public class CusClass2 implements Attribs {
// ...
}
public class MyClass {
// You can now pass anything that implements interface Attribs
public MyClass(Attribs myObject) {
globalVar1 = myObject.getAttrib1();
globalVar2 = myObject.getAttrib2();
}
}
Create one method for each type of the object instead.
public MyClass(CusClass1 obj) {
field1 = obj.getProperty1();
field2 = obj.getProperty2();
}
public MyClass(CusClass2 obj) {
field1 = obj.getOtherProperty1();
field2 = obj.getOtherProperty2();
}
Do not repeat code and do not cast. Create 2 constructors: one accepts CusClass1, second CusClass2. Implement them separately.
If you can modify CusClass1 and CusClass2, you could create an interface
public interface AttributeProvider {
Object getAttrib1(); // or whatever type getAttrib1 should return
Object getAttrib2();
}
and then ensure that CusClass1 and CusClass2 implement this interface:
public class CusClass1 implements AttributeProvider {
...
}
then you can have a constructor with just that interface:
public MyClass(AttributeProvider myObject) {
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
That way, you won't have to modify MyClass if you create a new CusClass3 which should also be used in MyClass
If your constructor can be modified to accept CusClass1 and CusClass2 rather than Object, then you can follow one of the solutions provided in other answers.
Otherwise, yes, you can use and init method like this:
public class MyClass {
public MyClass (Object obj) {
if (obj instance of CusClass1) {
init((CusClass1) obj);
} else if (obj instanceof CucClass2) {
init((CusClass2) obj);
}
// shared initialization code
}
public void init(CusClass1 obj) {
globalVar1 = obj.getAttrib1();
globaVar2 = obj.getAttrib2();
}
public void init(CusClass2 obj) {
globalVar1 = obj.getAttrib1();
globaVar2 = obj.getAttrib2();
}
}
If you have many such custom classes, it may be better to use reflection and/or annotations (and especially if not all of them are known at compile time, this may be the only solution).
If all the custom classes have the necessary attributes/methods with the same names (like attrib1 and attrib2 in your example), reflection is the easier. All you need is a set of potential class names, and the names of the attributes to query.
If, however, the attribute names may vary, you may consider using annotations to mark the desired source attributes in each class.
Before I look through my generic data structure for a value's index, I'd like to see if it is even an instance of the type this has been parametrized to.
But Eclipse complains when I do this:
#Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
This is the error message:
Cannot perform instanceof check against type parameter E. Use instead its erasure Object since generic type information will be erased at runtime
What is the better way to do it?
The error message says it all. At runtime, the type is gone, there is no way to check for it.
You could catch it by making a factory for your object like this:
public static <T> MyObject<T> createMyObject(Class<T> type) {
return new MyObject<T>(type);
}
And then in the object's constructor store that type, so variable so that your method could look like this:
if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass())) {
return -1;
}
Two options for runtime type checking with generics:
Option 1 - Corrupt your constructor
Let's assume you are overriding indexOf(...), and you want to check the type just for performance, to save yourself iterating the entire collection.
Make a filthy constructor like this:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Then you can use isAssignableFrom to check the type.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Each time you instantiate your object you would have to repeat yourself:
new MyCollection<Apples>(Apples.class);
You might decide it isn't worth it. In the implementation of ArrayList.indexOf(...), they do not check that the type matches.
Option 2 - Let it fail
If you need to use an abstract method that requires your unknown type, then all you really want is for the compiler to stop crying about instanceof. If you have a method like this:
protected abstract void abstractMethod(T element);
You can use it like this:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
You are casting the object to T (your generic type), just to fool the compiler. Your cast does nothing at runtime, but you will still get a ClassCastException when you try to pass the wrong type of object into your abstract method.
NOTE 1: If you are doing additional unchecked casts in your abstract method, your ClassCastExceptions will get caught here. That could be good or bad, so think it through.
NOTE 2: You get a free null check when you use instanceof. Since you can't use it, you may need to check for null with your bare hands.
Old post, but a simple way to do generic instanceOf checking.
public static <T> boolean isInstanceOf(Class<T> clazz, Class<T> targetClass) {
return clazz.isInstance(targetClass);
}
Provided your class extends a class with a generic parameter, you can also get this at runtime via reflection, and then use that for comparison, i.e.
class YourClass extends SomeOtherClass<String>
{
private Class<?> clazz;
public Class<?> getParameterizedClass()
{
if(clazz == null)
{
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
clazz = (Class<?>)pt.getActualTypeArguments()[0];
}
return clazz;
}
}
In the case above, at runtime you will get String.class from getParameterizedClass(), and it caches so you don't get any reflection overhead upon multiple checks. Note that you can get the other parameterized types by index from the ParameterizedType.getActualTypeArguments() method.
I had the same problem and here is my solution (very humble, #george: this time compiling AND working ...).
My probem was inside an abstract class that implements Observer.
The Observable fires method update(...) with Object class that can be any kind of Object.
I only want to handler Objects of type T
The solution is to pass the class to the constructor in order to be able to compare types at runtime.
public abstract class AbstractOne<T> implements Observer {
private Class<T> tClass;
public AbstractOne(Class<T> clazz) {
tClass = clazz;
}
#Override
public void update(Observable o, Object arg) {
if (tClass.isInstance(arg)) {
// Here I am, arg has the type T
foo((T) arg);
}
}
public abstract foo(T t);
}
For the implementation we just have to pass the Class to the constructor
public class OneImpl extends AbstractOne<Rule> {
public OneImpl() {
super(Rule.class);
}
#Override
public void foo(Rule t){
}
}
Or you could catch a failed attempt to cast into E eg.
public int indexOf(Object arg0){
try{
E test=(E)arg0;
return doStuff(test);
}catch(ClassCastException e){
return -1;
}
}
Technically you shouldn't have to, that's the point of generics, so you can do compile-type checking:
public int indexOf(E arg0) {
...
}
but then the #Override may be a problem if you have a class hierarchy. Otherwise see Yishai's answer.
The runtime type of the object is a relatively arbitrary condition to filter on. I suggest keeping such muckiness away from your collection. This is simply achieved by having your collection delegate to a filter passed in a construction.
public interface FilterObject {
boolean isAllowed(Object obj);
}
public class FilterOptimizedList<E> implements List<E> {
private final FilterObject filter;
...
public FilterOptimizedList(FilterObject filter) {
if (filter == null) {
throw NullPointerException();
}
this.filter = filter;
}
...
public int indexOf(Object obj) {
if (!filter.isAllows(obj)) {
return -1;
}
...
}
...
}
final List<String> longStrs = new FilterOptimizedList<String>(
new FilterObject() { public boolean isAllowed(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
String str = (String)str;
return str.length() > = 4;
} else {
return false;
}
}}
);
Let Java determine it and catch the exception bottom line.
public class Behaviour<T> {
public void behave(Object object) {
T typedObject = null;
try { typedObject = (T) object; }
catch (ClassCastException ignored) {}
if (null != typedObject) {
// Do something type-safe with typedObject
}
}
}