As per the documentation the difference between
orElse and orElseGet is in the fact that in the case of orElseGet(x) the x part
is called incase Optional.isPresent is false
But in below program in case the supplier x is a another method call in orElseGet(x)
the x part is called even if Optional.isPresent is true similiar to the behavior of
orElse(). Why is the behavior of orElseGet() in this scenario same as orElse()?
import java.util.Optional;
import java.util.function.Supplier;
public class TestOrElseGet {
public static void main(String[] args) {
checkOrElseGet();
}
private static void checkOrElseGet() {
System.out.println("------Start Optional.orElseGet-------");
String first= getFirst();
// else part is not initialized
// else doesn't get initialized if its inside OrElseGet()
String myOptional = Optional.of(first).orElseGet(() -> {
System.out.println("OrElseGet - Create & Return Second");
return "Second";
});
System.out.println(
"Result of OrElseGet " + myOptional);
// if supplier is a method then its gets called
myOptional = Optional.of(getThird()).orElseGet(getNumberFromSupplier());
System.out.println(" Result of OrElseGet is "
+ myOptional);
Optional<String> empty = Optional.empty();
// OrElseGet - else is initialized as optional was empty
myOptional = empty.orElseGet(() -> {
System.out.println("OrElseGet - Create & Return Fourth");
return "Four" ;
});
System.out.println("Result of OrElseGEt is " + myOptional);
System.out.println("----------Completed-----------");
}
private static Supplier<String> getNumberFromSupplier() {
System.out.println("Inside Supplier call..");
return ()->{
return "Supplying TEN";
};
}
private static String getThird() {
System.out.println("Inside Third");
return "Third";
}
private static String getFirst() {
System.out.println("Inside GetFirst");
return "First";
}
}
The contract of orElseGet(Supplier) says the →Supplier← will only be invoked if the value is not present. More specifically, it's the Supplier#get() method that's lazily invoked (on the Supplier instance passed to orElseGet).
And your code shows that. However, this bit:
private static Supplier<String> getNumberFromSupplier() {
System.out.println("Inside Supplier call..");
return ()->{
return "Supplying TEN";
};
}
Indicates a misunderstanding. Your println log says "Inside Supplier call...", but at that point you are not inside the supplier. The Supplier is the lambda expression and is returned from the method. That said, you're correct that the getNumberFromSupplier method is invoked eagerly, but that's because its return value is passed as an argument to the orElseGet call. Even for orElseGet(() -> ... ) the Supplier is created eagerly for the same reason.
If you had the following:
private static Supplier<String> getNumberFromSupplier() {
// Remember, the lambda is the implementation of Supplier#get()
return () -> {
System.out.println("Inside Supplier call...");
return "Supplying TEN";
};
}
Then you'd see the Supplier is lazily invoked. Notice the new location for the println call. Additionally, the method would be better named getNumberSupplier as that's a more apt description of what the method actually does.
Related
In the class below, I pass the method reference WordCounterEx::accumulate as second parameter to the reduce method. The signature of reduce method is:
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
Thus the second parameter of reduce method, must fulfil the BiFunction recipe.
But the passed accumulate method is not BiFunction (it has only one parameter). Why it still compile?
public class WordCounterEx {
private final int counter;
private final boolean lastSpace;
public WordCounterEx(int counter, boolean lastSpace) {
this.counter = counter;
this.lastSpace = lastSpace;
}
public int countWords(Stream<Character> stream) {
WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true),
//HOW CAN THIS WORK? here must come BiFunction - R apply(T t, U u);
WordCounterEx::accumulate,
WordCounterEx::combine);
return wordCounter.counter;
}
public WordCounterEx accumulate(Character c) {
if(Character.isWhitespace(c)) {
return lastSpace ?
this :
new WordCounterEx(counter, true);
} else {
return lastSpace ?
new WordCounterEx(counter+1, false) :
this;
}
}
public WordCounterEx combine(WordCounterEx wordCounter) {
return new WordCounterEx(counter + wordCounter.counter
,wordCounter.lastSpace /*does not matter*/);
}
}
accumulate() is an instance method, and you refer to it by class name and method name (not by instance and method name). So if I wanted to call the method you are giving me, I would usually do myEx.accumulate(myCh). Thus I provide two things, the WordCounterEx instance and the character. Therefore, used this way the method counts as a BiFunction<WordCounterEx, ? super Character, WordCounterEx>.
If instead you had given me for example this::accumulate, the object to call the method on would have been given (this), and it could no longer be used as a BiFunction (in my Eclipse I get “The method reduce(U, BiFunction, BinaryOperator) in the type Stream is not applicable for the arguments (WordCounterEx, this::accumulate, WordCounterEx::combine)”).
The WordCounterEx#countWords method can be rewritten as follows:
public int countWordsWithInstance(Stream<Character> stream) {
WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true),
this::accumulate,
WordCounterEx::combine);
return wordCounter.counter;
}
public WordCounterEx accumulate(WordCounterEx wc,Character c) {
if(Character.isWhitespace(c)) {
return wc.lastSpace ?
wc :
new WordCounterEx(wc.counter, true);
} else {
return wc.lastSpace ?
new WordCounterEx(wc.counter+1, false) :
wc;
}
}
In this case the accumulate method must have WordCounterEx wc in its signature
I have class myClass extends TreeItem<file> to be used as datamodel in a TreeTableView mostly following the example here: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TreeItem.html .
public class myTreeItem extends TreeItem<File>
private boolean isLeaf;
private boolean isFirstTimeChildren = true;
private boolean isFirstTimeLeaf = true;
#Override public ObservableList<TreeItem<File>> getChildren() {
// ... full code see link to Oracle documentation
return super.getChildren();
}
private ObservableList<TreeItem<File>> buildChildren(TreeItem<File> TreeItem) {
// ... full code see link to Oracle documentation
};
}
I have added a function to add children to this item. I have problems with the correct update of the TreeTableView. More details see in the code and comments below:
public void addChild(String name) {
itemManger.addChild(this.getValue(), name); // Generate Child
isFirstTimeChildren = true; // Ensure that buildChildren() is called, when getchildren() is called.
// getChildren(); // If I would activate this line,
// all listeners would be notified
// and the TreeTableView is updated.
// This is most likely due to the call super.getChildren();
// However I want to throw the event on my own in order
// to avoid the extra call of this.getChildren(). Here is my
// (not sufficent) try:
EventType<TreeItem.TreeModificationEvent<MLDCostumizableItem>> eventType = TreeItem.treeNotificationEvent();
TreeModificationEvent<MLDCostumizableItem> event = new TreeModificationEvent<>(eventType,this);
Event.fireEvent(this, event);
// Here I don't know how to get a value for target.
// Is there some standard target, which includes all FX components?
}
How the correctly throw this event?
Seems that I had a missunderstanding in how the triggering works in JavaFX. Now the most simple solution is:
#Override // Taken from Link
public void update(Observable observ, Object arg1) {
if (observ!=this.item)
{
LOGGER.error(new MLDConnectionException("Unexpected call of update() with observ = " + observ.toString()));
return;
}
// Build new Chidren list
try {
super.getChildren().removeIf((x) -> true); // empty list
super.getChildren().setAll(buildChildren(this));
} catch (MLDConnectionException e) {
LOGGER.error("Error when genereting children List: ", e);
}
}
public File addChild(String name) throws MLDException {
File newChild = itemManger.addChild(item, name);
update(this.item, null);
return newChild;
}
I'm using the Mongo c# driver 2.0 and am running into BsonSerializer registration issues when registering AbstractClassSerializers for my Id value objects.
MongoDB.Bson.BsonSerializationException: There is already a serializer registered for type HistoricalEventId.
When I peek into the BsonSerializer I'm seeing that a BsonClassMapSerializer is already registered for my type.
I'm assuming that a BsonClassMapSerializer is being created for my entity types and it's also creating a BsonClassMapSerializer for the Id field as well. Has anyone run into this before? The Bson serializer code is shown below if that helps.
Sorry if the formatting is wrong, c# doesn't seem to be showing up well.
HistoricalEventIdBsonSerializer
public class HistoricalEventIdBsonSerializer : ToObjectIdBsonSerializer<HistoricalEventId>
{
public override HistoricalEventId CreateObjectFromObjectId(ObjectId serializedObj)
{
HistoricalEventId parsedObj;
HistoricalEventId.TryParse(serializedObj, out parsedObj);
return parsedObj;
}
}
ToObjectIdBsonSerializer
public abstract class ToObjectIdBsonSerializer<T> : AbstractClassSerializer<T> where T : class
{
private static readonly Type _convertibleType = typeof(IConvertible<ObjectId>);
public abstract T CreateObjectFromObjectId(ObjectId serializedObj);
public override T Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var bsonType = context.Reader.GetCurrentBsonType();
ObjectId value;
switch (bsonType)
{
case BsonType.Undefined:
value = ObjectId.Empty;
context.Reader.ReadUndefined();
break;
case BsonType.Null:
value = ObjectId.Empty;
context.Reader.ReadNull();
break;
case BsonType.ObjectId:
value = context.Reader.ReadObjectId();
break;
case BsonType.String:
value = new ObjectId(context.Reader.ReadString());
break;
default:
throw new NotSupportedException("Unable to create the type " +
args.NominalType.Name + " from the bson type " + bsonType + ".");
}
return this.CreateObjectFromObjectId(value);
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value)
{
if (value == null)
{
context.Writer.WriteObjectId(ObjectId.Empty);
}
else
{
if (!_convertibleType.IsAssignableFrom(args.NominalType))
{
throw new NotSupportedException("The type " + args.NominalType.Name +
" must implement the " + _convertibleType.Name + " interface.");
}
var typedObj = (IConvertible<ObjectId>)value;
context.Writer.WriteObjectId(typedObj.ToValueType());
}
}
}
IConvertible
public interface IConvertible<out T>
{
T ToValueType();
}
My assumption must have been correct because I just fixed this by doing the BsonSerializer registration before creating the MongoClient and getting the database. Hopefully this will help someone else.
Update (Stupidity Fail)
So then, in all of my convoluted formula code, I neglected the fundamental principles of C#.
Methods may return a value.
static dynamic Construct<T>(T expression){
return expression;
}
Then just use that, instead of a variable ...
Method = Construct<Action<Context, string, int>>(
(context, key, change) =>
{
context.Saved[key] += change;
Console.WriteLine("{0}'s saved value of {1} was changed by {2}, resulting in {3}",
context.Name, key, change, context.Saved[key]);
}
)
I have a situation where I need to call upon methods that don't exist as compiled methods, but rather need to be able to accept an array of parameters and execute as an anonymous function. I thought I had it worked out, but I am running into an issue with the following..
public static IDictionary<string, Function> Expressions =
new Dictionary<string, Function> {
{
"Increase [X] by value of [Y]",
new Function {
Name = "Increase [X] by [Y]",
Parameters = 2,
Types = new List<Type>{
typeof(Param),
typeof(Param)
},
Method = (Expression<Func<Context, Param, Param, bool>>)
((context, x, y) => {
Console.WriteLine("test"); // this is where I need to do stuff...
})
}
}
};
I am being told that a Method name is expected on this. The problem is that Context will be passed in by the object that takes the function and runs its method, because the Context object cannot be pre-bound (it has to be late bound). So basically I package up the trailing 2 parameters (Param) and (Param) in this case and create a function to execute against them.
The database stores those parameters, and then invokes the method passing in the appropriate Context as the first parameter by using Compile().DynamicInvoke(object[] params).
Can anyone give me a hand here as to why I cannot put any kind of logic in between my { }?
UPDATE
Okay, since I've been told this example is unclear, here is an entire program running start to finish that illustrates what I am trying to accomplish.
public class Program {
static void Main(string[] args) {
// simple object stored in database.
var ctx = new Context {
Name = "Ciel",
Saved = new Dictionary<string, int> {
{ "First", 10 },
{ "Second", 20 }
}
};
// simple object stored in database.
var rule = new Rule {
Equations = new List<Equation> {
new Equation {
Parameters = new List<object>{
"First",
5
},
Name = "Increase [X] by value of [Y]"
}
}
};
// =======================================
// runtime environment!!!
// =======================================
var method = Evaluations.Expressions[rule.Equations[0].Name].Method;
var parameters = rule.Equations[0].Parameters;
// insert the specific context as the first parameter.
parameters.Insert(0, ctx);
method.DynamicInvoke(parameters.ToArray());
Console.ReadLine();
}
}
public class Function {
public string Name { get; set; }
public dynamic Method { get; set; }
}
public class Equation {
public string Name { get; set; }
// these objects will be simple enough to serialize.
public IList<object> Parameters { get; set; }
public Function Function { get; set; }
}
public class Context {
public string Name { get; set; }
// this is a crude example, but it serves the demonstration purposes.
public IDictionary<string, int> Saved { get; set; }
}
public class Rule {
// again, a crude example.
public IList<Equation> Equations { get; set; }
}
public static class Evaluations {
static Action<Context, string, int> expr = (context, key, change) =>
{
context.Saved[key] += change;
Console.WriteLine("{0}'s saved value of {1} was changed by {2}, resulting in {3}",
context.Name, key, change, context.Saved[key]);
};
public static IDictionary<string, Function> Expressions =
new Dictionary<string, Function> {
{
"Increase [X] by value of [Y]",
new Function {
Name = "Increase [X] by [Y]",
Method = expr
}
}
};
}
Four problems:
You're trying to create an expression tree from a lambda expression with a statement body (i.e. braces). C# doesn't allow this - you can only convert a statement lambda into a delegate, not an expression tree
Your lambda body doesn't return a Boolean value
You're trying to call an Expression<Func<Context, Param, Param, bool>> as if it were a method with a bool parameter. It's not at all clear what you're trying to do there.
Even if the third point were valid, I suspect you'd need more brackets.
If you refactor your code to make it a little more readable and manageable, you'll probably be well on your way to solving your problem. Rather than having one mammoth C# statement with a single semicolon, split it up into several lines. Something like this:
public static Dictionary<string, Function> Expressions = getExpressions();
private static Dictionary<string, Function> getExpressions()
{
var method = (Expression<Func<Context, Param, Param, bool>>)
((context, x, y) => {
Console.WriteLine("test"); // this is where I need to do stuff...
})(true);
var func = new Function()
{
Name = "Increase [X] by [Y]",
Parameters = 2,
Types = new List<Type>
{
typeof(Param),
typeof(Param)
},
Method = method
};
var dict = new Dictionary<string, Function>();
dict["Increase [X] by value of [Y]"] = func;
return dict;
}
Note: my syntax could be incorrect, but you get the general idea.
A task at university was to implement a simple proxy generator / interceptor mechanism using Reflection.Emit.
I came up with the following program.
It seems to work just fine inside Visual Studio in debug mode [F5] (Debug -> Start Debugging) but crashes most of the time when started without debugging [Ctrl + F5] (Debug -> Start Without Debugging).
What is the difference between these two modes? (I do not refer to Debug <> Release mode).
The issue occurs on multiple machines/setups (Win XP SP3 32bit and 64bit, Windows 7 32bit).
Click for pastebin.
// The proxy generator; I assume that the error is buried along the lines emitting the IL code
public static class ProxyGenerator
{
public static T Create<T>(object obj, IInterception interception)
{
Type type = obj.GetType();
TypeBuilder proxy = DefineProxy(type);
FieldBuilder wrappedField = DefinePrivateField(proxy, "wrappedObject", type);
FieldBuilder interceptionField = DefinePrivateField(proxy, "interception", interception.GetType());
DefineConstructor(proxy, wrappedField, interceptionField);
DefineInterfaceMethods(type, proxy, wrappedField, interceptionField);
return (T) Activator.CreateInstance(proxy.CreateType(), obj, interception);
}
private static TypeBuilder DefineProxy(Type type)
{
var assemblyName = new AssemblyName {Name = "GeneratedProxyAssembly"};
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("GeneratedProxyModule");
return moduleBuilder.DefineType(
type.Name + "Proxy",
type.Attributes,
typeof (object),
type.GetInterfaces());
}
private static FieldBuilder DefinePrivateField(TypeBuilder typeBuilder, string fieldName, Type fieldType)
{
return typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Private);
}
private static void DefineConstructor(TypeBuilder typeBuilder, params FieldBuilder[] parameters)
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, parameters.Select(f => f.FieldType).ToArray());
// Emit constructor
ILGenerator g = ctor.GetILGenerator();
// Load "this" pointer and call base constructor
g.Emit(OpCodes.Ldarg_0);
g.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0]));
// Store parameters in private fields
for (int i = 0; i < parameters.Length; i++)
{
// Load "this" pointer and parameter and store paramater in private field
g.Emit(OpCodes.Ldarg_0);
g.Emit(OpCodes.Ldarg, i + 1);
g.Emit(OpCodes.Stfld, parameters[i]);
}
// Return
g.Emit(OpCodes.Ret);
}
private static void DefineInterfaceMethods(Type type, TypeBuilder proxy, FieldInfo wrappedField, FieldInfo interceptionField)
{
// Loop through all interface methods
foreach (MethodInfo interfaceMethod in type.GetInterfaces().SelectMany(i => i.GetMethods()))
{
MethodInfo method = type.GetMethod(interfaceMethod.Name);
MethodBuilder methodBuilder = proxy.DefineMethod(
method.Name,
method.Attributes,
method.ReturnType,
method.GetParameters().Select(p => p.ParameterType).ToArray());
// Emit method
ILGenerator g = methodBuilder.GetILGenerator();
// Intercept before
EmitMethodCallOnMember(g, interceptionField, "Before", false);
// Delegate method call
EmitMethodCallOnMember(g, wrappedField, method.Name, true);
// Intercept after
EmitMethodCallOnMember(g, interceptionField, "After", false);
// Return
g.Emit(OpCodes.Ret);
}
}
private static void EmitMethodCallOnMember(ILGenerator g, FieldInfo field, string methodName, bool delegateParameters)
{
// Load "this" pointer to get address of field
g.Emit(OpCodes.Ldarg_0);
g.Emit(OpCodes.Ldflda, field);
MethodInfo method = field.FieldType.GetMethod(methodName);
if (delegateParameters)
{
// Load method parameters
for (int i = 0; i < method.GetParameters().Length; i++)
{
g.Emit(OpCodes.Ldarg, i + 1);
}
}
// Emit call
g.Emit(OpCodes.Call, method);
}
}
// Some infrastructure
public interface IInterception
{
void Before();
void After();
}
public class LogInterception : IInterception
{
public void Before()
{
Console.WriteLine("Before ... ");
}
public void After()
{
Console.WriteLine("... After");
}
}
public interface ITest
{
string DoSomething(string s1, string s2);
}
public class Test : ITest
{
public string DoSomething(string s1, string s2)
{
Console.WriteLine("... doing something ...");
return s1 + s2;
}
}
// The test program, expected output is down below
internal class Program
{
internal static void Main(string[] args)
{
var test = new Test();
var proxy = ProxyGenerator.Create<ITest>(test, new LogInterception());
Console.WriteLine(test.DoSomething("Hello", " World"));
Console.WriteLine("----------------------------------------");
Console.WriteLine(proxy.DoSomething("Hello", " World"));
Console.ReadKey();
}
}
Another question: What's the best way to narrow down such issues?
I tried to save the generated assembly to disk and open the resulting dll in Reflector but it appeared to be empty.
As mentioned above, when started in debug mode the program seems to work and prints the following output.
... doing something ...
Hello World
----------------------------------------
Before ...
... doing something ...
... After
Hello World
Thanks for your time.
Try to explicitly set x86 mode on project settings tab.
I got the fatal exception only when run program in x64 or AnyCpu mode.
Ah, I've got it. Replace Ldflda with Ldfld. It works fine even without debugger (I just ran .exe).
Ldflda is for fields you pass into method as parameters with ref or out keyword.