I'm trying to re-use a Java generic collection I wrote, looks a lot like this:
public class Blah<T>
implements List<T>
{
...
public void test(T[] array) {
...
}
...
}
When consumed from a Scala generic collection that uses the above, I'm getting a compilation error, where I notice that the Blah class method expects not T, but T with java.lang.Object!
Object MyStaticObject {
def test[T](array: Array[T]) = {
val x = new Blah[T]();
x.test(array) // <- error here: Overloaded method with alternatives test[T with java.lang.Object] ... cannot be applied
}
Is there a way to avoid this situation without re-writing the Blah class in Scala? (That works, but I have too much such Java code and rather not port the whole thing...)
Maybe perhaps some kind of implicit definition could come to the rescue?
Thanks!
Restricting def test[T <: AnyRef] does the trick.
Rightly so, the generic java method should not accept , e.g., an int[] (Array[Int]) parameter.
Blah[Int] will be taken as Blah<Integer>, Array[Int] is int[], which is not Integer[].
Related
I am a newbie in java functional interfaces so I want to see if this is possible and if not please explain me why not and what is possible in order to achieve my idea
I have these classes
public class A {
...
public String getInfo();
...
}
public class B {
...
public String getOtherInfo();
...
}
I want to pass the references to these functions to another object like this:
obj.init(A::getInfo)
obj.init(B::getOtherInfo)
so that later I can use/call these functions on different objects of type A or B inside the build functions:
obj.build(a1);
obj.build(a2);
...
obj.build(b1);
obj.build(b2);
PS1 I cannot use regular interfaces for this cause there are lot of getters and lots of classes similar to A which I want to use for this procedure and they are not related with one another
PS2 I try to avoid reflection cause you cannot trace the function calls
PS3 my example is not exactly working as is it throws this error: "non static method cannot be referenced from a static context"
A::get is a Java Method Reference. You should be able to store it for use later. As it's an instance method you'll need the instance object as well. So something like this might work:
Function<A,String> getFunction = A::get;
And whenever you need to use it you can do
//assuming you have an object instance of A which is a
getFunction.apply(a)
You can also pass it to other methods by declaring the method to take a functional parameter like this:
public void someOtherMethod(Function<A,String> param) {
//do whatever with param.
//invoke this with an instance of A when you're ready
param.apply(a);
}
Here's a reference that might help: https://www.baeldung.com/java-8-double-colon-operator
Made 2 mistakes
should have used Function<T, R> instead of Supplier
the error is thrown even if there is a slight mismatch of parameters even on the generic types. So an example of my function which accepts the Function parameter should be declared like this:
public <T extends Base> init (Function <T, String> f){
this.f = f;
}
and later I do something like:
public String build (A a){
return this.f.apply(a);
}
(so I had to make A, B implement some useless interface)
I'm doing a series of streaming operations to flatten what's effectively a 2D array.
Arrays.stream(attributes)
.map(Attribute::getCommand)
.filter(Optional::isPresent)
.map(Optional::get)
.flatMap((array) -> (Arrays.stream((String[]) array)))
.toArray(String[]::new)
Where Attribute conforms to the following interface:
public interface Attribute<T> {
Optional<String[]> getCommand();
}
However, the final flatMap() call isn't operating as expected.
.flatMap((array) -> (Arrays.stream((String[]) array))) works just fine.
.flatMap((array) -> (Arrays.stream(array))) fails to compile with java: no suitable method found for stream(java.lang.Object).
.flatMap(Arrays::stream) fails to compile with java: incompatible types: cannot infer type-variable(s) T (argument mismatch; java.lang.Object cannot be converted to T[]).
It seems to me that the type should be inferred just fine though. IntelliJ agrees and marks the cast as redundant and shows no compile errors with any of the three implementations. Why does Java require this apparently redundant typecast?
I additionally tried the following minimalist implementation:
import java.util.Arrays;
import java.util.Optional;
public class Streaming {
public static void main(String[] args) {
Optional<String[]>[] myarray = new Optional[]{Optional.of(new String[]{"Hello", "world"}),
Optional.empty(), Optional.of(new String[]{"Foo"})};
System.out.println(Arrays.toString(Arrays.stream(myarray).filter(Optional::isPresent).map
(Optional::get).flatMap(Arrays::stream).toArray(String[]::new)));
}
}
And it works just fine with all three implementations, outputting the expected [Hello, world, Foo].
Edit:
This was marked as a duplicate of this question. I may be wrong, but it seems that there's a distinction since this the type is specified in a more explicit manner. Notably, IntelliJ agrees that the cast is necessary in the example provided on said post, but not for my code. If I am mistaken, please let me know.
Edit:
Per request, the declaration of attributes is Attribute[] attributes = new Attribute[]{...} where ... is a variety of implementations of Attribute.
Attribute is a generic class (I wonder why as T is not used).
If you have this error it means that you declared a raw type of that such as :
Attribute[] attributes = ...;
For a raw type, the return type of getCommand() that is declared as Optional<String[]> becomes just Optional.
Declare Attribute as a generic type, for example : Attribute<String>[] attributes = ...; and this should compile without the cast or just remove the parameterized type T if it is not required.
I am using twirl templates with Java and Scala. So I am trying to sort a List in the template, but I do not know how to override the Comparator method.
My List contains objects of a class designed like:
class Foo extends BaseFoo<Foo>
The class BaseFoo does have a method called
public String FooName() {/*returns some Name of Foo*/}
In my scala twirl template it looks like:
source: java.util.Collection[_ <: BaseFoo[_]]
No in the twirl template I am trying to sort it:
#Collections.sort(
new util.ArrayList[_ <: BaseFoo[_]](source),
new Comparator[_ <: BaseFoo[_]] {
override def compare(o1: BaseFoo, o2: BaseFoo) = {
return o1.FooName.compareTo(o2.FooName);
}
})
But this seems not to compile:
class type required but java.util.ArrayList[_ <: BaseFoo[_]] found
Not a direct answer, but given that you state that you have a list of Foo objects, the straight forward solution seems to be to use
source: java.util.Collection[_ <: Foo[_]]
or something alike!
Meaning: when the list contains Foo objects, what does it matter if those descend from Object or from FooBase?!
You could convert your source to a Scala collection type and then just call .sortBy on it. No need for Comparators:
import collection.JavaConverters._
source.asScala.toSeq.sortBy(_.FooName)
I have got the following interface which is implemented by the following class. For this class, I would like to be able to use method chaining, which is why I added a "return this" at the end of the addFilter() method:
public interface IFilteredDataService<B extends Bean> extends IDataService<B>
{
FilteredDataService applyFilter(Predicate<B> filter);
}
public class FilteredDataService<B extends Bean> implements IFilteredDataService<B>
{
#Override
public FilteredDataService addFilter(Predicate<B> filter)
{
filters.add(filter);
return this;
}
}
When I use the addFilter() method in the following way, everything is fine:
someInstance.addFilter(foo);
someInstance.addFilter(bar);
When I use the method chaining like this:
someInstance.addFilter(foo).addFilter(bar);
it still works fine, but I get the following warning:
Unchecked call to 'addFilter(Predicate<B>)' as a member of raw type 'FilteredDataService'.
I was not able to figure out why this happens and how to remove it. Any help would be greatly appreciated.
You're missing the generic information in your return value, returning a raw (non-generic) FilteredDataService.
Use public FilteredDataService<B> addFilter(Predicate<B> filter) to keep the generics.
When you want to use generic and chain this method, you have to create fully generic method (include returning) as Kayaman wrote. And take a look at what you getting:
Unchecked call to 'addFilter(Predicate)' as a member of raw type 'FilteredDataService'.
In simple translation: You are calling method which should accept generic param (addFilter(Predicate filter)) but you are sending nongeneric param during chaining (return this; = FilteredDataService -> Non-Generic).
Just for clarify :o)
Suppose I have a Java class hierarchy defined as follow:
interface Bar<T> {}
class Foo<A,B> implements Bar<B> {}
How can I programmatically assess (using reflection) that the type parameter of Bar in Foo is the second of foo's parameters and not the first (B instead of A)?
I've tried using TypeVariable#getName() in order to compare the names, but when I apply getGenericInterfaces() to Foo<A,B> I get Bar<T> and not Bar<B>
Solution (thanks to #LouisWasserman): use Foo.class.getGeenricInterfaces()[0].getActualTypeParameters() returns the correct TypeVariable (B instead of T, in the previous example)
well using TypeVariable#getName() return the type as it appears in the source code in your case it's normal to get Bar<T>. TypeVariable Doc
Using reflection in generic Classes can't help, because of Type Erasure. Erasure of Generic Types
I've the same issue in some personal projects, I tried to change the design of my class, have a look at the example below:
Instead of this:
public class Mapper<T> {
public Mapper(){
}
}
I used this:
public class Mapper {
private Class<?> entityClazz;
public Mapper(Class<?> entity){
this.entityClazz = entity
//Here I've donne all reflection issues i want !
}
}
You can use Class#isAssignableFrom() Doc to test assignability between Class Objects.
I hope this helps, good luck !