Running on Eclipse Oxygen, and Create local variable (Cmd-1) results in Object instead of the inferred type.
public static void main(String[] args) {
Object x = get("test", o -> o.length());
}
public static <A, B> B get(A target, Function<A, B> func1) {
B result = func1.apply(target);
return result;
}
I would expect it to create x as int.
Any ideas?
Thanks.
Related
I am a newbie to kafka streams.
I am able to achieve the following.
I have an input topic. The message object (say Flower).
I have a transformer that converts Flower into Fruit.
I then store the Fruit to output topic.
What I want to achieve is like something that follows
I store Fruit to Fruit topic (... as above)
I store (the successful) Flower to Successful_Flower topic (... additionally)
(If it is not possible to discriminate Flowers as above, it is even okay if I can store the incoming Flower (successful or failed ...both) to OutputFlower topic)
Is this possible? If yes, how?
Please let me know if I need to supply more details.
Thanks
For this you can use the method branch as follow:
KStream<String, Either<Flower, Fruit>>[] flowerAndFruitStreams = inputMessages
.flatMapValues(flower -> List.<Either<Flower, Fruit>>of(Either.left(flower), Either.right(fromFlowerToFruit(flower))))
.branch((key, value) -> value.isLeft(), (key, value) -> value.isRight());
KStream<String, Either<Flower, Fruit>> flowerStream = flowerAndFruitStreams[0];
KStream<String, Either<Flower, Fruit>> fruitsStream = flowerAndFruitStreams[1];
Explanations
As you can see, the branch method returns a KStream<K, V>[] which means that the input is split in many streams based on the predicates applied to this method. Because of this, after you convert a flower to fruit you should return an object which either contains the flower, either the fruit so that to have a stream of the same objects type. For this we will borrow from functional programming the concept of Either which you can find it below:
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class Either<L, R> {
private final Optional<L> left;
private final Optional<R> right;
private Either(Optional<L> l, Optional<R> r) {
left = l;
right = r;
}
public static <L, R> Either<L, R> left(L value) {
return new Either<>(Optional.of(value), Optional.empty());
}
public static <L, R> Either<L, R> right(R value) {
return new Either<>(Optional.empty(), Optional.of(value));
}
public boolean isLeft() {
return left.isPresent();
}
public boolean isRight() {
return right.isPresent();
}
public L getLeft() {
return left.get();
}
public R getRight() {
return right.get();
}
public <T> T map(Function<? super L, ? extends T> leftFunc, Function<? super R, ? extends T> rightFunc) {
return left.<T>map(leftFunc).orElseGet(() -> right.map(rightFunc).get());
}
public <T> Either<T, R> mapLeft(Function<? super L, ? extends T> leftFunc) {
return new Either<>(left.map(leftFunc), right);
}
public <T> Either<L, T> mapRight(Function<? super R, ? extends T> rightFunc) {
return new Either<>(left, right.map(rightFunc));
}
public void apply(Consumer<? super L> leftFunc, Consumer<? super R> rightFunc) {
left.ifPresent(leftFunc);
right.ifPresent(rightFunc);
}
}
I didn't compiled the code, so please double check the syntax. This code is based on Java 13 and KafkaStreams 2.5.0 but should work also for newest versions.
I struggled to find a proper title for this question because the phenomenon I observed is very strange. Hence I skip explaining my problem literally and instead show you some (hopefully) self-describing code. Consider the following parameterized class:
public class GenericOptional<T> {
public GenericOptional(T someValue) {}
public T getValue() { return null; }
public Optional<String> getOptionalString() { return Optional.empty(); }
}
What I like to emphasize is that the return type Optional<String> of the method getOptionalString() does not depend on the type-parameter T.
Now have a look at the following code, which gets compiled inside Eclipse Luna 4.4.2 using Java 8u45:
public static void main(String[] args) {
Object obj = new GenericOptional<>(Boolean.TRUE);
GenericOptional go = (GenericOptional) obj;
Optional os = go.getOptionalString();
}
The local variable os has the type Optional without the type-parameter String! The Eclipse compiler has lost the information about the fixed type-parameter. Does anyone know why?
Now look at a second code example:
public static void main(String[] args) {
Object obj = new GenericOptional<>(Boolean.TRUE);
GenericOptional<?> go = (GenericOptional) obj;
Optional<String> os = go.getOptionalString();
}
By declaring the local variable go as GenericOptional<?> the return type of the method getOptionalString() now is Optional<String> as expected.
May anyone explain this behavior?
You are facing the behavior of raw types. When you are using a raw type, Generics are effectively turned off completely, regardless of whether there is a connection between the generic signature of the member and the type parameter of the class.
The reasoning behind this is that raw types are a feature for backward compatibility with pre-Generics code only. So either you have Generics or your don’t.
If the Generic method does not depend on the actual type parameter of the class, the problem is easy to fix:
GenericOptional<?> go = (GenericOptional<?>) obj;
Optional<String> os = go.getOptionalString();
Using <?> implies “I don’t know the actual type parameter and I don’t care but I’m using Generic type checking”.
It's not about Eclipse or anything, but about raw types.
Let's review this snippet:
public static void main(String[] args) {
Object obj = new GenericOptional<>(Boolean.TRUE);
GenericOptional go = (GenericOptional) obj;
Optional os = go.getOptionalString();
}
Here, you're creating a raw instance of GenericOptional, which means that the type-parameter information will be completely turned off. So, instantiating a raw GenericOptional means that the instance will expose the methods as following:
public class GenericOptional {
public GenericOptional(Object someValue) {}
public Object getValue() { return null; }
public Optional getOptionalString() { return Optional.empty(); }
}
However, if we now review the second snippet
public static void main(String[] args) {
Object obj = new GenericOptional<>(Boolean.TRUE);
GenericOptional<?> go = (GenericOptional) obj;
Optional<String> os = go.getOptionalString();
}
we can see that you're making a generic instance of GenericOptional. Even it's type-parameter is <?>, the compiler will not turn-off caring about type-parameters, so the instance will expose the getOptionalString() method parameterized, like this:
public Optional<String> getOptionalString() { return Optional.empty(); }
I am trying to overload the equals (==) operator on a custom "pair" type, as follows:
private typedef Data<A, B> = { a: A, b: B }
abstract Pair<A, B>(Data<A, B>) {
public var a(get, set):A;
public var b(get, set):B;
public function equals1(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
return (lhs.a == rhs.a && lhs.b == rhs.b);
}
#:op(X == Y) static public function equals(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
return (lhs.a == rhs.a && lhs.b == rhs.b);
}
public inline function new(a:A, b:B) this =
{ a: a, b: b };
inline function get_a():A
return this.a;
inline function get_b():B
return this.b;
inline function set_a(v:A):A
return this.a = v;
inline function set_b(v:B):B
return this.b = v;
}
I am new to abstract classes and operator overloading. But the overloading part is almost copied verbatim from the haxe documentation example. The overloaded operator is intended to test equality of two pairs. However, when I compiled the code to neko, I get an error:
Pair.hx:11: lines 11-13 : Class not found : A
I am confused here, because as you can see immediately above the overloaded function, there is an plain function version "equals1", which compiles just fine. As soon as I add #:op(X == Y), the template parameter A in Pair is "not found".
My questions is how to make this overloading work, and what went wrong in my code?
Thanks in advance.
P.S. I am using Haxe Compiler 3.0.1, installed on Windows.
--Update--:
I looked over the code again, it seems that declaring the equals function "static" is causing the problem. If I add "static" to the plain function,
static public function equals1(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
...
The same error is reported.
--update--:
The answer by back2dos is correct:
private typedef Data<A, B> = { a: A, b: B }
abstract Pair<A, B>(Data<A, B>) {
public var a(get, set):A;
public var b(get, set):B;
public function equals1(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
return (lhs.a == rhs.a && lhs.b == rhs.b);
}
#:op(X == Y) static public function equals<A, B>(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool {
return (lhs.a == rhs.a && lhs.b == rhs.b);
}
public inline function new(a:A, b:B) this =
{ a: a, b: b };
inline function get_a():A
return this.a;
inline function get_b():B
return this.b;
inline function set_a(v:A):A
return this.a = v;
inline function set_b(v:B):B
return this.b = v;
}
class Main {
static public function main() {
var p1 = new Pair(1,2), p2 = new Pair(1,5);
trace (p1 == p2);
}
}
Outputs:
Main.hx:34: false
Main.hx:35: true
The issue here is that type parameters declared on classes/abstracts are scoped to instances/values and thus are not defined in the static context.
Therefore, you need to parametrize the function:
#:op(X == Y) static public function equals1<A, B>(lhs:Pair<A,B>, rhs:Pair<A,B>):Bool;
Tried to run a project in IDEA and got an exception. Before that project was always run on Eclipse only.
Here is the example code:
package com.test;
public class GenericMethod {
private Object value;
#SuppressWarnings("unchecked")
public <X> X getValue() {
return (X) value;
}
public void setValue(Object value) {
this.value = value;
}
}
And the class that uses it:
package com.test;
public class GenericMethodTest {
public static void main(String[] args) {
GenericMethod method = new GenericMethod();
method.setValue(3);
int[] array = new int[] {1, 2};
array[0] = method.getValue();
System.out.println(array[0]);
}
}
So if you try to run this example in Eclipse - everything works fine. It compiles and shows you correct result.
But if you try to run it, say, in IDEA or if you just use ant or your console and javac command - you'll get compile error:
Buildfile: C:\test\build.xml
build:
[javac] C:\test\build.xml:13: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 1 source file to C:\test\bin
[javac] C:\test\src\com\test\GenericMethodTest.java:15: type parameters of <X>X cannot be determined; no unique maximal instance exists for type variable X with upper bounds int,java.lang.Object
[javac] array[0] = method.getValue();
[javac] ^
[javac] 1 error
What's happening?
Does Eclipse use it's own compiler?
Who has a bug?
In this case the code you posted has the bug. Eclipse let it slide (because you told it too with the #SuppressWarnings("unchecked")), but IDEA doesn't appear to be so forgiving. You can't cast value to X, because because of erasure you don't know what X is at runtime.
The proper way to do this would be to generify the class, and then store value as type X.
public class GenericMethod<X> {
private X value;
public X getValue() {
return value;
}
public void setValue(X value) {
this.value = value;
}
}
If you can't do that, then don't try to use generics here, just cast. Of course, if you were really really keen to use generics, you could also do something like this:
public <X> X getValue(Class<X> clazz) {
return clazz.cast(value);
}
But you'd have to have the class.
I am trying to refactor some of my code to use Func
I have created a sample to try to understand how it works but I am getting compilation error. In the e.g. below when I am trying to access the parameter attributes or return the return value the compiler complain.
Clarifications please.
using System;
namespace chsarp
{
class Program
{
static void Main(string[] args)
{
ParamInput input = new ParamInput();
input.ReservationID = 10;
Test testMethod = new Test();
Func<ParamInput, ReservationResult> methodToInvoke = testMethod.GetStatus;
ReservationResult result = TestFn(methodToInvoke, input);
}
static Result TestFn<Param, Result>(Func<Param, Result> methodToInvoke, Param parameter) where Result : new()
{
Result result = new Result();
try
{
result = methodToInvoke(parameter);
}
catch (Exception exception)
{
result.status = string.Format("Error-{0} during reserving {1}",
parameter.ReservationID,
exception.Message);
}
return result;
}
}
class Test
{
public ReservationResult GetStatus(ParamInput msg)
{
ReservationResult result = new ReservationResult();
result.status = string.Format("The ReservationID-{0}", msg.ReservationID);
return result;
}
}
class ParamInput
{
public int ReservationID { get; set; }
}
class ReservationResult
{
public string status { get; set; }
}
}
Annotated compile errors:
error CS1061: 'Result' does not contain a definition for 'status'
error CS1061: 'Param' does not contain a definition for 'ReservationID'
Code using generic type arguments can only compile if the compiler knows the member of the generic type. It doesn't know that the Result type argument has a "status" member. It certainly doesn't if you invoke TestFn<object, object>().
You'll need to use a constraint to make this work. You already do, but new() isn't strong enough. Something like "where Result : IResult" for example, where IResult is an interface type that has a status property. Or a base class. The compiler can now be 100% sure that any allowed concrete instance of the generic method will execute without causing runtime errors. Since it can only ever be compiled when it was invoked with a type that has a "status" property.
All the same applies to the Param type argument. The usefulness of a generic method here rapidly disappears when you do this, it is not the proper usage. Unless you can leverage IResult, like you can IEnumerable.
Compiles...
You ought to descibe what you aim is in your question.
See Hans' answer for details that might help you understand the error.
Your problem is that you're saying the function should take a Result that is instantiable, but you are not saying it has to have a property called "status".
namespace chsarp
{
class Program
{
static void Main(string[] args)
{
Func<int, string> m = Test.GetStatus;
var t = TestFn(m, 10);
}
static string TestFn<TParam>(Func<TParam, string> m, TParam p)
{
try { return m(p); }
catch (Exception exception)
{
return string.Format("Reserving \"{0}\" failure exception: {1}", p, exception);
}
}
}
static class Test
{
public static string GetStatus(int inp)
{
return string.Format("The ReservationID-{0}", inp);
}
}
}