This question already has answers here:
Lambda expression vs method reference implementation details
(3 answers)
Closed 5 years ago.
I just read in a book that when a lambda expression is assigned to a functional interface, then that sets the "target type" for the lambda and an instance of that type (that is, the functional interface's type) is created with the lambda expression used as implementation for the abstract method in the functional interface.
My question: If so, then does that mean lambdas aren't really standalone methods and as such a new type of element brought into the language, but are simply a more compact way for expressing an anonymous class and as such merely are added facility (just like generics) on the compiler's side?
Moreover, how do method references comply with that, in particular, static methods which are not associated with any objects? For example, when a method reference to an instance method is assigned to a functional interface then the encapsulating object for that method is used, but what happens in the case of a static method - those are not associated with any object.. ?
If so, then does that mean lambdas aren't really standalone methods and as such a new type of element brought into the language,
Correct, lambdas are compiled into normal methods with a synthetic name
but are simply a more compact way for expressing an anonymous class and as such merely are added facility (just like generics) on the compiler's side?
No, it's not only on the compiler side. There are is also code in the JVM involved, so that the compiler doesn't have to write class files for the lambdas.
Moreover, how do method references comply with that, in particular, static methods which are not associated with any objects?
Method references are not different from lambdas: at runtime there has to be an object implementing the functional interface. Upon calling the "SAM" of the object this method will call the referenced method.
For example, when a method reference to an instance method is assigned to a functional interface then the encapsulating object for that method is used,
No, it can't be used. Let's take the following example using a System.out::println method reference:
Arrays.asList("A", "B").forEach(System.out::println);
List<E>.forEach() expects a Consumer<? super E> which defines the method void accept(E e). The compiler need to generate byte code and other information in the class file so that at runtime the JVM can generate a class implementing Consumer<E> with a method void accept(E e). This generated method then calls System.out.println(Object o).
The runtime generated class would look something like
class $$lambda$xy implements Consumer<Object> {
private PrintStream out;
$$lambda$xy(PrintStream out) {
this.out = out;
}
void accept(Object o) {
out.println(o);
}
}
Your question from the comment: "Why not directly assign to instance and its method?"
Let's expand the example a little bit:
static void helloWorld(Consumer<String> consumer) {
consumer.apply("Hello World!");
}
public static void main(String[] args) {
helloWorld(System.out::println);
}
To compile this, the compiler has to generate bytecode that creates an object implementing Consumer<String> (so it can pass the object into helloWorld()). That object somehow has to store the information that upon calling it's accept(x) method it has to call println(x) on the System.out PrintStream.
Other languages may have other names or concepts for this kind of objects - in Java the established concept is "an anonymous class implementing the interface and an object of that anonymous class".
How does the object store this information? Well, you could invent some super cool new way to store this information. The Java Language designers decided that an anonymous class would be good enough - for the time being. But they had the foresight that if someone came along with a new idea to implement it in a more efficient way, this should be easy to integrate into the Java ecosystem (Java compiler and JVM).
So they also decided to create that anonymous class not at compile time but to let the compiler just write the necessary information into the class file. Now the JVM can at runtime decide on what the optimal way to store the information (calling the correct method on the correct object) is.
For example, when a method reference to an instance method is assigned
to a functional interface then the encapsulating object for that
method is used, but what happens in the case of a static method -
those are not associated with any object..
That depends on context. Let say we have a static Utils#trim(String) method that will obviously trim given string.
And now, lest have a List<String> list and lets have some strings in it. We can do something like this:
list.stream().map(Utils::trim).collect(Collectors.toList());
As you can see, in given context, we are using lambda static method reference in order to use every string in list as input argument of Utils::trim method.
Related
This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 8 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
The very common beginner mistake is when you try to use a class property "statically" without making an instance of that class. It leaves you with the mentioned error message:
You can either make the non static method static or make an instance of that class to use its properties.
What the reason behind this? Am not concern with the solution, rather the reason.
private java.util.List<String> someMethod(){
/* Some Code */
return someList;
}
public static void main(String[] strArgs){
// The following statement causes the error.
java.util.List<String> someList = someMethod();
}
You can't call something that doesn't exist. Since you haven't created an object, the non-static method doesn't exist yet. A static method (by definition) always exists.
The method you are trying to call is an instance-level method; you do not have an instance.
static methods belong to the class, non-static methods belong to instances of the class.
The essence of object oriented programming is encapsulating logic together with the data it operates on.
Instance methods are the logic, instance fields are the data. Together, they form an object.
public class Foo
{
private String foo;
public Foo(String foo){ this.foo = foo; }
public getFoo(){ return this.foo; }
public static void main(String[] args){
System.out.println( getFoo() );
}
}
What could possibly be the result of running the above program?
Without an object, there is no instance data, and while the instance methods exist as part of the class definition, they need an object instance to provide data for them.
In theory, an instance method that does not access any instance data could work in a static context, but then there isn't really any reason for it to be an instance method. It's a language design decision to allow it anyway rather than making up an extra rule to forbid it.
I just realized, I think people shouldn't be exposed to the concept of "static" very early.
Static methods should probably be the exception rather than the norm. Especially early on anyways if you want to learn OOP. (Why start with an exception to the rule?) That's very counter-pedagogical of Java, that the "first" thing you should learn is the public static void main thing. (Few real Java applications have their own main methods anyways.)
I think it is worth pointing out that by the rules of the Java language the Java compiler inserts the equivalent of "this." when it notices that you're accessing instance methods or instance fields without an explicit instance. Of course, the compiler knows that it can only do this from within an instance method, which has a "this" variable, as static methods don't.
Which means that when you're in an instance method the following are equivalent:
instanceMethod();
this.instanceMethod();
and these are also equivalent:
... = instanceField;
... = this.instanceField;
The compiler is effectively inserting the "this." when you don't supply a specific instance.
This (pun intended) bit of "magic help" by the compiler can confuse novices: it means that instance calls and static calls sometimes appear to have the same syntax while in reality are calls of different types and underlying mechanisms.
The instance method call is sometimes referred to as a method invocation or dispatch because of the behaviors of virtual methods supporting polymorphism; dispatching behavior happens regardless of whether you wrote an explicit object instance to use or the compiler inserted a "this.".
The static method call mechanism is simpler, like a function call in a non-OOP language.
Personally, I think the error message is misleading, it could read "non-static method cannot be referenced from a static context without specifying an explicit object instance".
What the compiler is complaining about is that it cannot simply insert the standard "this." as it does within instance methods, because this code is within a static method; however, maybe the author merely forgot to supply the instance of interest for this invocation — say, an instance possibly supplied to the static method as parameter, or created within this static method.
In short, you most certainly can call instance methods from within a static method, you just need to have and specify an explicit instance object for the invocation.
The answers so far describe why, but here is a something else you might want to consider:
You can can call a method from an instantiable class by appending a method call to its constructor,
Object instance = new Constuctor().methodCall();
or
primitive name = new Constuctor().methodCall();
This is useful it you only wish to use a method of an instantiable class once within a single scope. If you are calling multiple methods from an instantiable class within a single scope, definitely create a referable instance.
If we try to access an instance method from a static context , the compiler has no way to guess which instance method ( variable for which object ), you are referring to. Though, you can always access it using an object reference.
A static method relates an action to a type of object, whereas the non static method relates an action to an instance of that type of object. Typically it is a method that does something with relation to the instance.
Ex:
class Car might have a wash method, which would indicate washing a particular car, whereas a static method would apply to the type car.
if a method is not static, that "tells" the compiler that the method requires access to instance-level data in the class, (like a non-static field). This data would not be available unless an instance of the class has been created. So the compiler throws an error if you try to call the method from a static method.. If in fact the method does NOT reference any non-static member of the class, make the method static.
In Resharper, for example, just creating a non-static method that does NOT reference any static member of the class generates a warning message "This method can be made static"
The compiler actually adds an argument to non-static methods. It adds a this pointer/reference. This is also the reason why a static method can not use this, because there is no object.
So you are asking for a very core reason?
Well, since you are developing in Java, the compiler generates an object code that the Java Virtual Machine can interpret. The JVM anyway is a binary program that run in machine language (probably the JVM’s version specific for your operating system and hardware was previously compiled by another programming language like C in order to get a machine code that can run in your processor). At the end, any code is translated to machine code. So, create an object (an instance of a class) is equivalent to reserve a memory space (memory registers that will be processor registers when the CPU scheduler of the operating system put your program at the top of the queue in order to execute it) to have a data storage place that can be able to read and write data. If you don’t have an instance of a class (which happens on a static context), then you don’t have that memory space to read or write the data. In fact, like other people had said, the data don’t exist (because from the begin you never had written neither had reserved the memory space to store it).
Sorry for my english! I'm latin!
The simple reason behind this is that Static data members of parent class
can be accessed (only if they are not overridden) but for instance(non-static)
data members or methods we need their reference and so they can only be
called through an object.
A non-static method is dependent on the object. It is recognized by the program once the object is created.
Static methods can be called even before the creation of an object. Static methods are great for doing comparisons or operations that aren't dependent on the actual objects you plan to work with.
This question already has answers here:
Can I override and overload static methods in Java?
(19 answers)
Closed 5 months ago.
Would it be correct to say that static methods in a class extended with a class, in an interface extended with an interface and in an interface implemented by a class can only be redeclared in the extending/implementing part (hiding the original method in the class extending class case), and any other method can only be overridden there? And is redefining the same as overriding?
If not, can someone please explain these concepts with a flowchart (I've looked at other explanations and they don't give me the overview I'm looking for)?
Would it be correct to say that static methods in a class extended
No. static methods fundamentally are un-inheritable, and un-overridable. Or rather, conceptually it just doesn't apply.
Saying: "This static method is an override" is a bit like stating: "This smells blue" - it's not clear what that would even mean.
overriding is relevant essentially only for the notion of dynamic dispatch. Dynamic dispatch is this idea:
class Dog {
void bark() { System.out.println("Woof"); }
}
class Bulldog extends Dog {
void bark() { System.out.println("Grrrr"); }
}
Dog d = new Bulldog();
d.bark(); // prints "Grrrr"
That's dynamic dispatch at work. d is a variable. Like all non-primitives in java, it is a reference. Meaning, values stored in this variable are the reference - a pointer. An address in an addressbook that lets you get to a house, not the house itself. d's type is Dog. Its value is a reference to an actual instance of some object (and java guarantees that whatever the actual type it is an instance of, that type is Dog or a subtype of Dog). That reference gets you an instance of Bulldog. So, when invoking bark() here, what happens?
Dynamic dispatch: Java finds the most specific implementation of this method, and calls that. So that prints Grrrr, and not Woof.
However, when talking about static methods, the entire concept doesn't apply. Dynamic dispatch occurs because there is a discrepancy between the type of the reference (which is Dog here, that's the type of variable d) and the type of the thing the reference is pointing at (which is Bulldog). Overriding as a concept exists because these 2 types may not be the same.
When invoking static methods, this doesn't come up. You always write SomeType.someStaticMethod(), so what would dynamic dispatch even be?
SIDENOTE: You can legally invoke static methods using an expression. This is legal:
List.of("a", "b"); // this is how you normally do it
List<Integer> list = new ArrayList<Integer>();
list.of("a", "b"); // this compiles and works
But make no mistake - the compiler treats it the same and cares only about the type of list, not about the object the variable is pointing at. In fact, list = null; list.of("a", "b"); works fine, no NullPointerException, proving the point that list doesn't get dereferenced when you do this. All style guides strongly recommend not doing this, for good reason.
SIDENOTE 2: Unfortunately java lets you declare a static method as final which is weird: final means: Cannot be overridden, and we just figured out that 'override' conceptually doesn't make sense for static methods. It's just what it is - it's a design error in the original java spec and java does not like making changes that break existing code unless there is an incredibly good reason to do so, and whilst this spec brainfart is annoying, it doesn't hurt much. Just don't declare your static methods final. It even adds a rule (subtypes cannot declare a static method with the same signature) which is even more bizarre. Again, disregard that - java spec error that doesn't get fixed because not worth the headache.
And is redefining the same as overriding?
Yes. 2 words for the same thing. The correct term is 'override' - both the java lang spec uses this term, and the vast majority of the community does. If I was an editor of whatever tutorial, blogpost, documentation, or presentation you got this 'redefine' term from, I'd edit it. Unless the author was specifically talking about this:
class Parent {
static void foo() {}
}
class Child extends Parent {
static void foo() {}
}
In which case 'override' is the wrong term to use (given that static methods and override are orthogonal concepts), though I wouldn't use 'redefine' either. You're just defining a method named foo in one class, and also defining a method named foo in another. The fact that one is a child of the other is irrelevant; both have a foo method now. The foo method in child does not override or redefine anything; there's no such thing in static world.
with a flowchart
A flowchart requires some sort of flow to chart. Hence the name. No such thing here.
This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 8 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
The very common beginner mistake is when you try to use a class property "statically" without making an instance of that class. It leaves you with the mentioned error message:
You can either make the non static method static or make an instance of that class to use its properties.
What the reason behind this? Am not concern with the solution, rather the reason.
private java.util.List<String> someMethod(){
/* Some Code */
return someList;
}
public static void main(String[] strArgs){
// The following statement causes the error.
java.util.List<String> someList = someMethod();
}
You can't call something that doesn't exist. Since you haven't created an object, the non-static method doesn't exist yet. A static method (by definition) always exists.
The method you are trying to call is an instance-level method; you do not have an instance.
static methods belong to the class, non-static methods belong to instances of the class.
The essence of object oriented programming is encapsulating logic together with the data it operates on.
Instance methods are the logic, instance fields are the data. Together, they form an object.
public class Foo
{
private String foo;
public Foo(String foo){ this.foo = foo; }
public getFoo(){ return this.foo; }
public static void main(String[] args){
System.out.println( getFoo() );
}
}
What could possibly be the result of running the above program?
Without an object, there is no instance data, and while the instance methods exist as part of the class definition, they need an object instance to provide data for them.
In theory, an instance method that does not access any instance data could work in a static context, but then there isn't really any reason for it to be an instance method. It's a language design decision to allow it anyway rather than making up an extra rule to forbid it.
I just realized, I think people shouldn't be exposed to the concept of "static" very early.
Static methods should probably be the exception rather than the norm. Especially early on anyways if you want to learn OOP. (Why start with an exception to the rule?) That's very counter-pedagogical of Java, that the "first" thing you should learn is the public static void main thing. (Few real Java applications have their own main methods anyways.)
I think it is worth pointing out that by the rules of the Java language the Java compiler inserts the equivalent of "this." when it notices that you're accessing instance methods or instance fields without an explicit instance. Of course, the compiler knows that it can only do this from within an instance method, which has a "this" variable, as static methods don't.
Which means that when you're in an instance method the following are equivalent:
instanceMethod();
this.instanceMethod();
and these are also equivalent:
... = instanceField;
... = this.instanceField;
The compiler is effectively inserting the "this." when you don't supply a specific instance.
This (pun intended) bit of "magic help" by the compiler can confuse novices: it means that instance calls and static calls sometimes appear to have the same syntax while in reality are calls of different types and underlying mechanisms.
The instance method call is sometimes referred to as a method invocation or dispatch because of the behaviors of virtual methods supporting polymorphism; dispatching behavior happens regardless of whether you wrote an explicit object instance to use or the compiler inserted a "this.".
The static method call mechanism is simpler, like a function call in a non-OOP language.
Personally, I think the error message is misleading, it could read "non-static method cannot be referenced from a static context without specifying an explicit object instance".
What the compiler is complaining about is that it cannot simply insert the standard "this." as it does within instance methods, because this code is within a static method; however, maybe the author merely forgot to supply the instance of interest for this invocation — say, an instance possibly supplied to the static method as parameter, or created within this static method.
In short, you most certainly can call instance methods from within a static method, you just need to have and specify an explicit instance object for the invocation.
The answers so far describe why, but here is a something else you might want to consider:
You can can call a method from an instantiable class by appending a method call to its constructor,
Object instance = new Constuctor().methodCall();
or
primitive name = new Constuctor().methodCall();
This is useful it you only wish to use a method of an instantiable class once within a single scope. If you are calling multiple methods from an instantiable class within a single scope, definitely create a referable instance.
If we try to access an instance method from a static context , the compiler has no way to guess which instance method ( variable for which object ), you are referring to. Though, you can always access it using an object reference.
A static method relates an action to a type of object, whereas the non static method relates an action to an instance of that type of object. Typically it is a method that does something with relation to the instance.
Ex:
class Car might have a wash method, which would indicate washing a particular car, whereas a static method would apply to the type car.
if a method is not static, that "tells" the compiler that the method requires access to instance-level data in the class, (like a non-static field). This data would not be available unless an instance of the class has been created. So the compiler throws an error if you try to call the method from a static method.. If in fact the method does NOT reference any non-static member of the class, make the method static.
In Resharper, for example, just creating a non-static method that does NOT reference any static member of the class generates a warning message "This method can be made static"
The compiler actually adds an argument to non-static methods. It adds a this pointer/reference. This is also the reason why a static method can not use this, because there is no object.
So you are asking for a very core reason?
Well, since you are developing in Java, the compiler generates an object code that the Java Virtual Machine can interpret. The JVM anyway is a binary program that run in machine language (probably the JVM’s version specific for your operating system and hardware was previously compiled by another programming language like C in order to get a machine code that can run in your processor). At the end, any code is translated to machine code. So, create an object (an instance of a class) is equivalent to reserve a memory space (memory registers that will be processor registers when the CPU scheduler of the operating system put your program at the top of the queue in order to execute it) to have a data storage place that can be able to read and write data. If you don’t have an instance of a class (which happens on a static context), then you don’t have that memory space to read or write the data. In fact, like other people had said, the data don’t exist (because from the begin you never had written neither had reserved the memory space to store it).
Sorry for my english! I'm latin!
The simple reason behind this is that Static data members of parent class
can be accessed (only if they are not overridden) but for instance(non-static)
data members or methods we need their reference and so they can only be
called through an object.
A non-static method is dependent on the object. It is recognized by the program once the object is created.
Static methods can be called even before the creation of an object. Static methods are great for doing comparisons or operations that aren't dependent on the actual objects you plan to work with.
Would appreciate any help on understanding below two concepts in Java 8.
What I know
A lambda is an object without an identity and should not be used as a regular object.
A lambda expression should not be calling methods from Object class like toString, equals, hashCode etc.
What I'd like know more about
What difference does lambda expression have to be called as an object without identity?
Why exactly should methods from Objectclass not be used while using lambda expression?
1) A lambda is an object without an identify and should not be used as a regular object.
This is not true. A lambda is a Java object, and it does have an identity1. The problem is that the lifecycle is deliberately left specified to allow Java compilers freedom to optimize the code that evaluates them. Therefore, you cannot know when new lambda objects are going to be created, or existing ones are going to be reused.
JLS 15.27.4 says:
"At run time, evaluation of a lambda expression is similar to evaluation of a class instance creation expression, insofar as normal completion produces a reference to an object. Evaluation of a lambda expression is distinct from execution of the lambda body.
Either a new instance of a class with the properties below is allocated and initialized, or an existing instance of a class with the properties below is referenced. ... "
2) A lambda expression should not be calling methods from Object class like toString, equals, hashCode etc.
As written, that is also not true. A lambda expression may call those methods. However, it is not advisable to rely on those methods to have any specific behavior when you call them on a lambda object
The JLS states:
"The class ... may override methods of the Object class."
In other words, it may ... or may not ... override them. If you rely a particular behavior of these methods, your application is (in theory) non-portable.
Furthermore, since the instantiation semantics are also unspecified, the behavior of Object::equals and Object::hashCode are uncertain.
Finally, it is unspecified whether lambdas are clonable.
1 - Sure, a lambda doesn't have a name: it is anonymous. But name and identity are different concepts.
Basically, a lambda is a convenience of doing this:
#FunctionalInterface
interface A {
void b();
}
void c(A a) {
...
}
void main() {
c(new A() {
void b() {
...
}
});
}
I apologize for the less than stellar variable names, but as you can see, A is an interface with one method. c is a method that takes in an A interface. However, instead of creating your own class that implements A, you can create it on the spot. This is what you call an anonymous class, since it doesn't have a name. This is where the quote you have:
A lambda is an object without an identify
comes from. The class doesn't have an identity. The reason it relates to lambdas is because if an interface has only one method, you can use lamdas to simplify it.
void main() {
c(
() -> {
...
}
);
}
This is the exact same as before.
The second part, why lambdas shouldn't use Object's methods, I didn't know before. You should probably have someone else answer this, however my guess is that lambda classes don't look like it extends Object directly, so you can't use it's methods.
This question already has answers here:
Why are only final variables accessible in anonymous class?
(15 answers)
Closed 6 years ago.
So in Java it's possible to instantiate an interface without creating an explicit class
public interface Foo {
public void OnNotify()
}
Say I do the following somewhere else, say in a method Subscribe
public void Subscribe()
{
final int someInt = 5;
Foo bar = new Foo() {
final int value = someInt;
#Override
public void OnNotify()
{
Log.d("Debug", "You are being notified that I hold the value " + value);
}
}
someObject.AddSubscription(bar);
}
This is used extensively in Android for setting listeners to events.
Why is this possible, and does this kind of instantiation have a special name? Is this related to lambda functions in some way perhaps?
And why do I need to make a 'final' variable if I want to give it to this instantiated interface to hold. Say for example I wanted to pass the current iteration 'i' of a for loop to identify what index of an array a subscription references. I need to declare a final variable to hold 'i', and then pass it into the instantiated interface.
Edit:
I'm still asking why I can instantiate an interface without making a class first, and what it's called. Not knowing what this is, there's no way I could have found the duplicate question, which doesn't cover what a Java anonymous class is.
Why is this possible, and does this kind of instantiation have a special name? Is this related to lambda functions in some way perhaps?
I don't know of any "special name" for this. I generally refer to it as a "interface implementation declaration." That's just me though, and maybe that's not accurate or correct.
I believe they are not, because aside from syntax differences, I look to lambdas as a method-class like structure, and this form is overriding methods from an object type. When passing an interface object, you're passing reference of a type.
And why do I need to make a 'final' variable if I want to give it to this instantiated interface to hold.
The way I have looked at it, and understood it to be, is because this declaration inline and not in a separate class doesn't quite change what an Interface still is. In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types Link
An interface is required to have a constant, and to me final is a keyword that works similarly to the C/C++ keyword const in that it isn't holding the value but a reference to the type that you've declared. These values are immutable, preventing any copies and changes, as they only contain a reference to the location of the value.
So, overall, I believe that an interface declaration like how you illustrate is not working as declaring an instance of the actual interface class, but rather it's creating an object of that type and that object is a new location in memory that holds references to these methods and members (like a class).
Hope this helps some. I don't normally like to volunteer answers to something I am not 100% sure on, and wish this was a comment more (but lack the rep still for that), but hopefully it helps clear some things.
You can read the Java Language Specification here for more information on Interfaces too. Hope that helps.