Overloading a method: both methods have same erasure - java

I have the following code and it doesn't work: the error both methods have same erasure appears.
public class Foo<V> {
public static void main(String[] args) {
}
public void Bar(V value) {
}
public void Bar(Object value) {
}
}
Also I have this code:
public class Foo<V> {
public static void main(String[] args) {
}
public void Bar(B value) {
}
public void Bar(A value) {
}
}
class A {
}
class B extends A {
}
And this works. In the first case V is a child of Object, just like in the second case B is a child of A. Then why the first case results in error, while the second compiles successfully?
EDIT: What should I do to achieve method overloading, without raising an error?

What should I do to achieve method overloading, without raising an error?
Simple: don't try to overload the method with parameters with the same erasure.
A few options:
Just give the methods different names (i.e. don't try to use overloading)
Add further parameters to one of the overloads, to allow disambiguation (ideally only do this if you actually need those parameters; but there are examples in the Java API where there are junk parameters simply to avoid overloading issues).
Bound the type variable, as suggested by #Kayaman:
<V extends SomethingOtherThanObject>

V isn't "a child of Object". V is an unbounded generic type that erases to Object, resulting in the error. If the generic type were bounded, such as <V extends Comparable<V>>, it would erase to Comparable and you wouldn't get the error.

Related

Overloaded methods in the class must have different Erasures - why only leftmost bound is considered to be the Erasure type?

Consider the following two method definitions:
static <T extends Do & Done>T whatToDo(T ele){return null;}
static <R extends Done & Do>R whatToDo(R ele){return null;}
Both will have the following erasures respectively:
static Do whatToDo(Do);
static Done whatToDo(Done);
Consider the concrete class Doing and the interfaces Do and Done
interface Do{void doIt();}
interface Done{void didIt();}
class Doing implements Do,Done{
#Override
public void doIt() {}
#Override
public void didIt() {
}
}
Now, when I try to invoke the method whatToDo, this gives the ambiguous invocation compilation error, even though the methods got compiled in the class correctly. Only at the time of invocation, I am getting error.
public static void main(String[] args) {
whatToDo(new Doing()); //compile error : ambiguous method call
}
Does it not mean that the definition of erasure is responsible for anomaly, that only the left most element is treated as the erasure for a given bounded type? Also, why has erasure been chosen to be this way? Can there be something better for the way JLS defines the procedure of erasure?
Ideal would have been that Java shouldn't have allowed the two methods in this case to exist by modifying the definition of erasure to include the unordered set of bounds rather than just the leftmost bound?
Here is the complete code:
class Scratch {
public static void main(String[] args) {
whatToDo(new Doing());
//Compilation error : because of Erasure - the 2 definitions exist even though the
//the elements of the bounds are exactly the same
//Ideally this should have been unordered list of bounds rather than left most bound?
}
static <T extends Do & Done>T whatToDo(T ele){return null;}
static <R extends Done & Do>R whatToDo(R ele){return null;}
}
interface Do{void doIt();}
interface Done{void didIt();}
class Doing implements Do,Done{
#Override
public void doIt() {}
#Override
public void didIt() {
}
}

What does public<T> void run (T object ) { } means? [duplicate]

This question already has answers here:
Return Type of Java Generic Methods
(5 answers)
Closed 6 years ago.
I am reading generics and tried writing the below code. There are no compilation error.
import java.util.*;
public class JavaApplication14 {
public<T> void run (T obj ) {
//Do Something
}
public static void main(String[] args) {
JavaApplication14 m= new JavaApplication14();
m.run(new ArrayList<>());
m.run(new Interger(5);
m.run(5);
}
}
If the function is
public<T extends Number> void run (T obj) {
//Do Something
}
It makes sense as we can restrict the arguments of this function to a Number and its subtypes. But am terribly confused what the function 'run' without any bound mean?
Can it now take any object as the argument ? In what scenario do i need to use such a function with generics ?
Part of your confusion may stem from the fact that there is no point in having run be a generic method in this case. You normally use a type parameter to create a relationship between two parameter types and/or between parameter type and return type. In your example run could just as well have been declared as requiring an Object parameter (a type parameter without a declared bound effectively has Object as its bound).
There is one case I know of where you might usefully use a type parameter in a single parameter type: when you want to be able to manipulate a collection in a way that doesn't depend on the element type, but which does require inserting elements into the collection. Consider for example a hypothetical "reverse list" method:
<T> void reverse(List<T> list)
{
List<T> reversed = new ArrayList<T>();
for (int i = list.size(); i > 0; i--) {
reversed.add(list.get(i - 1));
}
list.clear();
list.addAll(reversed);
}
It would be difficult to write this in a way that didn't require a type parameter, i.e. that takes a List<?> parameter. The only way to do it without casts is to do:
void reverse2(List<?> list)
{
reverse(list); // call reverse as defined above!
}
But again, this doesn't apply in the example you discuss.
So in summary:
A type parameter without an explicit bound effectively has an Object bound.
There are two reasons why a method might need a type parameter (either with or without an explicit bound):
Specify a relationship between parameter types and/or return type
Capture a potential wildcard as a type parameter to allow operations that wouldn't otherwise be possible (as in the reverse example).
The example method you discussed:
public<T> void run (T obj )
... does neither of these, and so the type parameter is pointless. The method might just as well have been declared as public void run(Object obj).
It allows you to avoid any cast.
public class SomeClass {
void doStuff();
}
public<T extends SomeClass> void run (T obj) {
//can call doStuff without any casting
obj.doStuff();
}
public<T> void run (T) {
//Here, there's no clue to perform the implicit cast.
obj.doStuff(); //won't compile
}
While in this case the function could take Object just as well, the variant that makes sense to you is equivalent to public void run(Number obj) { ... } as well. For an example where lack of bound makes sense consider a case where the return type mentions T: public <T> List<T> singletonList(T obj).
Some theory
There're generic methods. Their main goal is generic algorithms (receive and return same types).
Code that uses generics has many benefits over non-generic code:
Elimination of casts.
Stronger type checks at compile time.
Enabling programmers to implement generic algorithms.
A little practice
Consider the following code:
class MyClass {
public void method() {}
public static void main(String[] args) {
runFirst(new MyClass());
runSecond(new MyClass());
}
public static <T extends MyClass> void runFirst(T obj) {
obj.method();
}
public static <T> void runSecond(T obj) {
((MyClass) obj).method();
}
}
The runFirst() method allows us to avoid cast to class and all its subclasses. In runSecond() method we can get any type of parameter (<T>, roughly speaking, means <T extends Object>). Firstly, we must cast to MyClass and then call its method.
First of all I will start with the meaning of public <T> void run(T object) { ... }. Yes when you use that kind of code you than you may use any object as a parameter of run. If you want to restrict the arguments of this function to a specific interface, class or its sub classes you can just write code like NotGenericRun which is shown below.
public class NotGenericRun {
public void run(ArrayList<?> list) {
String message = "Non Generic Run List: ";
System.out.println(message.concat(list.toString()));
}
public void run(int intValue) {
String message = "Non Generic Run Int: ";
System.out.println(message.concat(String.valueOf(intValue)));
}
}
Here I tested output of GenericRun and NotGenericRun classes.
public class TestClass {
public static void main(String[] args) {
GenericRun m = new GenericRun();
m.run(new ArrayList<>());
m.run(new Integer(5));
m.run(5);
NotGenericRun n = new NotGenericRun();
n.run(new ArrayList<>());
n.run(new Integer(5));
n.run(13);
}
}
Output of this code was following:
Generic Run: []
Generic Run: 5
Generic Run: 5
Non Generic Run List: []
Non Generic Run Int: 5
Non Generic Run Int: 13
When you use Generic run as I already said arguments may be any object but there is other way of restricting the arguments while still using generics.
public class GenericRun {
public <T> void run(T object) {
String message = "Generic Run: ";
System.out.println(message.concat(object.toString()));
}
}
This is how.
public class GenericRun <T> {
public void run(T object) {
String message = "Generic Run: ";
System.out.println(message.concat(object.toString()));
}
}
In this case you'll be using GenericClass like this:
GenericRun<Integer> m = new GenericRun<Integer>();
m.run(new Integer(5));
m.run(5);
and only value that it will be tacking should be stated while creating class. I can't think of scenario when public <T> void run(T object) { ... } may be needed but it might occur when you'll need the method to get every argument or you don't know what arguments will be (but it's really less likely). I think more often when you'll be using generics with run like this:
public class GenericRun <T> {
public void run(T object) {
...
}
}
I was searching about usage of generic methods here you can read more about why may we need generic methods.
Here is another example:
public class GenericRun {
public <T> void run(T[] inputArray) {
for (T element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
}
Using this class you can print array of different type using a single Generic method:
public class TestClass {
public static void main(String[] args) {
GenericRun m = new GenericRun();
// Create arrays of Integer, Double and Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("Array integerArray contains:");
m.run(intArray); // pass an Integer array
System.out.println("\nArray doubleArray contains:");
m.run(doubleArray); // pass a Double array
System.out.println("\nArray characterArray contains:");
m.run(charArray); // pass a Character array
}
}
I hope I answered your question.
The only thing makes sense here is if this was some kind of pseudo-abstract or base class, that provided framework for behaviour and let another coders implement their own logic, but also provided default null action.
It could allow for better generic type-setting, for example as:
class MySubClass extends JavaApplication14 {
public <T> void run(T obj){
new ArrayList<T>().add(obj);
}
}

Cannot convert functional interface with generic method into lambda expression

Cannot convert functional interface with generic method into lambda expression.
Following code is working. It is without lambda expression i.e. using anonymous class.
public interface Pro{
public <T> void callee(T t);
}
public void fun(Pro obj){}
public void implement() {
fun(new Pro() {
#Override
public <Integer> void callee(Integer t){}
});
}
I cannot understand how to use lambda expression instead of anonymous class.
After trying it myself I used the hint shown in netbeans. I used the shown bulb to do it.
And here is what I got, an ERROR.
public void implement() {
fun((Integer t) -> {
});
}
It is showing error. What is the correct lambda expression to be used here?
Here is the error :
one\LambdaScopeTest.java:18: error: incompatible types: invalid functional descriptor for lambda expression
fun((Integer t) -> {
^
method <T>(T)void in interface Pro is generic
where T is a type-variable:
T extends Object declared in method <T>callee(T)
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get
full output
The main problem is that you've got a generic method instead of a generic interface. That doesn't make a lot of sense. As soon as you make the interface generic instead, it works:
#FunctionalInterface
interface Pro<T> {
void callee(T t);
}
public class Test {
public static <T> void fun(Pro<T> obj){}
public static void main(String[] args) {
fun((Integer t) -> {});
}
}
It makes much more sense for the interface to be generic, as then it makes sense to have different implementations for different types. For the method to be generic suggests that every implementation should be able to accept any value of any type, because the caller would be specifying it - which doesn't make sense if you then use a lambda expression with a specific type.
Your original version is only working because you're declaring a generic type parameter called Integer... you're not specifying an implementation for the Integer type. In other words, this:
fun(new Pro() {
#Override
public <Integer> void callee(Integer t){}
});
is equivalent to:
fun(new Pro() {
#Override
public <T> void callee(T t){}
});
... and I don't know of a way of representing that as a lambda expression. Basically, I think your original interface is inappropriate for lambda expressions.

Java 8 method references : validation of methods at compile time

I'd like to use the new method references of Java 8 to provide more validation of some code at compile time.
Let's say I have a validateMethod method which requires one parameter : a "method" to be validated. For example :
validateMethod(foo, "methodA");
Here, the method would validate that foo#methodA() exists, at runtime.
Using method references, I'd like to be able to do :
validateMethod(foo::methodA);
So the existence of the method would be validated at compile time.
The problem is that it seems method references have to be assigned to a functional interface. For example, this :
Object dummy = foo::methodA;
Generates the error : "The target type of this expression must be a functional interface".
If I create a functional interface that has a compatible signature with the methodA method, it works :
#FunctionalInterface
public interface MyFunctionalInterface
{
public String run();
}
MyFunctionalInterface dummy = foo::methodA;
Now the existence of foo#methodA() is validated at compile time, which is what I want!
But...
Let's say validateMethod doesn't know the signature of the method it has to validate. Is it still possible to implement it then?
Let's pretend we don't care about ambiguity and overloaded methods. Is it possible in Java 8 to implement some kind of method which would trigger the validation of any method reference?
For example :
public class Foo
{
public String methodA()
{
return "methodA";
}
public String methodB(String str)
{
return "methodB";
}
public String methodC(String str, int nbr)
{
return "methodC";
}
}
Foo foo = new Foo();
validateMethod(foo::methodA); // Compile
validateMethod(foo::methodB); // Compile
validateMethod(foo::methodC); // Compile
validateMethod(foo::methodD); // Error!
Would it be possible to implement validateMethod in such a way that any method reference would be accepted, so the existence of the method would be validated at compile time?
I tried :
public void validateMethod(Object obj){}
But it doesn't work : "The target type of this expression must be a functional interface"
This would work :
#FunctionalInterface
public interface MyFunctionalInterface
{
public String run();
}
public void validateMethod(MyFunctionalInterface param){}
But only for methodA of the Foo class, because its signature (no parameter) is compatible with the functional interface's method signature!
Would it be possible to implement the functional interface MyFunctionalInterface in such a way that any method reference would be a valid parameter and therefore would be validated at compile time?
Any other ways you see to validate the existence of a method at compile time?
You seem to be trying to use method references, which are really the short-hands for lambda expressions, as method literals, which are the syntactic references to methods (much like Foo.class is the syntactic reference to class instance of Foo). These two are not the same, and this is the reason for the impedance you encounter. Things you try are the abuse of language feature which javac compiler utterly resists.
Unfortunately, there is no method literals in Java, so you will have to describe the method by other means, e.g. Reflection, MethodHandles.Lookup, etc. I think it is very easy to come up with the reflective checker for this kind of thing, or even build up the annotation processor to check the existence of given methods in compile time.
You could try something like the following:
public class Validate {
public String methodA() { return "methodA"; }
public String methodB(String s) { return "methodB"; }
public String methodC(String s, int n) { return "methodC"; }
public static void main(String[] args) {
Validate foo = new Validate();
validateMethod(foo::methodA);
validateMethod(foo::methodB);
validateMethod(foo::methodC);
}
private interface Func0 { void method(); }
private interface Func1<T> { void method(T t); }
private interface Func2<T, U> { void method(T t, U u); }
private interface Func3<T, U, V> { void method(T t, U u, V v); }
public static void validateMethod(Func0 f) { }
public static <T> void validateMethod(Func1<T> f) { }
public static <T, U> void validateMethod(Func2<T, U> f) { }
public static <T, U, V> void validateMethod(Func3<T, U, V> f) { }
}
But you'll need to provide an interface and an overload of validateMethod for every arity of method you need to validate. Also, it will not work if the method to validate is overloaded, unless you add an explicit cast:
// if there are two methodA's:
public String methodA() { return "methodA"; }
public String methodA(long x) { return "methodA"; }
validateMethod(foo::methodA); // this doesn't work
validateMethod((Func0)foo::methodA); // this does
validateMethod((Func1<Long>)foo::methodA); // so does this
would interface Method { public Object runMethod(Object... args); } work? the only potential problem i see is methods that deal with primitive types, but perhaps they could be upcast automatically to Double's / Long's, dont really have a running java8 compiler atm.

Java Generics Value.<SomeValue>

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
}
}

Categories

Resources