This question already has answers here:
Behavior of Functional Interface and Method Reference
(2 answers)
Closed 7 years ago.
This code uses method reference to an instance method of a particular object:
public class Main {
public static void main(String[] args) {
One one=new One();
// F f = ()->{one.bar();}; //previous wrong syntax
F f = one::bar; //4
f.foo();
}
}
class One{void bar(){}}
interface F{void foo();}
I know it works. But I'm not being able to understand why and how.
What I can't understand is how is it possible that F.foo() method is using a reference to an object that is not an argument to the method itself (signature is not void foo(One one)).
At line 4 I am
creating an instance of a class that implements F interface
implementing the method by using the reference one to invoke bar() method
But how can foo() have a scope on one reference? Am I being wrong trying to translate this solution to a "traditional, explicit implementation"? If not, what would it be the "explicit counterpart"?
Your lambda is compiled into private synthetic method which looks like this:
private static void lambda$1(One one) { one.bar(); }
At runtime the lambda expression is translated into runtime representation during the first time you execute this code. Current runtime representation in OpenJDK 8 is an anonymous class which takes the captured variables as constructor parameters and stores them into fields, then calls the lambda body method generated by compiler. Something like this is generated:
class lambda12345678 implements F {
private One arg1;
lambda12345678(One arg1) {this.arg1 = arg1;}
public void foo() {
lambda$1(arg1);
}
}
And call site is technically replaced with constructor call, thus instead of
F f = ()->{one.bar();};
You effectively have
F f = new lambda12345678(one);
Note that if your lambda does not capture context, it works in more efficient way: only one object is created and reused. But in your example as lambda behavior depends on external state, every time the new instance is created.
Related
This question already has answers here:
Difference between Static methods and Instance methods
(10 answers)
Closed 1 year ago.
What is the point of creating a class object to call a method in another file when I can just call the file and do the exact same thing?
What I've seen and been taught is that in order to call a method from another file you need to make a class object first, then you call the method using the object
Say you have a method in "FileTwo"
public class FileTwo
{
public static void method
{
}
}
So if I wanted to call "method" in another file, "FileOne" I'd call it like this
public class FileOne
{
FileTwo file = new FileTwo;
public static void main(String[] args)
{
file.method();
}
}
But I'm able to do the same thing just by calling the file itself
public class FileOne
{
public static void main(String[] args)
{
FileTwo.method();
}
}
So what's the point of creating the class object?
the method you're calling is static, means you can call it from both instances or types.
Normally, you use static methods to compute on a facade that doesn't require the object instance to operate.
class math {
private int x;
public math(int init){
x = init;
}
public int sum(int a, int b) {
return a + b;
}
public static int sumInternal(int a) {
return x + a;
}
}
math.sum(4, 6) doesn't require an instance of math
math.sumInternal(4) requires an instance of math. Notice that it has been declared static
What is the point of creating a class object to call a method in another file when I can just call the file and do the exact same thing?
Terminology:
class instance, or simply object. The phrase "class object" suggests an instance of class java.lang.Class.
invoke a method. Everyone will understand "call", but it's not standard in this context
methods belong to classes and / or to instances, not to files. This makes a difference for several reasons, not least that one file can contain multiple classes.
To rephrase the question, then:
What is the point of creating an instance of a class to invoke one of its methods when I can just invoke the same method via the class's name, instead?
Answer: when the method you want to invoke is static, there is no special reason to invoke it through an instance, and some style guides specify that in fact, you should not do so. However, most methods of most classes are not static (they are instance methods) and such methods can be invoked only on instances.
As a very rough guide, one creates and uses static methods for operations that impact all objects of a given class or none at all, whereas one uses instance methods for operations of or on one specific instance of that class.
I have a software specification document for a specific library in java which helps collecting data from a biosensor and has a class called 'Patch'. The document specifies:
Following is the constructor of Patch class:
Patch(JSONObject options, (JSONObject)->onDiscovery,(JSONObject)->ondata,(JSONObject)->onStatus)
Where
JOSNObject options: options settings for the object
(JSONObject)->onDiscovery: Callback for receiving the sensor info as a JSONObject,
(JSONObject)->ondata: Callback for receiving the sensor data as a JSONObject,
(JSONObject)->onStatus: Callback for receiving the global errors as a JSONObject
It should be called as
Patch patch=newPatch(jsonConfigObject, discoveryObject, streamObject, status);
The concerned fellow stated that these callbacks shall be just lambda expressions.
Now what I understand is:
Constructor takes 4 args:
An empty JSON object,
Callback function reference
Callback function reference
Callback function reference
Am new to Callback implementation so am not able to figure out:
how shall I implement this one in my code?
Do I have to create the functional interfaces for each of those callback methods?
Lets say I have just imported the library, what shall I do next?
The objective of lambda expressions is to denote methods that the Patch-object can call (back) at certain events. In contrast to other programming languages it was not possible to pass functions as parameters to constructors or methods in Java. Thus it was necessary to create an object of a class that implements a certain interface (or is otherwise known to have a certain method by type) and to pass it to the method or constructor as a parameter. The method can then be called at the passed object when the event occurs.
The functional interface is already there. You do not need to create it by yourself. It has been already used in the signature of the constructor of Patch (the types of the last three parameters to the constructor). Functional interfaces are types which have exactly one abstract method that has to be overridden.
Lets suppose the functional interface looks like this:
interface Callback { // could of course have a different name
public void call(JSONObject o);
}
It is not necessary to add the #FunctionalInterface-annotation. It would only prevent the interface from later modifications, namely adding further abstract methods.
It seems reasonable to assume that the abstract method does not have a return value (but you need to check this. When you use lambda expressions you do not need to know what the actual method name (here call) is.
Although most handy it is not necessary to call the constructor with lambda expressions for the last three parameters. Other possibilities include a method reference (using ::), anonymous classes, and instantiating a newly defines class.
Of course you need to know what should happen when the three events occur. Lets say that you have already three methods that provide the necessary functionality. Probably a JSONObject that contains information about the event is necessary to do something useful.
class Main {
static void onDiscovery(JSONObject o) {...}
static void onData(JSONObject o) {...}
static void onStatus(JSONObject o) {...}
}
It is not necessary that the three methods have exactly these names nor that they are static.
In the main method of this class (or somewhere else) could happen:
public static void main(String[] args) {
JSONObject o = // ...
Patch p = new Patch(o,
(x) -> Main.onDiscovery(x), // (1) lambda expr. (Main. can be omitted)
Main::onData, // (2) method reference
new Callback() { // (3) anonymous inner class
public void call(JSONObject x) {
Main.onStatus(x);
}
});
//...
}
(1)-(3) show alternative ways to pass an object of type Callback.
(1) has the advantage that shorter implementations could go right here instead of calling onDiscovery(x). If you have more than one statement you need curly brackets around the statements and ";" after each statement:
(x) -> {
System.out.println("discovery event");
System.out.println(x.getXYZ());
// ...
}
(2) has the advantage to be super concise. If you do not have a static method to reference, a object reference can also be used to denote the object on which the method should be called.
(3) anonymous inner classes are would normally not be used anymore for functional interfaces. If the interface / abstract class has more abstract methods but one it is still necessary to use anonymous inner classes.
class Main {
void onData(JSONObject o) { ... }
// ...
public static void main(String[] args) {
var m = new Main();
var o = new JSONObject(); // or whatever
var p = new Patch(o,
(x) -> m.onDiscovery(x),
m::onData;
new Callback() {
public void call(JSONObject x) {
m.onStatus(x);
}
});
}
}
This question already has answers here:
:: (double colon) operator in Java 8
(17 answers)
Closed 2 years ago.
I have a class constitues 2 methods static and non static respectively, as per my limited knowledge submit method accepts runnable,callable instance directly or through lamba expression.
Today I came to know that we can even call or trigger static as well as non static method directly by using double colon which has been added in java 8.
I was just wondering how this works, there is no run method in my class and it doesn't implements runnable and even I'm not using lamba?
Is it a good practice to use :: or one should pass the runnable or callable instance.
Is there any other way to call a method inside submit() rather passing an instance?
Class A {
public static void printSomething(){
System.out.println("Staitc Method");
}
public void print()
{
System.out.println("Non-Staitc Method");
}
}
psvm()
{
A a = new A():
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(A::printSomething); //Expected is runnable or callable task
es.submit(a::print);
}
A::printSomething is called a method reference. When you use a method reference in a place that expects an interface like Runnable or Callable, Java automatically creates an implementation of that interface that calls the method.
That is,
es.submit(A::printSomething);
behaves the same as
es.submit(new Runnable() {
public void run() {
A.printSomething();
}
});
but is easier to read and does not create a new class everywhere you use it, or a new object instance every time it's called.
You can read more about method references in
The tutorial from Oracle
This write-up on Baeldung
Another way of achieving the same is using lambda expressions such as:
es.submit(() -> A.printSomething());
Since Runnable is a functional interface, you can use lambda expressions or method references that fit it even if the method name doesn't match. Therefore any no-arg void method can be used as a Runnable.
Runnable r1 = () -> a.printSomething();
Runnable r2 = A::printSomething(); // Method reference, short-hand
Runnable r3 = () -> A.printSomething(); // Same as r2, but as explicit lambda expression
The reason why the method reference works even though the class does not implement a void run() method is because what matters for Functional Interface assignment is the method signature and not the method names.
The method signature of A's printSomething matches Runnable's run and for that reason it works. Notice this only works with Functional Interfaces (i.e. those with only one method, said method method not having a default implementation).
Is it good practice? It's a matter of style but it is definitely not bad practice to use method references, and they're also more concise than left -> right lambdas.
I suggest you try this out yourself so you're clear on the rules.
public class FunctionalInterfaceDemo {
public static class SimpleClass {
public static void doItStatic() {
}
public void doItNonStatic() {
}
}
interface MyOwnFunctionalInterface {
void methodA();
}
interface NotAFunctionalInterface {
void methodA();
void methodB();
}
interface AlsoNotAFunctionalInterface {
default void methodA() {
}
}
public static void main(String[] args) {
MyOwnFunctionalInterface compiles = SimpleClass::doItStatic;
MyOwnFunctionalInterface alsoCompiles = new SimpleClass()::doItNonStatic;
NotAFunctionalInterface doesNotCompile = SimpleClass::doItStatic;
AlsoNotAFunctionalInterface alsoDoesNotCompile = SimpleClass::doItStatic;
}
}
This question already has answers here:
Require a default constructor in java?
(3 answers)
Closed 8 years ago.
I've tried running the following code which gives me a constructor A in class A cannot be applied to given types error.
class A{
int a;
A(int b){
a = b;
}
}
public static void main (String[] args) throws java.lang.Exception
{
A a = new A();
System.out.println(a.a);
}
If I remove the c'tor from class A however the code runs as expected (and outputs 0). It seems that if another c'tor exists there is no default c'tor (and an argument less c'tor exists only if it is written). Am I correct?
More importantly, why is this?
If you don't create a constructor then there is a constructor by default as below
public YourClass(){
}
But if you create a constructor like below:
public YourClass(int x){
}
Then you won't have a constructor by default i.e.
public YourClass(){
//this won't exist
}
So you have to do
YourClass anObject = new YourClass(5);//you can do this.
And hence you cannot do something like
YourClass anObject = new YourClass();//you cannot do this
In order to do this you need to create a constructor by yourself as
public YourClass(){
//this time you must create this
}
For the question why?, I doubt there is any reason. This is the way OOP has moved.
Once you defined a non-empty constructor, the non-empty conscrutor isn't implicite and you have to explicite it.
public A() {
}
This question already has answers here:
Uninitialized variables and members in Java
(7 answers)
Closed 8 years ago.
I have a question that why this code is giving me an error while i am trying to call a static function defined within a class through a class reference and it makes possible to call a static function when i am creating an object of a reference.
public class Example
{
public static void main(String args[])
{
Example t;
t.method();//getting error
Example t1=new Example t1();
t1.method();//it runs successfully
}
public static void method()
{
System.out.println("NullPointerException");
}
}
You should not call a static method on an instance of the class. You should use name of the class itself:
Example.method()
Also when you declare a variable and left it without initialization, It will not be initialized (Local variables) and when you try to call a method on it, you will get error
t is not initialised when you call t.method();. You therefore get a NullPointer on the non-instanciated t object.
public class Example
{
public static void main(String args[])
{
Example t; // t points to nothing (not even null, actually, its as if it doesn't exist at all)
t.method();//getting error // how can you call a method of example with a reference to nothing.
Example t1=new Example t1(); // t1 points to an Example object.
t1.method();//it runs successfully // works fine , but is not suggested as the method is at class level, not at instance level. use Example.method()
}
public static void method()
{
System.out.println("NullPointerException");
}
}
that is possible, but if you want to call anything through a reference, you need to instantiate it first.
do remember also: Java has methods, not functions. So, change:
Example t;
in
Example t = new Example();
and try again