I would like to create a lambda function in Java 8, get it's classname and then later instantiate the function again from its classname.
This is what I try:
import java.util.function.Consumer;
public class SimpleLambda
{
public static void call(String aLambdaClassName, String aArg) throws Exception
{
Class<Consumer<String>> lClass = (Class<Consumer<String>>) Class.forName(aLambdaClassName);
Consumer<String> newlamba = lClass.newInstance();
newlamba.accept(aArg);
}
public static void main(String[] args) throws Exception
{
{
// Attempt with a static method as lambda
Consumer<String> lambda = Host::action;
String classname = lambda.getClass().getName();
call(classname, "Hello world");
}
{
// Attempt with a locally defined lambda
Consumer<String> lambda = (s) -> { System.out.println(s); };
String classname = lambda.getClass().getName();
call(classname, "Hello world");
}
}
}
class Host {
public static void action(String aMessage) {
System.out.println(aMessage);
}
}
However, with this code (in both variants, using the static method reference and using the locally declared lambda), I get an exception:
Exception in thread "main" java.lang.ClassNotFoundException: mypackage.SimpleLambda$$Lambda$1/471910020
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at mypackage.SimpleLambda.main(SimpleLambda.java:12)
I would have expected that at I can at least re-instantiate the static method reference... nope, apparently not.
I have been using a similar approach with Groovy Closures and that worked nicely. So am I just doing something wrong with the Java 8 lambdas, or is it not possible to instantiate lambdas by name? I found some hints on the net that lambdas can be (de)serialized, so I would expect it should also be possible to instantiate them by name.
Well, it is a special property of Oracle’s JRE/OpenJDK to use “anonymous classes”, which can’t be accessed by name at all. But even without this, there is no reason why this ought to work:
Class.forName(String) tries to resolve the class via the caller’s ClassLoader. So even if lambda expressions were implemented using ordinary classes, there were not accessible if loaded via a different ClassLoader
Class.newInstance() only works if there is a public no-arg constructor. You can’t assume that there is a no-arg constructor nor that it is public
The assumption that the entire function’s logic has to reside in a single class is wrong. A counter-example would be java.lang.reflect.Proxy which generates interface implementations delegating to an InvocationHandler. Trying to re-instantiate such a proxy via its class name would fail, because you need the to pass the actual InvocationHandler instance to the proxy’s constructor. In principle, the JRE specific lambda expression implementation could use a similar pattern
Considering the points above, it should be clear that you can’t say that it worked with inner classes in general. There are a lot of constraints you have to fulfill for that.
Regarding Serialization, it works for serializable lambda expressions, because the persistent form is completely detached from the runtime implementation class, as described in this answer. So the name of the generated class is not contained in the serialized form and the deserializing end could have an entirely different runtime implementation.
Store the lambda instances in Map, keyed on the instance name. You can make the map globally available trough a singleton wrapper class (just watch out for synchronization issues).
class LambdaMap {
private HashMap<String, Consumer<String>> theMap;
private LambdaMap() {
theMap = new HashMap<>();
}
private static class INSTANCE_HOLDER {
private static LambdaMap INSTANCE = new LambdaMap();
}
public static LambdaMap getInstance() {
return INSTANCE_HOLDER.INSTANCE;
}
public Consumer<String> put(String key, Consumer<String> value) {
return theMap.put(key, value);
}
public static void Call(String aLambdaClassName, String aArg) {
Consumer<String> func = getInstance().theMap.get(aLambdaClassName);
if (func != null) {
func.accept(aArg);
}
}
}
class Host {
public static void action(String aMessage) {
System.out.println("Goodbye, " + aMessage);
}
}
public class GlobalLambdas {
public static void main(String[] args) {
LambdaMap.getInstance().put("print greeting", s -> {
System.out.println("Hello, " + s);
});
LambdaMap.getInstance().put("print goodbye", Host::action);
LambdaMap.Call("print greeting", "John");
LambdaMap.Call("print goodbye", "John");
}
}
run:
Hello, John
Goodbye, John
Related
If I declare this advice in my agent:
public static class SequenceAdvice {
#Advice.OnMethodEnter
static void enter(#Advice.This Object thiz,
#Advice.Origin Method method,
#Advice.AllArguments Object... args) {
StackWalker walker =
StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
walker.forEach(sf ->
System.out.println(sf.getClassName() + "." + sf.getMethodName())
);
}
}
as javac compiles the lambda expression into a private method (at least in OpenJDK 11):
public class SequenceAgent$SequenceAdvice {
...
private static void lambda$enter$0(java.lang.StackWalker$StackFrame);
...
}
when the agent is attached to a program and the program is executed, it causes the program to crash:
Exception in thread "main" java.lang.IllegalAccessError:
class DemoController tried to access private method
SequenceAgent$SequenceAdvice.lambda$enter$0(
Ljava/lang/StackWalker$StackFrame;)V
(DemoController and SequenceAgent$SequenceAdvice
are in unnamed module of loader 'app')
at DemoController.getDemos(DemoController.java)
at DemoMain.main(DemoMain.java:13)
Ideally I prefer not to use objects instead of lambda expressions to workaround this:
public static class SequenceAdvice {
public static Consumer<StackWalker.StackFrame> SF_CONSUMER =
new Consumer<>() {
#Override
public void accept(StackWalker.StackFrame sf) {
System.out.println(sf.getClassName() + "." + sf.getMethodName());
}
};
#Advice.OnMethodEnter
static void enter(#Advice.This Object thiz,
#Advice.Origin Method method,
#Advice.AllArguments Object... args) {
StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
walker.forEach(SF_CONSUMER);
}
}
A custom permissive security policy does not seem to resolve this error:
grant {
permission java.security.AllPermission;
};
Is there a way to temporarily disable this category of security checks (e.g. "access to private method")?
You cannot use lambda expressions from an advice. The lambda expression will be a part of the advice class that is not exposed to the target class. Instead, you will need to define a utility class that defines the lambda expressions code in public methods and reference those methods as method references.
You must then either:
add this class to the bootstrap class loader via Instrumentation.
add this class to the class loader of the instrumented class via Byte Buddy's Injector.
This way, the references are available to the instrumented class and can be executed.
Today I was thinking about a nice way to write less code for a common functionality that is required for different objects.
Inheritance can do the job but then the classes won't be able to inherit from anyone else, so I chose Interfaces.
So I have my interface with the functionality I will need for some objects:
public interface Test {
String message = "Hello from Interface!";
default void printMessage() {
System.out.println(message);
}
}
And then I can use it in any object without having to override/write any code more than just simply calling the method when needed:
public class TestingTest implements Test {
public String message = "Hello from Class!";
public TestingTest() {
printMessage();
}
public static void main(String[] args) {
new TestingTest();
}
}
It works like a charm! But... Then I thought, what if I want some of those objects to specify a different message without being required (optional), well first thing I thought was to shadow the interface variable, but it doesn't work, the default method keeps using the variable from the interface instead of the class variable (which shadowed it).
A solution of course would be to overload the printMessage method in the interface so it recieves the message as a parameter for when the user requires to specify the message, but is there any more elegant way? Something like simply just declaring a new message in the class?
The String message in the interface is static (AFAIK). So that scheme does not work.
You might do something (ugly) as:
default void printMessage(String... messages) {
if (messages.length == 0) {
messages = new String[] { "arrgg" };
}
System.out.println(messages[0]);
}
Fields have no inheritance, so the value can only stem from an overridable method like
public String message() { return "..."; }
What you want is a functionality in n classes that should also be modifiable, if needed.
To be honest, your example is a little bit abstract and thus my answer will be abstract, too.
public interface Test {
void printMessage();
default void printMessage(String message) {
System.out.println(message);
}
}
public class TestingTest {
private final test;
public TestingTest(Test test) {
this.test = test;
}
public void someMethod() {
test.printMessage("Hello from class");
}
}
Additionally, you would have a class that implements the interface and offers the message. This way you could group your objects, change the message, make more complex logging and you would actually see the dependency from outside.
In my opinion, you are misusing the interface. An interface offers public methods to call it from outside, but you want to use them inside like they were private functionalities for the class.
Just use objects instead.
I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.
I know Java basics, and now I'm in the journey of reading Effective Java. The book suggest using static factory methods instead of constructors. So I have Groovy code like this:
public class Anto {
public static void main(String[] args) {
println Java.javaInstance()
}
}
class Java {
public static Java javaInstance() {
return this
}
}
When I compile this, I get an error like this:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class Java' with class 'java.lang.Class' to class 'Java'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class Java' with class 'java.lang.Class' to class 'Java'
at Java.javaInstance(Anto.groovy:9)
at Java$javaInstance.call(Unknown Source)
at Anto.main(Anto.groovy:3)
Where am I making a mistake?
You can do it using return new Java();. Static methods don't have access to this.
EDIT:
These static factories are usually singletons, which means that only one instance of the class should be used (typically, a connection to a db for example). If you want do add this dimension to your Java class, use a private static attribute as follow:
class Java {
private static Java instance;
public static Java javaInstance() {
if(instance == null) {
instance = new Java();
}
return instance;
}
}
Creating a Singleton correctly can be easy to get wrong (especially in a multi-threaded environment), so you're probably better using the Singleton annotation that comes with Groovy rather than rolling your own:
public class Anto {
public static void main(String[] args) {
println Java.instance
}
}
#Singleton
class Java {
}
This transforms the Java class to:
class Java {
private static volatile Java instance
private Java() {}
static Java getInstance () {
if( instance ) {
instance
} else {
synchronized( Java ) {
if( instance ) {
instance
} else {
instance = new Java()
}
}
}
}
}
A good (albeit not specific to Groovy) example of a library that uses static factory methods that you could look at would be Google Guava. Guava uses this idiom in a number of places. For example, their Range class supports nine types of ranges, and if they used normal constructors, their signatures would conflict in several cases since the only thing you can use to distinguish them is their arguments.
Static methods on the other hand can also be distinguished by their name, so Guava defines different ones for each type of Range. Internally these methods still call a normal constructor, but it's not one that's publicly accessible.
import com.google.common.collect.Ranges
import com.google.common.collect.DiscreteDomains
final dom = DiscreteDomains.integers()
assert [1,2,3,4,5] as Set == Ranges.closed(1, 5).asSet(dom)
assert [2,3,4] as Set == Ranges.open(1, 5).asSet(dom)
This is a useful idiom, but not one that should just be automatically preferred over a normal constructor. In situations where a normal constructor would have sufficed, you've at best written more code than you needed and at worst have made extending the class impossible, since any subclasses will still need a public or protected constructor they can call.
You can't use this because static methods are not instance methods.
Each time you create a new instance of a particular class, that new object/instance as it's own state. this points to a particular instance.
Are you trying to make a singleton ? Meaning you just want a single instance of a class ?
class Singleton {
//static reference to a particular instance
private static Singleton instance;
//private constructor so that it cant be called outside this class scope
private Singleton();
//synchronized in case your working in threaded enviroment
public synchronized static Singleton getInstance()
{
if(NULL == instance)
{
instance = new Singleton();
}
return instance;
}
}
Is it even possible?
if you mean an anonymous function, and are using a version of Java before Java 8, then in a word, no. (Read about lambda expressions if you use Java 8+)
However, you can implement an interface with a function like so :
Comparator<String> c = new Comparator<String>() {
int compare(String s, String s2) { ... }
};
and you can use this with inner classes to get an almost-anonymous function :)
Here's an example of an anonymous inner class.
System.out.println(new Object() {
#Override public String toString() {
return "Hello world!";
}
}); // prints "Hello world!"
This is not very useful as it is, but it shows how to create an instance of an anonymous inner class that extends Object and #Override its toString() method.
See also
JLS 15.9.5 Anonymous Class Declarations
Anonymous inner classes are very handy when you need to implement an interface which may not be highly reusable (and therefore not worth refactoring to its own named class). An instructive example is using a custom java.util.Comparator<T> for sorting.
Here's an example of how you can sort a String[] based on String.length().
import java.util.*;
//...
String[] arr = { "xxx", "cd", "ab", "z" };
Arrays.sort(arr, new Comparator<String>() {
#Override public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
System.out.println(Arrays.toString(arr));
// prints "[z, cd, ab, xxx]"
Note the comparison-by-subtraction trick used here. It should be said that this technique is broken in general: it's only applicable when you can guarantee that it will not overflow (such is the case with String lengths).
See also
Java Integer: what is faster comparison or subtraction?
Comparison-by-subtraction is broken in general
Create a Sorted Hash in Java with a Custom Comparator
How are Anonymous (inner) classes used in Java?
With the introduction of lambda expression in Java 8 you can now have anonymous methods.
Say I have a class Alpha and I want to filter Alphas on a specific condition. To do this you can use a Predicate<Alpha>. This is a functional interface which has a method test that accepts an Alpha and returns a boolean.
Assuming that the filter method has this signature:
List<Alpha> filter(Predicate<Alpha> filterPredicate)
With the old anonymous class solution you would need to something like:
filter(new Predicate<Alpha>() {
boolean test(Alpha alpha) {
return alpha.centauri > 1;
}
});
With the Java 8 lambdas you can do:
filter(alpha -> alpha.centauri > 1);
For more detailed information see the Lambda Expressions tutorial
Anonymous inner classes implementing or extending the interface of an existing type has been done in other answers, although it is worth noting that multiple methods can be implemented (often with JavaBean-style events, for instance).
A little recognised feature is that although anonymous inner classes don't have a name, they do have a type. New methods can be added to the interface. These methods can only be invoked in limited cases. Chiefly directly on the new expression itself and within the class (including instance initialisers). It might confuse beginners, but it can be "interesting" for recursion.
private static String pretty(Node node) {
return "Node: " + new Object() {
String print(Node cur) {
return cur.isTerminal() ?
cur.name() :
("("+print(cur.left())+":"+print(cur.right())+")");
}
}.print(node);
}
(I originally wrote this using node rather than cur in the print method. Say NO to capturing "implicitly final" locals?)
Yes, if you are using Java 8 or above. Java 8 make it possible to define anonymous functions, which was impossible in previous versions.
Lets take example from java docs to get know how we can declare anonymous functions, classes
The following example, HelloWorldAnonymousClasses, uses anonymous
classes in the initialization statements of the local variables
frenchGreeting and spanishGreeting, but uses a local class for the
initialization of the variable englishGreeting:
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
public void sayHello() {
class EnglishGreeting implements HelloWorld {
String name = "world";
public void greet() {
greetSomeone("world");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hello " + name);
}
}
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
HelloWorld spanishGreeting = new HelloWorld() {
String name = "mundo";
public void greet() {
greetSomeone("mundo");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hola, " + name);
}
};
englishGreeting.greet();
frenchGreeting.greetSomeone("Fred");
spanishGreeting.greet();
}
public static void main(String... args) {
HelloWorldAnonymousClasses myApp =
new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
Syntax of Anonymous Classes
Consider the instantiation of the frenchGreeting object:
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
The anonymous class expression consists of the following:
The new operator
The name of an interface to implement or a class to extend. In this
example, the anonymous class is implementing the interface
HelloWorld.
Parentheses that contain the arguments to a constructor, just like a
normal class instance creation expression. Note: When you implement
an interface, there is no constructor, so you use an empty pair of
parentheses, as in this example.
A body, which is a class declaration body. More specifically, in the
body, method declarations are allowed but statements are not.
You can also use Consumer and BiConsumer type regarding to how many parameters you need. Consumer accepts one parameter, BiConsumer accepts two.
public void myMethod() {
// you can declare it here
Consumer<String> myAnonymousMethod = s -> {
System.out.println(s);
};
// you can call it here
muAnonymousMethod.apply("Hello World");
}