I want to receive a function in parameter and call it with one parameter as:
public static <T> T foo(Callable<T> func)
{
return func.call("bar");
}
But it call doesn't take any parameter. Any idea on how can I do this?
No matter how much I search, I dont find anything that help me...
A Callable<T> only has one method: T call().
If you want something different, you will need to use a different parameter type, for example:
public interface CallableWithString<T> {
T call(String arg); //Assuming you want a string argument
}
Then your function can do:
public static <T> T foo(CallableWithString<T> func) {
return func.call("bar");
}
The call method defined in Callable has no parameters defined so you cannot pass anything to it.
Depending on what you want to do exactly you can write your own interface for that:
public interface CallableWithParameters<T> {
public T call(Object... arguments);
}
Then you call it in different ways:
call();
call(someObject);
call("someString", 42);
Related
Say I have a 3 generic parameters:
public static interface Mapper<V,T,E> {
public void map(KeyValue<V> v, AsyncCallback<T,E> cb);
}
How can I make the parameters optional? How can I give the parameters default values if the user only supplies the first parameter?
Using TypeScript, that would look like:
public static interface Mapper<V,T = any,E = any> {
public void map(KeyValue<V> v, AsyncCallback<T,E> cb);
}
so if the user doesn't supply T and E, they default to any. Is there a way to do this with Java?
If what you have in mind is something along the lines:
Having a method that takes 3 (generic) parameters
But at times you'll want it to have 2 parameters
Then, the following is the way to approach this. Since otherwise making parameters optional is not allowed in my opinion.
interface InterfaceA<T, T> {
boolean myMEthod(T clazz, UserRef user, String type, T clazz2) {
return false;
}
}
interface InterfaceB<T> extends InterfaceA<T, T> {
default boolean myMEthod(T clazz, UserRef user, String type) {
return myMEthod(clazz, user, type, clazz);
}
}
This allows you to implement the InterfaceB whereever you want to skip a parameter.
You could pass same parameter (of same type) twice, pass null, or some default value.
I hope this works for your case.
I'd say no. Java enjoys it when all of it's variables are set as a certain type and never change. If you want to find the most flexibility, try finding the biggest possible superclass, as in maybe T = Object and E = Object. Later when you need to use the object you can typecast it into what you want? Maybe?
I see two ways of doing it (or at least workaround the problem):
The first way is to implement a method with all your parameters and pass null instead of the parameter if you don't need it. Then handle it in your method's body. This should look like this:
public void myMethod(Sometype param1, Sometype param2, Sometype param3) {
//Test if your paramaters are null or not then do what you want
}
And you can call your method like this (if you don't need the second parameter for example):
myInstance.myMethod(param1, null, param2);
You could do it like this, but I DON'T recommand using this trick, because it's
counterintuitive for the user, and your method will be verbose, and "unclean"...
There's a second way to do it. even if it's way more verbose than TypeScript or Kotlin, you can simply define several methods with the required parameters. For example one method with only the second parameter, one with the first and the third parameter, etc... It's just basic method overloading, but it works perfectly! I think it's one of the most "java-friendly" way to do it.
I hope I helped you
Like many languages, there is no optional or gradual typing in Java. The typing rules are probably complicated enough as it is. Nor are there default type arguments, but that doesn't seem to be the major issue here.
In your case, it looks like making the typing more client friendly solves the problem without having to go further. I am assuming the E in AsyncCallback is for "exception" and T is, as in GWT's AsyncCallback, for a method parameter.
public static interface Mapper<V,T,E> {
public void map(KeyValue<V> v, AsyncCallback<? super T,? extends E> cb);
}
That allows any particular Mapper to take any applicable AsyncCallback.
We can be more explicit about the exception - useful if we need to define a throws anywhere.
public static interface Mapper<V,T,E extends Throwable> {
If a reference to a Mapper could take any AsyncCallback, declare it of type Mapper<V,Object,Throwable> for some V.
If you desperately wanted a short form of Mapper with a concise declaration for you could introduce an adapter.
public class MapperAny<V> implements Mapper<V,Object,Throwable> {
private final Mapper<V,Object,Throwable> target;
// A static creation method would be nicer, but ctor conventional.
public MapperAny(Mapper<V,Object,Throwable> target) {
this.target = target;
}
public void map(KeyValue<V> v, AsyncCallback<T,E> cb) {
target.map(v, cp);
}
// unwrap
public Mapper<V,Object,Throwable> mapper() {
return target;
}
}
If you wanted the same thing for AsyncCallback, it's a bit more difficult. There is no denotable opposite of Object (i.e. the type of null).
You can´t do it with one class, but you can partially solve it using inheritance. Say you have
interface Mapper<V,T,E> {
public void map(KeyValue<V> v, AsyncCallback<T,E> cb);
}
You can then have interfaces that specialize this, like so:
interface MapperWithObjectValue<T,E> extends Mapper<Object, T, E> {
}
interface MapperWithObjectResult<V,E> extends Mapper<V, Object, E> {
}
etc.
It´s not all that useful in this way, as the user could just as well pass Object as the type parameter, but it does have its uses for retroactively generifying an interface. Say you have
interface Foo {
Object getFoo();
}
You then realize that you´d like that return type be a generic type, but you´ve already committed this interface as part of your stable API. You can then use specialization via inheritance to solve it, like so:
interface GenericFoo<T> {
T getFoo();
}
interface Foo extends GenericFoo<Object> {
}
Existing code can keep using Foo just like before, and code that has a need for a different return type can use GenericFoo instead.
I have the following method:
public <T> T getObjectFromMessage(Class<T> clazz) {
return gson.fromJson(compressor.decompress(message.getJsonInputs(s3)), clazz);
}
I want to pass getObjectFromMessage as a parameter into a lambda that's supplied to me. The lambda can then supply the class of the object that it expects to find in the message, and get an instance of it back. Is there a way to do this without losing the type information?
I can force it to work with casting and some Object bounds, but I'd really like the consumer to know that if it passes in a Class<T> it will get a T back, much like any method with generic bounds.
In the consuming lambda, I'm currently forced to do declaration gymnastics like:
public void consume(Function<Class<Object>, Object> getInputs){
MyType type = (MyType)getInputs.apply(MyType.class);
}
but there are cases where I want to try to parse the inputs, and if I fail, try a different class. The generics really need to be inferred per-call, as a method would.
You can define a custom function interface with a generic method:
interface TypeFunction {
<T> T apply(Class<T> clazz);
}
public void consume(TypeFunction getInputs) {
MyType type = getInputs.apply(MyType.class);
}
Some thoughts on this... does a function that invokes another function add anything?
For example:
<T> T consume(ReadType<T> typeFunction) {
T type = typeFunction.read();
return type;
}
There are generic types being managed in at least 3 entities here:
The class that contains the message string.
The function that deserializes the message string to an object.
The function that calls the deserializer function.
I expect from the question that the Object that holds the message string is also responsible for deserialization? If so you could consider declaring the generic type there. That would prevent the need of passing the type to the deserializer function, for example this could be simplified further:
<T> ReadType<T> readObjectFromMessage(Class<T> clazz) {
return () -> readValue(clazz);
}
I've declared ReadType as:
interface ReadType<T> {
T read();
}
Also implemented a simple test to check outputs and visualise how this might be used:
#Test
public void consumeTypeTest() throws Exception {
String message = "{\"foo\":\"hello\",\"bar\":\"world\"}";
GenericFunctions genericFunctions = new GenericFunctions(message);
ReadType<MyType> myTypeFromMessage = genericFunctions.readObjectFromMessage(MyType.class);
MyType myType = genericFunctions.consume(myTypeFromMessage);
Assert.assertThat(myType, equalTo(new MyType().setFoo("hello").setBar("world")));
}
I had an interview test and saw the following code:
EDIT:
public class TestValue {
private Value<SomeValue> defaultValue;
#Test
public void Empty_Value_Has_No_Value() {
Assert.assertFalse(Value.<SomeValue> createEmptyValue()
.hasValue());
}
#Test
public void Default_Value_IsEmpty() {
Assert.assertEquals(Value.<SomeValue> createEmptyValue(),
defaultValue);
}
#Test
public void Non_Empty_Value_Has_Value() {
Assert.assertTrue(new Value<SomeValue>(true, new SomeValue())
.hasValue());
}
}
I had never seen Java generic like
Value.<SomeValue>
The test is to implement Value class with the given unit test code above.
I tried to figure out the Value method signature below (need implementation):
public interface Value<T> {
public boolean hasValue();
public Value<T> createEmptyValue();
}
Any one know, please help?
Thank you
EDIT: Should be like this according to answers below #marlon
public class Value<T> {
public boolean hasValue(){}
public static <M> Value<M> createEmptyValue(){}; //need <M>
}
The key syntax to know:
Value.<SomeValue> //ClassName.<Type>method
is way to invoke static method of a class with parameterized argument.
EDIT: according to #snipes83, syntax to invoke non-static method of a class with parameterized argument.
SomeObject.<Type>method
Value.<SomeValue> it's the way generics are represented for methods.
Using Google Guava's Optional as an example:
Optional<String> email = Optional.<String>of(strEmail);
See Generic Types - Invoking generic methods
Since interfaces cannot declare static methods (shame on you java), just declare your method as static and forget about the interface, like this:
class Value<T> {
public static <T> Value<T> createEmptyValue(){
return null;
}
}
Look at the class Test with the method getEmptyList below:
public class Test {
public <T> List<T> getEmptyList() {
return new ArrayList<T>();
}
}
It returns an empty List containing objects of type T.
If you use Test like this
Test t = new Test();
List<Integer> list = t.getEmptyList();
Then the type inference mechanism is able to infer the type parameter based on the variable type.
However if you need to use the return value of getEmptyList within a method invocation expression like in the following example where the method printList expects a single argument of type List<Integer>, then the type can not be infered from any variable type.
public void printList(List<Integer> list) {
for (int i : list) {
System.out.print(i);
}
}
printList(t.getEmptyList()); // This will FAIL.
In this case you need to specify the type using the following:
printList(t.<Integer>getEmptyList());
1) This is how generic methods are invoked. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/methods.html
2) <SomeValue> in Value.<SomeValue> is optional. Compiler can infer the type. This is called TypeInference. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
Answer Updated:
3) Value.<SomeValue> createEmptyValue() is right and Value.<SomeValue>createEmptyValue() is right too. Both ways are legal. Just tested it. Didn't notice before.
Although Value is itself obviously typed ( based on the instance variable type of Value<SomeValue>), the static createEmptyValue() method is also typed.
A reasonable assumption, if naming conventions have been adhered to, is that SomeValue extends (or implements) Value.
Although there us no one correct answer, a likely possibility for the signature of Value is:
public class Value<T extend Value> {
public static <V extends Value> V createEmptyValue() {
// some impl
}
}
My question is: is it possible to make one generic method where I can use 2 different types? E.g. an Integer and a String.
There is no practical use for this, but I'd just like to know if it's possible. And if it is, how? :)
You dont need to use generics for this. You can overload the methods. For example
public void method(Integer i){}
public void method(String s){}
If you call method with an integer then it will call the first method. If you call it with a string it will call the second method.
Presumably you mean two different types of parameter?
You could use one method for the String param, and another than takes the integer and passes it on to the String version.
The example types are not good one as the are final. This mean that you can not use them to limit the generic parameter as nothing can inherit from them.
So for that types the answer is No.
But what we can do with Java is:
You can create a method that accept Object type.
public <T> void doStaff(T obj) {
}
You can create a method that is limited to CharSequence as String is final
public <T extends CharSequence> void doStaff(T str){
}
You can create a method that is litmited to more the one interface
public <T extends CharSequence & Comparable<T>> void doStaf(T interf) {
}
But even with so many possibilities we can not create a generic parameter that is valid for Two unrelated types. This would not have sense. As main task of generic type is to provide type safety. And in generally when we use them we should operate with interfaces not classes.
If you want your method to accept Integer and String, try below approach:
public class Test {
public static void main(String[] a) {
method(new String(),new Integer("2"));
}
public static <T extends String, U extends Integer> void method(T t, U u){
}
}
EDIT:
if you want your method to take a single parameter that takes either a String or Integer
try this :
public static <T extends Comparable<T>> void method(T t){
}
I am trying to achieve the following:
I have this method
public String methodName(Userdefinedclass.class,Userdefinedclass obj)
{
//some code
.........
method(Userdefinedclass.class);
method2(obj);
}
I want to generalise this method.
The challenge is that the argument here is user defined, i.e it can change. So please help.
public <T> String methodName(Class<T> c, T obj)
{
method1(c);
method2(obj);
return "some string";
}
void method1(Class c)
{
// Some stuff.
}
Generics is type erasure so you cannot have .class of Generic type. That is becaue generics are erased in this case to Object type. Hence `T.class' wont work
So instead use Class<T> to get the class and then work along
This keeps your method signature intact:
public <T> String methodName(Class<T> c, T obj)
{
method(c);
method2(obj);
}
but i would use ivanovic's answer.
If you want to generalize the parameters used in the function you can create an empty interface and force the userDefinedClass to implement it.. Or You can use T for achiving this