i have a bit a weak understanding of those 2 concepts. could you explain to me what is happening in that part of the code?

public class Part5{

	public static void main(String[] args) {
//		Object[] zoo=new Object[4];
//		zoo[0]=new Cat();
		
		Object[] animals=new Object[4];
		animals[0]=new Cat();
		animals[1]=new Dog();
		animals[2]=new Duck();
		animals[3]=new Cow();
		for (int i = 0; i < animals.length; i++) {
			if(i==0)
				((Cat)animals[i]).makeNoise();
			if(i==1)
				((Dog)animals[i]).makeNoise();
			if(i==2)
				((Duck)animals[i]).makeNoise();
			if(i==3)
				((Cow)animals[i]).makeNoise();
		}
		System.out.println("============");
		for (int i = 0; i < animals.length; i++) {
			if(animals[i] instanceof Cat)
				((Cat)animals[i]).makeNoise(); // whats happening here?
			if(animals[i] instanceof Dog)
				((Dog)animals[i]).makeNoise();
			if(animals[i] instanceof Duck)
				((Duck)animals[i]).makeNoise();
			if(animals[i] instanceof  Cow)
				((Cow)animals[i]).makeNoise();
		}
		
		
		
	
		
	}
}


class Cat {
	public void makeNoise(){
		System.out.println("Miyau...");
	}
}
class Dog 
{
	public void makeNoise(){
		System.out.println("HowHow....");
	}
}
class Duck {
	public void makeNoise(){
		System.out.println("GAAGAa.....");
	}
}
class Cow {
	public void makeNoise(){
		System.out.println("Moooooooo......");
	}
}

another question

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		A a=new D();
		a.foo(50); 
		B b=(B)a;
		b.foo(10);
	}
		
	
}
abstract class A{
	final int NUMBER_OF_TIME=100; 
	abstract void foo(int x);
	final void doIt(){ 
		System.out.println("bla");
	}
}
class B extends A{
	@Override
	void foo(int i) {
		System.out.println("B"+i);
	}
}
class D extends B{
	void foo(int t) {
		super.foo(t);  // why do i need to use super. here? what would happen if i didnt?
		System.out.println("D");
	}
}

Recommended Answers

All 9 Replies

1. animals[i is an Object (as far as the compiler knows, because that's how you declared it), and Objects don't have a makeNoise() method. The code checks that this particular Object is in fact a Cat, the uses the cast (Cat) to tell the compiler that this particular reference to animals is actually a reference to a Cat. The compiler says "ok, if you say so..) and now knows that the makeNoise() method is valid. If you get this wrong then there will be an error at runtime when it finds out that animals isn't really a Cat.
2. Class D overrides foo(), so if the code on line 30 just read foo(t) that would call the same method - infinite loop. With super. it calls the version of foo defined in the superclass (B) - which prints "B", then prints "D". Not very useful, but safe.

if(animals[i] instanceof Cat)
  ((Cat)animals[i]).makeNoise();

The if statement here is saying if the Object contained in the Object array animal, at index i, is a Cat object then execute ((Cat)animals[i]).makeNoise(); Because animals is an array of Object, if you try this animals[i].makeNoise(); , you will get an error, because animals will give you an Object, not a Cat, and an Object does not have a makeNoise() method. So you cast the Object to a Cat first, ((Cat)animals[i]).makeNoise();

chaospie:
What you say is basically right, but it hides an important point that can confuse learners. You cabnnot "cast an object". An Object's class is unalterable. What you are casting is the reference. Ie you are saying "this ref to an Object is really a ref to Cat". The object iteself was, and always will be a Cat.

commented: Thanks for the (Cat)animal[i] explanation +0

Thanks for pointing that out James, I'll edit my post.

( I shouldn't be posting before breakfast anyway, my basic Java concepts seem to be away in dreamworld... ) :)

isnt casting creates some sort of conversion?

(double)int
it converts the double to int.
is doing the opposite produces an error because of information lose?
(int)double

is the same principle true to Cat and animal[1]?
(Cat)animal

Good question - the difference is because ints and doubles are primitive types, they are not accessed via a reference, and the cast creates, in effect, a new primitive and performs the conversion to initialise it. Cats and Objects are objects and are accessed by reference variables, and it's these references that are cast in that case.
So, to answer the question, the primitibve and the Object cases are quite different.

Calling String toString() method shows that
the JVM would dynamically identify the objects of cat, Dog, Duck, and Cow since the array stores their references respectively. Therefore neither casting nor the instanceof operator is needed. An Object array may store a reference of any kind of type.

public class Part5{

	public static void main(String[] args) {
		
		Object[] animals=new Object[4];
		animals[0]=new Cat();
		animals[1]=new Dog();
		animals[2]=new Duck();
		animals[3]=new Cow();
		
		for (Object o:animals)
		System.out.println(o);
	}
}


class Cat {
	public String toString(){
		return "Miyau...";
	}
}
class Dog 
{
	public String toString(){
		return "HowHow....";
	}
}
class Duck {
	public String  toString(){
		return "GAAGAa.....";
	}
}
class Cow {
	public String toString(){
		return "Moooooooo......";
	}
}

output:
Miyau...
HowHow....
GAAGAa.....
Moooooooo......

Not sure what point you are trying to make here tong1, but the bald statement "Therefore neither casting nor the instanceof operator is needed" could easily mislead a learner.
toString is a special case because it's one of the very few methods defined for Object, and therefore inherited by every object in Java. Because, and only because, its defined in Object, you don't need to cast.
In the case shown by the O/P the instanceof and cast are necessary, as they are for all but the very few methods defined in Object.

okay, the topic is more or less clear to me. thread is solved. thanks everyone

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.