Why the following is possible in Java ?
Integer[] ints = (Integer[])new Comparable[10];
But it gets ClassCastException at runtime. What is the usecase to new an array of an interface.
To answer the specific question:
Comparable toComplare[] = new Comparable[10];
Why not create an array that will allow you to store any object that implements the Comparable interface?!
The point is: the interface denotes a "common functionality" - and it could be helpful to only look at objects from that "view".
Of course, the objects stored in that array are always of some "real" class - but all these objects will implement the functionality that the Comparable interface provides.
So you could do things like:
toCompare[0] = new Integer(5);
toCompare[1] = new BigDecimal("3.2");
...
I am not saying that this is something that you would use frequently, but as said - it allows you to "collect" objects under a certain, specific "view" of their capabilities. It is also worth pointing out: having such an array does not mean that you would be able to do:
toCompare[0].compareTo(toCompare[1]);
successfully!
Beyond that: a cast always implies somehow that you, the programmer know something the compiler doesn't know. So the compiler steps back and lets you do that - assuming you know what you are doing. But as the code you are showing in the question is obviously not correct, reality comes back biting you at runtime. And yes, it would be possible to decide at compile that the given code is incorrect.
Regard this case: You have an interface and two (or more) classes that implement that interface:
interface MyInterface
{
public void someMethod();
}
class MyClass1 implements MyInterface
{
public void someMethod() { System.out.println("foo");}
}
class MyClass2 implements MyInterface
{
public void someMethod() { System.out.println("bar");}
}
And you call it like this:
public static void main(String[] args)
{
MyInterface[] array = new MyInterface[2];
array[0] = new MyClass1();
array[1] = new MyClass2();
array[0].someMethod();
array[1].someMethod();
}
An array of an interface gives you the method of holding different implementations of that interface in an array
The compiler looks at the type of the right side, and sees that it is an array of Comparable. In general, it could be an Integer[] (because that is assignable to Comparable[]).
We know that it will not be an Integer[], because that right-hand expression is a constructor call. But the compiler does not look that far. It uses the same logic as if that expression was a method call with a declared type of Comparable[]. It does not look inside to figure out the actual type.
So the compiler will accept your typecast, because it might succeed. It will only reject casts that cannot work out at all (according to declared types), such as casting Integer to String.
Note that it is probably a design flaw to allow this co-variance in arrays. You can cast Integer[] to Comparable[], but this has problems and for this reasons you cannot cast List<Integer> to List<Comparable>.
Having Integer implement Comparable, doesn't mean Integer[] implements Comparable[], so you can't convert arrays of different type. You can, however, put Integer in element of Comparable[] array.
Reason for ClassCastException is due to Heap Pollution.
Find more details here http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ050
Use case of new to an interface array / just interface is to fill it with any class object which implements that interface (or) give an anonymous inner class definition.
It is because you are performing a Narrowing Reference Conversion
The class Integer implements the Comparable interface:
public final class Integer extends Number implements Comparable<Integer>
see: 5.1.6. Narrowing Reference Conversion
From any array type SC[] to any array type TC[], provided that SC and TC are reference types and there is a narrowing reference conversion from SC to TC.
Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If not, then a ClassCastException is thrown.
Related
I am trying to make a generic Stack class as shown
public class Stack<T> {
public Stack(Class<T[]> type, int capacity) {
this.capacity = capacity;
array = type.cast(Array.newInstance(type,capacity));
}
}
but am unsure of what to put in for type when instantiating since I thought of doing
MyClass[] c = new MyClass[0];
myStack = new Stack<MyClass>(c.getClass(), 100);
however I get the following error of
Required type: Class <MyClass[]>
Provided: Class <capture of ? extends MyClass[]>
so I thought of using
c.getClass().cast()\
but I am unsure of what to put inside of cast() since it won't take
Class<MyClass[]>
now I am stuck.
The overall design of this implementation is brittle. We are mixing two language constructs: arrays and generics. These two constructs differ in two major ways: arrays are covariant and retained, while generics are invariant and erased (see this question by eagertoLearn as to why). Mixing both is a recipe for disaster.
Furthermore, we need the component type to call Array::newInstance. Right now, we pass along the container-type.
I would recommend to use an Object[] as backing data structure and make the accessors generic to guarantee type-safety. This is also the approach taken by ArrayList. This approach will result in (at least) one unchecked cast that cannot be avoided. I leave it to the reader to
find the unchecked cast in ArrayList
argue why the cast is rectified and will never result in an actual ClassCastException as long as the interal array is never leaked.
You can refer to a typed array by adding [] after the class name:
myStack = new Stack<MyClass>(MyClass[].class, 100);
why can we cast from a Super Class down to a Subclass like so:
Object o = getStringObject();
String str = (String) o;
but then use the same principle to cast an interface DOWN to a sub-type E.G.?
InterfaceType anInterface;
anInterface = (InterfaceType) SubClassVar;
so EXAMPLE 1 is all fine and dandy. What i Don't understand is that if an interface is a super-type of a class that implements it, then how do we not have a ClassCastException when we downcast the class to the interface, if within the hierarchy the interface is higher? i read somewhere that there's a difference between casting via classes, and interfaces, but of course they didn't feel like explaining why, so i'm left in the open. Thanks, Stack!
Technically, you up-casted to the interface because it is higher in the hierarchy than the (presumed?) implementer of that interface, SubClassVar. Additionally that cast isn't even needed because implementations of an interface can be talked about in terms of that interface anyway, without cast syntax.
You can downcast an interface just as you did with the subclass. Here is an example:
interface I1 {}
interface I2 extends I1 {}
class I2Impl implements I2 {}
class Main {
public static void main(String[] args) {
I1 test = new I2Impl();
I2 test2 = (I2)test;
I2Impl test3 = (I2Impl) test2;
}
}
When the programmer explicitly cast one type to another, it's usually because the programmer knows more about the runtime type of the object than the compiler. The compiler could choose to allow any cast, because the smart programmer says so. However, being Java, the compiler will try to catch and prevent obvious mistakes.
A cast between two types is not allowed, if it is obvious that no object can belong to the two types at the same time; or in another word, the intersection of the two types is empty. For example, we cannot cast between String and Integer; nor String and Runnable. However, Number and Runnable can be cast to each other, because conceivably there could be an object in both types.
Also, identity comparison a==b is only allowed, if A and B can be cast to each other, for the same rationale. == isn't allowed if the compiler knows they cannot be the same object. see JLS
The exact algorithm is very complicated - http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.5.1 Note that the algorithm is symmetric - A can be cast to B, if and only if B can be cast to A. The text of the spec is not very good and likely contains bugs (see this question )
A "downcast" is when the target type is a subtype; an "upcast" is when the target type is a supertype. Upcasting is usually unnecessary, however there are cases when it is needed.
Trying to learn some basic operations using JAVA-Genric, i tried to make a generic class, which takes a number and does some operation on it and returns the value but its throwing error
Parent class :
public class HelloWorld{
public static void main(String []args){
MathsExec<Integer> my_obj = new MathsExec<Integer>();
int rst = my_obj.doAddition(100);
System.out.println("Solution is : "+rst);
}
}
Generic Class :
class MathsExec<T>{ //didn't extend NUMBER because m strictly sending int values
T doAddition(T nmbr){
int k=100;
T rst;
rst = nmbr+k;
return rst;
}
}
Error :
MathsExec.java:6: error: bad operand types for binary operator '*'
rst = nmbr+k;
^
first type: T
second type: int
where T is a type-variable:
T extends Object declared in class MathsExec 1 error
I understand why this error is coming(incompatible types for operation) but as per generics, type T should have been converted to Integer before doing the + operation...or is there some other explanation i should know????
P.S : please go easy, JAVA is not my strong suite!!
Generic types are not known in compile time. Therefore, you get that compilation error. And it makes sense, because there is no guarantee that your * operator will work on your generic type T.
A trivial but educational solution might be adding an interface called Multipliable and adding the abstract method multiply() to it, than calling that method in your doAddition method. BTW to do that you need to change your class definition as something like
class MathsExec<T extends Multipliable>
Additional clarifications:
We have to come to an understanding that you cannot use operators like * for classes, they are for primitive types only.
If you have to use generics and you have to do some operations on generic types, you have to keep your compiler happy and assure it that that Generic object, does have that method. And that is through T extends SomeClass.
If you want to practice generics without using interfaces or abstract classes or whatever, the most common use case is custom data structures. Where it is possible that you do not actually need many operations on the data that you are storing. You just put them in your structure.
// didn't extend NUMBER because m strictly sending int values
You can do that. int primitives will be boxed to Integer wrapper. But the issue is, arithmetic operators won't work on generic types. There may be workaround, but it wouldn't be worth of your effort. I would rather provide overloaded method for handling different primitive types.
BTW, you should take two arguments in the doAddition() method, and pass the value of k, that you're currently hard-coding. This will allow you to re-use this method in any other class too.
You should do an explicit cast from T to int if you know for sure that T will be casted down to an int. The compiler has no way of knowing if that will actually happen, so it will give you that error.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
Java Generics — Assigning a list of subclass to a list of superclass
With raw types you can easily say something like this.
[...] // MyClass is generic with upper bound of Object
MyClass c = new MyClass<Double>();
[...]
But this isn't allowed
MyClass<Number> c = new MyClass<Double>()
I don't understand why this is. My book tells me why the second doesn't work, because you can't add a Integer to a MyClass<Double>. What it doesn't explains is why MyClass<Double> is a subclass of MyClass<Object> (or the equivalent raw type form), since double is subclass of object.
So why is the first allowed if the second form isn't. Please realize I am new to this.
Edit: Taking it a step further what would happen in the first example if Number was the upper bound?
You can see here the effects of type erasure
class Untitled {
public static void main(String[] args) {
}
public static<T> void c(T t)
{
t.SubClassMethod();// this won't work because class Object has no such method. But if I change the upperbound to SubClass it will.
t.toString() // this will because class Object has such a method
}
}
My point is that why should it matter what the Generic is declared as if it ultimately becomes treated as the upper bound anyway?
Try this:
MyClass<? extends Number> c = new MyClass<Double>();
The first thing to eliminate your confusion is to understand that the Raw Type is not part of the generics system at all. It is in no way equivalent to Something<Object>. Basically, the reason the Raw Type exists at all is just for backward compatibility. When Generics were introduced in Java 5, some existing classes and interfaces were retroactively made generic. In order for old code that didn't have generic declarations to compile in the Java 5 or later compiler, the Raw Declarations are legal.
Any comparison between the way the Raw Type behaves and the way the Parameterized type behaves is in a way a bit fundamentally spurious. The intent of the design is not that the Raw Type be considered an 'alternative' to declaring a parameter. New code that uses the Raw Type is incorrect code. It's legal to compile it so that old code still works.
My point is that why should it matter what the Generic is declared as
if it ultimately becomes treated as the upper bound anyway?
Because the entire point of the generics is to prevent ClassCastException. It will be treated as the actual declared type when someone, for example, someone takes the object back out of the list and assigns it to the specific type they're expecting. The compiler is making a promise that it guarantees this will succeed, so it has to restrict what goes in and out.
Suppose that MyClass is like this:
public class MyClass<T>{
T value;
public void foo(T arg){
value = arg;
}
}
and then those two other classes:
class A{ }
class B extends A { }
now imagine what happens if you do:
MyClass<A> container = new MyClass<B>();
container.foo(new A());
you'd try to put an A into a field of type B. The restriction you are facing is thought to prevent such things. C# has a nifty solution in terms of in and out parameters to generics...
Any MyClass<XXX> is a MyClass, but contrary to what you are saying, MyClass<Double> is not a subclass of MyClass<Object>.
You can find more about it if you search for erasure, like here.
In Objective-C, I could do:
id<HTTPRequestDelegate> delegate;
to say that delegate (a variable of type id) conforms to the HTTPRequestDelegate protocol (or implements the HTTPRequestDelegate interface in Java speak).
That way, whenever I send a message defined by the HTTPRequestDelegate protocol to delegate, the compiler understands that delegate responds.
How do I do this, i.e., duck typing / dynamic typing, in Java?
Duck typing doesn't exist in Java. If a class implements an interface, it must declare that this interface is implemented. It isn't sufficient just to have methods with the same signature as the ones in the interface.
An interface is a type, though, and you may declare a variable of this type. For example:
List<String> myList;
declares a variable myList of type List<String>, where List is an interface.
You may initialize this variable with any object implementing this List interface:
myList = new ArrayList<String>();
But then ArrayList must declare that it implements the List interface (which it does).
//Static typing
HTTPRequestDelegate delegate;
Interface a = new Implementation();
Java has no concept of duck typing. You must cast the instance to a known type.
I'm assuming then that delegate doesn't explicitly implement the interface you want.
You could make a new class that implements the interface and extends the implementing class you want (or has the implementing class and explicitly calls the appropriate method in the interface).
If this isn't what you want, you might be in for a healthy dose of reflection. Take a look at java.lang.reflect.Proxy and InvocationHandler.
If you are looking for a shorthand to avoid explicitly implementing methods for an interface using composition, Java doesn't really provide syntactic support for this. You'll have to be explicit.
If you do want to go the reflection-heavy way (not recommended over extra typing), take a look at Mockito.
Most of the answers given already are correct. If an object implements an interface, then you can use that object anywhere an implementation of that interface is needed. This is the most natural approach given Java's strong typing system.
To keep with the example of List/ArrayList, you can create an ArrayList object and then use it anywhere a List is required -- or, based on the other implemented interfaces, Serializable, Cloneable, Iterable, Collection, or RandomAccess. Considering superclasses, an instance of ArrayList can be used as an AbstractList, AbstractCollection, or a java.lang.Object.
Reflection can be used, along with dynamic proxy objects, to wedge an object with the correct methods into a duck costume. That shifts the type checking to runtime, and there are usually far better reasons to work with the normal typing system than against it.
Because it sounded like fun, here an example of wrapping a non-Duck in a proxy object.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DuckDemo {
public static Duck getDuckProxy(final Object duckLike) {
final InvocationHandler invocationHandler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class<?> actualClass = duckLike.getClass();
String methodName = method.getName();
Class[] parameterTypes = method.getParameterTypes();
Method requested = actualClass.getDeclaredMethod (methodName, parameterTypes);
return requested.invoke(duckLike, args);
}
};
final ClassLoader originalObjectClassLoader = duckLike.getClass().getClassLoader();
Duck woodenDuck = (Duck) Proxy.newProxyInstance(
originalObjectClassLoader,
new Class[] { Duck.class },
invocationHandler
);
return woodenDuck;
}
private interface Duck {
void quack();
};
public static void makeItQuack (Duck duck) {
duck.quack();
}
public static void main (String args[]) {
Object quacksLikeADuck = new Object() {
void quack() {
System.out.println ("Quack!");
}
};
// Does not compile -- makeItQuack(DuckDemo.Duck) [...] cannot be applied to (java.lang.Object)
// makeItQuack (quacksLikeADuck);
// Runtime java.lang.ClassCastException: [...] cannot be cast to GenericProxyFactory$Duck
// makeItQuack ((Duck)quacksLikeADuck);
Duck d = getDuckProxy(quacksLikeADuck);
makeItQuack (d);
}
}
For what it's worth, IBM developerWorks also has a good article on the topic of dynamic proxies.
In Objective-C, the type consists of two parts: 1) An class pointer type (e.g. NSObject *, NSString *, etc); this could also be id, which is a special type that can accept any object pointer and disables static type compiler warnings for calling methods; and 2) optionally, one or more protocols (which are like interfaces in Java) that the object conforms to (e.g. <NSCopying, NSCoding>)
In Java, a reference type is either a class or interface name. (You can only pick one.) There is not so much separation between classes and interfaces.
In your case, your object pointer type is id, which expresses no information, and you specified one interface, HTTPRequestDelegate. This can be equivalently expressed in Java as
HTTPRequestDelegate delegate;
If you had specified more than one protocol, or you specified an actual class pointer type plus one or more protocols, then your type is an "intersection type", the intersection of the multiple types you specified. In that case, it would be harder because there is no simple way of expressing intersection types in Java. (Although intersection types can be specified in generic type bounds, e.g. class Foo<T extends Collection & Comparable & CharSequence>)
Other than that, the only other difference between Objective-C and Java is that in Objective-C, you can send any message (i.e. call any method) on an object pointer and it is allowed, even if the static type of the variable does not indicate that it is supported (the compiler will give a warning if you use an actual class pointer type; if you use id it will not give a warning). I guess this is the dynamic typing you're talking about. Whereas in Java, you can only call methods that are known to be supported by the static type at compile time.
But if you're using a type like id<HTTPRequestDelegate>, then chances are that you only intend to use the methods provided by HTTPRequestDelegate anyway, so you are not using any of the dynamic typing abilities. So in Java just HTTPRequestDelegate will suffice.
I think there's a lot of terminology to unpack here. Java doesn't let you have a raw pointer, only a reference, which has a type.
Anyway, say you have a reference to an instance that you know implements HTTPRequestDelegate. You can cast it, like so:
HTTPRequestDelegate delegate = (HTTPRequestDelegate) ref;
The bit in the parentheses is the cast. You can now call methods on delegate (pass messages in java speak) to your hearts content as long as they are defined on HTTPRequestDelegate.
The other way Java programmers do duck typing type stuff is refection, but if you know the interface, casing is the way to go.