Java 8 Method references default method implementation - java

interface HelloWorld {
String hello(String s);
}
public static void main(String[] args) {
HelloWorld h = String::new;
System.out.println(h.hello("dasdasdadasd"));
}
When I execute the above method,it returns the value which I am passing in the arguments dasdasdadasd
Which method of string class is executed or is there any default implementation which java provides at runtime or by default it calls supplier.get() method?

h was assigned a method reference to the public String(String original) constructor of the String class. That's the only constructor that matches the signature of the String hello(String s) method of your HelloWorld interface.
Therefore h.hello("dasdasdadasd") creates a new String instance whose value is equal to "dasdasdadasd" and returns that instance.
HelloWorld h = String::new;
is equivalent to:
HelloWorld h = s -> new String(s);

Your code can be rewritten as:
hw returns a string created from what it receives:
//Returns a string based on the input
HelloWorld hw = (s) -> {
return new String(s);
};
Invoking hello() on that object returns "basically" the input:
//The value assigned to print is "dasdasdadasd", as returned by hw
String print = hw.hello("dasdasdadasd");
println Is receiving dasdasdadasd:
System.out.println(print); //"dasdasdadasd" is passed to println

Related

Java printing inherited objects with a println method

I'm taking those first steps from python to java and here is my first of many Java questions do doubt.
When printing via a shortened print method, I'm running into a problem with the return value from a inherited class. I'm sure it's something simple about Java I don't get yet. I'm also trying to convert any integers the println method receives to a string with .tostring(), but I'm not sure if that is correct.
class Inheritance {
private static void println (Object line){
System.out.println(line.toString());
}
static class A {
public int multiply(int a, int b){
int val = a*b;
return val;
}
}
static class B extends A {
public int multiply(int a, int b) {
int val = a * b * 5;
return val;
}
}
public static void main(String[] args) {
B b_class = new B();
b_class.multiply(3,4);
println(b_class);
println("Hello World");
}
}
The output is as follows:
Inheritance$B#74a14482
Hello World
You can just use the method inside println
public static void main(String[] args) {
B b_class = new B();
println(Integer.ToString(b_class.multiply(3,4)));
println("Hello World");
}
For Java toString method default it will
returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()
so when you println b_class it will print: Inheritance$B#74a14482.
For your println (Object line) it's receiving Reference type(Object) to println, but as multiply method it's return a primitive type(int), it's not an object, you need to convert it to an Object for println method, as #StanteyS's answer, use Integer.toString can convert int to String.
What's the difference between primitive and reference types?
When you are executing println(b_class); implicitly it calls toString method of same class, which is inherited from Object class.
You need to override toString method to display correct output.
static class B extends A {
int val=0;
public int multiply(int a, int b) {
val = a * b * 5;
return val;
}
public String toString(){
return String.valueOf(val);
}
}
Now, println(b_class); will work as per your expectation.

How does method reference casting work?

public class Main {
interface Capitalizer {
public String capitalize(String name);
}
public String toUpperCase() {
return "ALLCAPS";
}
public static void main(String[] args) {
Capitalizer c = String::toUpperCase; //This works
c = Main::toUpperCase; //Compile error
}
}
Both are instance methods with same signature. Why does one work and the other doesn't?
Signature of String::toUpperCase: String toUpperCase();
There are 3 constructs to reference a method:
object::instanceMethod
Class::staticMethod
Class::instanceMethod
The line:
Capitalizer c = String::toUpperCase; //This works
use 3'rd construct - Class::instanceMethod. In this case first parameter becomes the target of the method. This construct is equivalent (translates) to following Lambda:
Capitalizer = (String x) -> x.toUpperCase();
This Lambda expression works because Lambda gets String as parameter and returns String result - as required by Capitalizer interface.
The line:
c = Main::toUpperCase; //Compile error
Translates to:
(Main m) -> m.toUpperCase();
Which does not work with the Capitalizer interface. You could verify this by changing Capitalizer to:
interface Capitalizer {
public String capitalize(Main name);
}
After this change Main::toUpperCase will compile.
You have a method which
public String capitalize(String name);
Takes a String and returns a String. Such a method can have a number of patterns.
A constructor
c = String::new; // calls new String(String)
// or
c = s -> new String(s);
A function on String which takes no arguments
c = String::toLowerCase; // instance method String::toLowerCase()
// or
c = s -> s.toLowerCase();
of a method which takes a String as the only argument
// method which takes a String, but not a Main
public static String toUpperCase(String str) {
c = Main::toUpperCase;
// or
c = s -> toUpperCase(s);
In every case, the method referenced has to take the String.
If not you can do this instead.
c = s -> capitalize(); // assuming Main.capitalize() is static
This tells the compiler to ignore the input.
You should change:
public String toUpperCase()
to
public static String toUpperCase(String text)
You should read the java tutorial on method references. The different kind of method references and there is a similar example with String::compareToIgnoreCase (Reference to an Instance Method of an Arbitrary Object of a Particular Type).
The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).

when calling method from another class - retuns an incomprehensible value JAVA

When i run 2nd class i see " Car#15ab7626 " why ? in teory i must see 20, yes?
I have alredy used differnet combinatoin & ask google but dont understent why.
i have 1 class
public class Car {
public int drive(int a) {
int distance = 2*a;
return distance;
}
}
and 2nd class
public class CarOwner {
public static void main(String[] args) {
Car a = new Car();
a.drive(10);
System.out.println(a);
}
}
You are printing the car object, not the result printed by drive
That incomprehensible value JAVA is textual representation of Object.
When you do System.out.println(a); then by default toString() method calls on passed object.
As per docs of toString()
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object.
So
Car#15ab7626 is the textual representation of Values class.
To print result which is returned by your drive() method, print,
System.out.println(a.drive(10));
If you want to print the result from the drive() method, assign the result to a variable and then print it.
int result = a.drive(10);
System.out.println("Result = " + result);
or directly pass the result to the System.out.println() method;
System.out.println("Result = " + a.drive(10));
If you want to print the a object in a readable way, override the toString() method in the Car class definition.
#Override
public String toString() {
return "This is a car"; //for example
}
You are returning the value you have from a drive method, but you're not printing it.
To print out the value of the drive method, use
public class CarOwner {
public static void main(String[] args) {
Car a = new Car();
System.out.println(a.drive(10));
}
}
That's not the way method return values work. If you want to see the result as 20, replace your SOP with the following
System.out.println(a.drive(10));

Java String immutable passed by reference/value

Hi Im studying for my scja exam and have a question about string passing by ref/value and how they are immutable. The following code outputs "abc abcfg".
What I want to know is why is this happening? Im not understanding what happens inside of method f. String is passed by value so surely it should change to "abcde" inside the method? Because if b+="fg" appends to the string why doesnt it work inside the method?
Thanks!
public class Test {
public static void main(String[] args){
String a =new String("abc");
String b = a;
f(b);
b+="fg"
System.out.println(a + " " + b);
}
public static void f(String b){
b+="de";
b=null;
}
}
The line b+="de"; in the void f(String b) functions creates a completely new object of String that does not affect the object in the main function.
So when we say String is immutable when mean any change on a String object will result in creating a completely new String object
public class Test {
public static void main(String[] args){
String a =new String("abc");
String b = a; // both a & b points to the same memory address
f(b); // has no effect
// b still has the value of "abc"
b+="fg" // a new String object that points to different location than "a"
System.out.println(a + " " + b); // should print "abc abcfg"
}
public static void f(String b){
b+="de"; // creates a new object that does not affect "b" variable in main
b=null;
}
}
In your method f() you are assigning a new String to the parameter b, but parameters are just like local variables, so assigning something to them has no effect on anything outside the method. That's why the string you passed in is unchanged after the method call.
This line of code:
b += "de";
Roughly translates to:
b = b + "de";
Which creates a new String and stores it in the local variable 'b'. The reference outside the method is not changed in anyway by this. There are a couple of key things to remember when trying to understand how/why this works this way.
In Java, all method arguments are passed by value.
Methods have a local stack where all their data is stored, including the method arguments.
When you assign a new object to a variable that was passed into a method, you are only replacing the address in the local stack, with the address of the new object created. The actual object address outside of the method remains the same.
When you pass the String into the method, it creates a new String object in the method. If you put a println statement in your method, like this:
public static void f(String b){
b+="de";
System.out.println(b);
b=null;
}
You would see the output "abcde".
However, once you come out of the method, you go back to your original object, which has not been altered. Therefore, appending fg to it will only produce a NEW string (b), containing "abcfg".
Your creating a new object of String when you say something like b+="de"
Its like saying b = new String(b+"de");
If you really want to keep the value passed in then use a stringBuilder like this:
StringBuilder a =new StringBuilder("abc");
StringBuilder b = a;
f(b);
b.append("fg");
System.out.println(a + " " + b);
}
public static void f(StringBuilder b){
b.append("de");
b=null;
}
Now your output will be "abcdefg" because stringbuilder object b was passed into f as the value of the object itself. I modified the value without using "new" to point to another object. Hope its clear now.

Passing arguments in main method in java class

Can someone tell me what is the need to declare a class like this:
public class Test {
String k;
public Test(String a, String b, String c){
k = a + " " + b + " " + c; //do something
}
public void run(){
System.out.println(k);
}
public static void main(String[] args) {
String l = args[0];
String m = args[1];
String n = args[2];
Test obj = new Test(l,m,n);
obj.run();
}
}
Of course it works but I don't get the point why would one use such way to implement something. Is it because we need to pass arguments directly to the class main method that is why we use this way or is there some other reason?
What is the purpose of public Test(...) using the same class name. Why is it like this?
The public Test(...) is a constructor and its purpose is for object creation. This is clearly seen from the sample code...
Test obj = new Test(l,m,n);
The variable obj is instantiated with object Test by being assigned to the Test's constructor. In java, every constructor must have the exact same name (and case) as the java file it's written in (In your case constructor Test is found in Test.java).
...Why is it like this?
It all depends on what you want to do with your object. You could have a zero-argument constructor (i.e. requires no parameters) and have methods to set your l, m, n, like so:
package net;
public class Test {
private String k;
/**
*
*/
public Test() {
super();
// TODO Auto-generated constructor stub
}
public void set(String a, String b, String c) {
k = a + " " + b + " " + c; //do something
}
public void run() {
System.out.println(k);
}
public static void main(String[] args) {
String l = args[0];
String m = args[1];
String n = args[2];
Test obj = new Test();
obj.set(l, m, n);
obj.run();
}
}
As you can see, it's exactly the same feature as your example but with a zero-argument constructor.
If your class has no constructor at all, java adds a public zero-argument constructor for you automatically.
Hope this helps.
The method called Test is a so-called constructor for the Test class. The constructor is the method that gets called when you write something like new Test(...).
Bear in mind that the main method is a static method, which means that it does not require an instance of the class Test to be called. This is not the case for the run method. run is an instance method, and to invoke it you need an instance of the Test class (the obj in your case).
The public Test(...) bit is the constructor of that class. It always has the same name as the class. Classes and main methods are two quite different aspects of programming. Classes define reusable components that have both state and methods. The main method is a special method that gets called from the command line.
Your example is so trivial that it doesnt really show any benefits of Object Orientated Programming. If you consider an example where you had different Classes intetracting you might get more of a feel for it.
The main method is the entry point for the program and is called when you run java Test from the command line.
public Test(String a, String b, String c) is a public constructor for the Test class and is called when you call new Test(l,m,n); Note that a in the constructor and l in main method refer to the same String... this also applies to b and m; c and n.
As a side note, this class expects to be passed three values from the command line, and then stores them in l, m, and n
One last note: If you have a method with the signature public void run(), your class should likely implement Runnable so that it can be used in a Thread.
Learn Java.
A constructor is a function that gets called to create an object, and it's denoted by a function with the same name as the class, but no return type. Multiple constructors can be declared with different arguments.
In this case, the arguments are taken out of the argument array and passed as arguments to the constructor for Test.
These are fundamentally basic concepts to the Java programming language. You should read up on Java. Try Thinking in Java, this is a great book to get started.

Categories