In Objective-C it is possible to pass a function parameter with type in the form Object<Protocol> which has the meaning "an object of type Object that implements the protocol Protocol". I was wondering whether there is a way to do the same in Java, for instance "an Android View that implements some custom interface" (protocol = java interface).
You can use generics to specify that the parameter implements an interface:
public <T extends Protocol> void foo(T t) { ... }
This can be extended to specify multiple bounds. The type must be a subtype of all the specified types. Object isn't the best example, but here's how you could specify it:
public <T extends Object & Protocol> foo(T t) { ... }
Here's a related tutorial:
Oracle Docs - Bounded Type Parameters
Especially note this paragraph:
To declare a bounded type parameter, list the type parameter's name,
followed by the extends keyword, followed by its upper bound, which in
this example is Number. Note that, in this context, extends is used in
a general sense to mean either "extends" (as in classes) or
"implements" (as in interfaces).
The unexpected part here is that extends is used for interfaces as well.
Note that you can get the desired behaviour without generics as well (see comments below):
public void foo(Protocol p) { ... }
since this allows for any object that is-a Protocol. If you want to specify multiple interfaces with this approach you could for example create a third interface that implements the other two. However, this assumes that you're in control of the classes that should be able to be passed as arguments since you need to implement that interface.
If you're passing a "regular" generic type parameter you simply specify the type directly:
public void foo(Object<Protocol> o) {
// TODO: Implement
}
Related
I have the following interface:
public interface Message<T> {
//some other methods
Class<T> getType();
}
Each implementation is always returning the class of T. For example:
public class StringMessage implements Message<String> {
//other overrides
#Override
Class<String> getType() {
return String.class;
}
}
I would like to make this getType a default method of the interface, but that's not possible since I can't call T.class because of type erasure:
public interface Message<T> {
//some other methods
default Class<T> getType() {
return T.class; //<-- not allowed
}
}
Do you know any trick to avoid having to repeat the return XXX.class on each implementation?
Note that I can't bound T to anything, it must remain unbounded.
Note 1: if the answer is no and well explained, I'll accept it.
Note 2: I found many questions that "sound like this" but are not exactly the same (they usually refer to instances and not to the static interface itself). If you find the right duplicate, don't hesitate to mark it as such and I'll delete it.
Yes. And No. It's complicated.
Before we go down this path, are you sure?
Generally, caring about the <T> in Class<T> is a code smell and means your API design is bad. For example, the T in generics can not represent primitives, but it can represent parameterized types; for example, Stream<List<? extends Foo & Bar>> is fine. An instance of java.lang.Class on the other hand can represent primitives (return int.class;), but cannot represent parameterized types. List<String>.class is not a thing, and there is no instance of j.l.Class that represents "a list of strings". List is as far as it goes.
Generally if you think you want a Class instance what you really wanted is a factory. A factory is the way to abstract away a constructor. Instead of returning a Class<T> this code should probably be wanting a Supplier<T> perhaps or some other interface-of-T that does the job of whatever you're currently using Class<?> for. If you're using that class instance for invoking .getConstructors(), then move that logic into an interface instead. Etcetera.
You've considered all that and still insist.
Generics are erased at runtime, yes, but they still exist in those places where they are part of signatures. In other words, in the extends and implements clauses of class definitions, in the types of fields, and in the parameters and return type of any method definition. The JVM considers these comments (the JVM does not know or care about generics in the slightest, it is purely something javac and editors worry about), but they are available in the class file and therefore you can theoretically at least query it.
But, and this is very important, only the literal thing that is there, at compile (write) time, is available.
So, yes, you CAN retrieve the String bit in public class StringMsg implements Message<String>. But what if you write public class GeneralMsg<T> implements Message<T>? Then all you get is T. What if you write public class ListOfStringsMessage implements Message<List<String>>? You can obtain List<String> here, but that notion cannot be conveyed in terms of a value of type java.lang.Class.
The way to do this, is to use the method .getGenericInterfaces(). But, this is a very low level method that just gets you literally what you asked for: The list of interfaces (with any type params preserved) that the class you invoked this on directly implements. Therefore, you need to write a ton of code. After all, maybe you have this:
class StringMessage implements Message<String> {}
class UnicornStringMessage extends StringMessage {}
or even
interface StringMessage implements Message<String> {}
class MyStringMessage implements StringMessage {}
You need to write lots of code to trawl through the entire class hierarchy. Hence, writing it all out in this answer is a bridge too far. This merely handles the very simplest case, and will fail on all others. So, you need to take this code and expand on it, and add:
Detect a misuse, such as writing class GenericMsg<T> implements Message<T>.
Detect hierarchy usage (or alternatively, disallow it with a proper message, if you prefer that) by way of having an interface that extends Message<Concrete>, and then having a class that implements the subinterface.
Same, but for interface SubIntf<T> implements Message<T> and then having a class Foo implements SubIntf<String>.
Same, but with the class hierarchy: class MyMsg implements Message<String> + class MySubMsg extends MyMsg.
Taking that into consideration:
default Class<T> getType() {
for (Type i : getClass().getGenericInterfaces()) {
if (!(i instanceof ParameterizedType pt)) continue;
if (!pt.getRawType().equals(Message.class)) continue;
Type param = pt.getActualTypeArguments[0];
if (param instanceof Class<?> paramC) return paramC;
}
throw new IllegalArgumentException("Programmer bug: " + getClass() + " must implements Message<ConcreteType>");
}
In case you need to pass an argument of an interface type to a method you could use two impl.
Use a bounded type parameter:
public static <I extends InterfaceObj> void isTrue(boolean expression, I interfaceobj) {
if(!expression){
throw new RunTimeException(interfaceobj);
}}
Otherwise you could use the type of interface :
public static void isTrue(boolean expression, InterfaceObj interfaceobj) {
if(!expression){
throw new RunTimeException(interfaceobj);
}
}
Then if I have a class which implements InterfaceObj I could use it in the first and second example so I don't see the difference, advantadges and disadvantages from one or other.
What is it the difference in each case?
When is it better to use one or other?
I don't see the difference, advantadges and disadvantages from one or
other.
I think you forgot about Collections!
If you have a Collection parameter, that's where the real advantage of bounded type parameters comes into play
In this method you can only pass a List which has instatiated like List<InterfaceObj> list = new ArrayList<InterfaceObj>();
public static void processList(List<InterfaceObj> input){
//...
}
but if you use bounded parameterized generic, you can pass all below lists as inputs
List<InterfaceObj> list = new ArrayList<InterfaceObj>();
List<SubInterfaceObj> list = new ArrayList<SubInterfaceObj>();
List<SubSubInterfaceObj> list = new ArrayList<SubSubInterfaceObj>();
public static void processList(List<? extends InterfaceObj> input){
//...
}
From oracle :
There may be times when you want to restrict the types that can be
used as type arguments in a parameterized type. For example, a method
that operates on numbers might only want to accept instances of Number
or its subclasses. This is what bounded type parameters are for.
Functionally, it is exactly the same thing since with a interface as parameter type, it might also only want to accept instances of Number or its subclasses.
Technically, it is slightly different since compiled classes should be different.
In your case, I would prefer use the raw interface type without wildcard since it's less verbose.
It doesn't mean that bounded type parameters in methods are useless.
It can indeed be useful when you use multiple bound type parameters.
Imagine that your method would accept a parameter at the condition that it belongs both to two specified types : InterfaceObj and OtherInterfaceObj.
With a interface type, to address this need, you should create another interface which extends these two interfaces and you would use it in your method such as :
public static void isTrue(boolean expression, MyTwoInterfacesObj interfaceobj) {
if (!expression) {
throw new RuntimeException();
}
}
With multiple bound type parameters, you don't need to create an additional interface. You can specify it such as :
public static <I extends InterfaceObj & OtherInterfaceObj> void isTrue(boolean expression, I interfaceobj) {
if (!expression) {
throw new RuntimeException();
}
}
With two interfaces, restricting the parameter type on both of them is a little awkward, imagine with three or four interfaces and multiple possible mixes of them.
The difference is that with the first, or typed, version the code in the method can know which exact subtype was passed, but the second version can not.
You would notice the difference more clearly if your methods returned a list of the same type as the parameter. Version one could return List<I> - a list whose type is the same as the parameter's (sub)type, but version two can only return a List<InterfaceObj> whose type is the supertype.
The Generic Methods tutorial has this helpful example:
public <T extends E> boolean addAll(Collection<T> c);
However, [...] the type parameter T is used only once. The return type
doesn't depend on the type parameter, nor does any other argument to
the method (in this case, there simply is only one argument). [...]
If that is the case, one should use wildcards.
The codebase of the project I am working on has a few methods like this:
public <T extends Something> T getThing();
and (not in the same interface)
public <D> void storeData(int id, D data);
Is there any point in having the method type parameter instead of using the bound (Something above, Object below) directly?
(Note that in the former case, all of the few implementations are annotated with #SuppressWarnings("unchecked") and the point could be to hide this warning from the user of the method, but I am not sure this is a laudable achievement.
In the latter case, some implementations use reflection to store instances of different classes differently, but I do not see how this is facilitated by the type parameter.)
There are five different cases of a type parameter appearing only once to consider.
1) Once in return type position:
1.a) Return type is the type variable
public <T extends Something> T getThing();
This should be a red flag: The caller can arbitrarily choose an expected return type and the callee has no way of knowing the chosen type. In other words the implementation can't guarantee the returned value will be of the specified return type unless it (a) never returns, (b) always throws an exception or (c) always returns null. In all of these cases the return type happens to be irrelevant altogether.
(Personally I don't mind methods like these if the code is very "dynamic". I.e. you're running the risk of a class cast exception anyway and the method boundary is still early enough for the exception to be raised. A good example is deserialzation. All parties calling the method have to know and understand this though..)
1.b) Type variable is contained in return type, but not the return type itself
Very common and valid. Examples are the various factory methods in guava, like Lists.newArrayList().
2) Once in parameter type position:
2.a) Simple type parameter
public static <E> void shuffle(List<E> list);
Note that the implementation actually needs the type parameter in order to shuffle the elements. Nonetheless, the caller should not have to be bothered with it. You can write an internal helper method that "captures" the wildcard:
public static void shuffle(List<?> list) {
shuffleWithCapture(list);
}
private static <E> void shuffleWithCapture(List<E> list) {
// implementation
}
2.b) Type parameter with multiple bounds
public static <T extends Foo & Bar> void foo(T);
public static <E extends Foo & Bar> void foo(List<E>);
Since Java does not allow intersection types anywhere but in type parameter bounds, this is the only way to express these signatures.
2.c) Type parameter bound contains the type parameter variable
public static <T extends Comparable<? super T>> void sort(List<T> list);
To express that the elements of the list must be comparable with each other, one needs a name for their type. There is no way to eliminate such type parameters.
The first one -
public <T extends Something> T getThing();
will cast the return type to the assigned one and generally not safe (compiler warns you about it) and so may throw ClassCastException. but since it doesn't take any parameter I assume it will always return SomeThing and generic type over there is useless.
The second one I think is also useless as it will allow any type, so better to use Object instead
Such declarations make code less readable and doesn't provide any benefit as well, I'll recommend to use -
public Something getThing();
and
public static void storeData(int id, Object data);
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.
I'd like to define a generic type, whose actual type parameter can only be
One of the numeric primitive wrapper classes (Long, Integer, Float, Double)
String
I can meet the first requirement with a definition like this
public final class MyClass<T extends Number> {
// Implementation omitted
}
But I can't figure out how to meet both of them. I suspect this is not actually possible, because AFAIK there's no way to specify "or" semantics when defining a formal type parameter, though you can specify "and" semantics using a definition such as
public final class MyClass<T extends Runnable & Serializable > {
// Implementation omitted
}
Cheers,
Don
Java generics does not support union types (this parameter can be A OR B).
On a related note that may be of interest to some, it does support multiple bounds, if you want to enforce multiple restrictions. Here's an example from the JDK mentioned in the Java generics tutorial:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
You could use factory methods for all supported types and make the constructor private/protected. You have to fix the generic type in the constructor anyway so that it makes sense, so you could probably code it like this:
public final class MyClass<T> {
public static MyClass<Integer> newInstance(int i) {
return new MyClass<Integer>(i);
}
public static MyClass<String> newInstance(String s) {
return new MyClass<String>(s);
}
//More factory methods...
protected MyClass(T obj) {
//...
}
}
Or if you do not want the constructor parameter, something like this:
public final class MyClass {
public static MyClass newIntegerInstance() {
return new MyClass();
}
//...
}
As erickson stated, the common implementation can rely only on Object anyway, so the only restriction is, that you can create other implementations for other types besides the primitive and String.
While generics won't work here, a base type with derived types for Number and String will. Since a generic type would have erased to Object anyway, any functionality you would have put there can go in an abstract base class. You're likely to need only a type-specific accessor on the subclass to get the value.
Also, be careful with the Number class. It's not limited to boxing the primitive types, as anyone can extend it—e.g., BigInteger.
Interesting question, it boggled me a bit. However apparently this is impossible. I tried several different hacks, none really work.
Maybe you could do what follows:
Make MyClass<T> a package-default class, invisible to other components, or at least with a package-default ctors only, so that it cannot extended or instantiated outside the package.
Create two public classes in the package of MyClass<T>:
MyNumericClass<T extends Number> extends MyClass<T>
MyStringClass extends MyClass<String>
This way all subclasses of MyClass will be limited to those parametrized with a Number subclass or String.