Generics and Comparator - java

I am working on generics and found that the following code is giving compile time error at comparing method.
Multiple markers at this line
- Cannot infer type argument(s) for comparing(Function)
- The type A does not define m1(Object) that is applicable here
class A<T> {
String m1() {
return null;
}
}
class B {
void test() {
Comparator<A<String>> target = Comparator.comparing(A::m1).thenComparing(A::m1);
}
}
Can some one help me understand this behavior; and how can I fix the problem?

If you specify the exact generic types at the comparing method, the code compiles.
Comparator<A<String>> target =
Comparator.<A<String>, String>comparing(A::m1).thenComparing(A::m1);

You should specify type parameter for class A.
Comparator<A<String>> target = Comparator.comparing(A<String>::m1).thenComparing(A<String>::m1);

Interesting question. Haven't gone into JLS but I guess type inference does not work in case of chained method call. (You can see it works for a simple Comparator<A<String>> target = Comparator.comparing(A<String>::m1); )
One quick fix, which is similar to another answer, is help Java do the type inference:
Comparator<A<String>> target = Comparator.comparing(A<String>::m1)
.thenComparing(A::m1);
Please note doing it at the first method already do the trick.
(Looking forward to see if someone can dig out JLS to see if such inference is supposed to be valid :P )

you can nested as
Comparator<A<String>> target1 = Comparator.comparing(A::m1);
Comparator<A<String>> target2 = target1.thenComparing(A::m1);
myVarList.sort(target2);

Comparator<A<String>> target = Comparator.comparing(A::m1).thenComparing(A::m1);
thenComparing() expects a Comparator object as parameter...

Related

Java fails to properly infer stream type without apparently redundant typecast

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.

SomeClass.<OtherClass>someMethod() syntax meaning

I have come across a curious syntax today. The code is from Gradle's source files you can find it in src/core-impl/org/gradle/api/internal/artifacts/configurations/DefaultConfiguration.java
private class ConfigurationResolvableDependencies implements ResolvableDependencies {
public FileCollection getFiles() {
return DefaultConfiguration.this.fileCollection(Specs.<Dependency>satisfyAll());
}
}
Is someone able to explain the purpose of this strange generics syntax. If this is a repeat, then please forgive me as i do not know what to call this for searching purposes.
The syntax here is because the Specs class's satisfyAll method is static, so the Generics syntax there is specifying the type to use for the static method.
See this for the API doc: http://www.gradle.org/docs/current/javadoc/org/gradle/api/specs/Specs.html#satisfyAll%28%29
Silly me, just read the documentation on the oracle website, This type of syntax is referred to as Type Witnessing and it is used when a generic method with generic types is defined as so:
public class BoxDemo {
public static <U> void addBox(U u, List<Box<U>> boxes) {
Box<U> box = new Box<>();
box.set(u);
boxes.add(box);
}
}
The method may be called with an additional specifier telling the compiler to infer the argument type of the first and second parameter:
List<Box<Integer>> listOfIntegerBoxes = new ArrayList<>();
BoxDemo.<Integer>addBox(Integer.valueOf(20), listOfIntegerBoxes);
also from the documentation:
Alternatively, if you omit the type witness,a Java compiler automatically infers (from the method's arguments) that the type parameter is Integer:
BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);

Understanding [[I.class referenced in some Java source

I'm looking at some Java reflection sourcecode that goes like this:
Method fixTransparentPixels = TextureAtlasSprite.class.getDeclaredMethod("fixTransparentPixels", new Class[] { [[I.class });
The method being referenced is declared like so:
private void fixTransparentPixels(int[][] p_147961_1_) {...}
What I do not understand is the [[I.class part. Now, I get that the actual Class[] array is to determine which form of the declared method you want (what parameter types etc.), but what does [[I.class actually mean?
Furthermore, when I try to write this reflection code myself, my IDE gives me syntax errors on the [[I.class bit. Can anyone give me any info on this?
Cheers.
When using getDeclaredMethod(String name, Class<?>... parameterTypes) the parameterTypes must be the class of the parameter (obviously). So in this case fixTransparentPixels require a int[][], so the parameterTypes will be int[][].class.
This will works :
TextureAtlasSprite.class.getDeclaredMethod("fixTransparentPixels", int[][].class);
[[I is the internal name of the class for int[][]:
System.out.println(int[][].class.getName()); outputs [[I
or Class.forName("[[I") == int[][].class.
However, it's illegal to write [[I.class in source code. You should write int[][].class instead.

Generic List and reflection

I'd like to call via reflection the following method, but I have problem to specify the correct signature:
public void executeRule(List<Node> params, SomethingStrangeFound callMeBack) throws IOException
{
...
}
I tried something like this:
Class partypes[] = new Class[2];
partypes[0] = Class.forName("java.util.List");
partypes[1] = Class.forName("vp.SomethingStrangeFound");
Method meth = cls.getMethod("executeRule", partypes);
It doesn't work because I use "java.util.List" when it must be "List<Node>", but I have no idea how to specify it.
If I just use "java.util.List", I have the following error calling cls.getMethod("executeRule", partypes):
NoSuchMethodException: vp.RuleWebXmlContextParamFacesPortletRenderStyles.executeRule(java.util.List, vp.SomethingStrangeFound)
Any help?
P.S.
At debug time, I see "List<Node>" is resolved with:
(Ljava/util/List<Lorg/w3c/dom/Node;>;Lit/vp/SomethingStrangeFound;)V
but it doesn't help me.
If both parameter classes are available at compile time you can initialize parameter array like this:
Class partypes[] = new Class[] { List.class, SomethingStrangeFound.class };
Method meth = cls.getMethod("executeRule", partypes);
This will guarantee that you have not mistyped qualified class names.
If this still does not work, check available methods in your class using Class#getMethods() method:
for (Method method : cls.getMethods()) {
System.out.println(method);
}
I ran your code and it worked for me.
You have not provided the definition of cls, but I assume it is something like
Class cls = RuleWebXmlContextParamFacesPortletRenderStyles.class;
Since you get a NoSuchMethodException, Class.forName already passed successfully, so no typo there (unless you have multiple SomethingStrangeFound classes, which would mean that you got the package wrong).
Because of this the last thing that comes to my mind is that perhaps you compiled RuleWebXmlContextParamFacesPortletRenderStyles before adding the method in question. Clean your code and recompile.
With partypes of size 2, getMethod will search for a method called "executeRule" with 2 parameters, one of type "java.util.list" and other of type "vp.SomethingStrangeFound"
But your method has only 1 parameter. You need to add a second parameter of type "vp.SomethingStrangeFound" to your method or set partypes size to 1.

How to use scala.None from Java code [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Accessing scala.None from Java
In Java you can create an instance of Some using the constructor, i.e. new Some(value), but None has no partner class. How do you pass None to a Scala function from Java?
The scala.None$.MODULE$ thing doesn't always typecheck, for example this doesn't compile:
scala.Option<String> x = scala.None$.MODULE$;
because javac doesn't know about Scala's declaration-site variance, so you get:
J.java:3: incompatible types
found : scala.None$
required: scala.Option<java.lang.String>
scala.Option<String> x = scala.None$.MODULE$ ;
This does compile, though:
scala.Option<String> x = scala.Option.apply(null);
so that's a different way to get a None that is usable in more situations.
I think this ugly bit will work: scala.None$.MODULE$
There is no need for a new instance since one None is as good as another...
You can access the singleton None instance from java using:
scala.None$.MODULE$
I've found this this generic function to be the most robust. You need to supply the type parameter, but the cast only appears once, which is nice. Some of the other solutions will not work in various scenarios, as your Java compiler may inform you.
import scala.None$;
import scala.Option;
public class ScalaLang {
public static <T> Option<T> none() {
return (Option<T>) None$.MODULE$;
}
}
public class ExampleUsage {
static {
//for example, with java.lang.Long
ScalaLang.<Long>none();
}
}
Faced with this stinkfest, my usual modus operandi is:
Scala:
object SomeScalaObject {
def it = this
}
Java:
doStuff(SomeScalaObject.it());

Categories