Why is this program yielding this result? - java

Lambda is used here, but when ::new is used, the following parameters are populated into the constructor:
#FunctionalInterface
interface Lambdademo1<T> {
T test(String s);
}
class Test {
public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
Apple i = lambdademo1.test(s);
System.out.println(i.getColor());
}
public static void main(String args[]){
test2(Apple::new,"hehehe");
}
}
Output:
hehehe
UPDATE:
class test {
public static void main(String args[]) {
test1((String s) -> new Integer(1), "hehehe");
test1(Integer::new, "hehehe"); //It's wrong
test2(Apple::new,"hehehe");
test3(Apple1::new,"hehehe"); //Compile error
// I think XXX::new is equivalen to new XXX() but here shoe it's not
}
public static void test1(Lambdademo1<Integer> lambdademo1, String s) {
Integer i = lambdademo1.test(s);
System.out.println(i);
}
public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
Apple i = lambdademo1.test(s);
System.out.println(i.getColor());
}
public static void test3(Lambdademo1<Apple1> lambdademo1, String s) {
Apple1 i = lambdademo1.test(s);
System.out.println(i.getColor());
}
}
The Apple1 class:
class Apple1 {
private String color;
// getter and setter
}
The Apple class:
class Apple {
private String color;
public Apple(String color) {
this.color = color;
}
// getter and setter
}

Original answer
Apple::new can (and does) refer to a constructor Apple(String) because it follows the contract of T test(String s) - (String string) -> new Apple(string); or Apple:new
Apparently, that constructor sets the value for the color field since the getter returns the value you passed to the constructor.
test2(Apple::new,"hehehe");
is equivalent to
System.out.println(new Apple("hehehe").getColor());
Update
Let's discuss each line in detail to make it clear.
1.
test1((String s) -> new Integer(1), "hehehe");
You are taking a String s, not using it, and returning a constant new Integer(1) or simply 1.
We might rewrite it to
test1(s -> 1,"hehehe" );
2.
test1(Integer::new, "hehehe");
It's not wrong. It's absolutely compilable line. There is a constructor Integer(String s) that converts the given String to an int using Integer.parseInt(String).
Since "hehehe" isn't a parsable int, you will get a NumberFormatException, but that's a runtime issue.
3.
It's fine, and I have explained it in the original answer above.
4.
test3(Apple1::new,"hehehe");
You haven't defined any constructors for Apple1, so we have the no-arguments one by default. Since it doesn't take a String, we can't use it to represent Lambdademo1#test.
Writing a lambda will make it compile, though.
test3(s -> new Apple1(),"hehehe");
I think XXX::new is equivalent to new XXX() but here it's not.
It depends on context. XXX::new always refers to a constructor. What constructor? We don't know it until we see the context.
Examine an example where Apple::new points at 3 different constructors.
class Apple {
public Apple() {}
public Apple(Integer i) {}
public Apple(String s) {}
public static void main(String[] args) {
Supplier<Apple> a = Apple::new;
Function<Integer, Apple> b = Apple::new;
Function<String, Apple> c = Apple::new;
}
}

Related

How to pass a Default and Optional Parameter into a function like a python in the Java

I am trying to migrate the python library into the java native script but I facing extreme complexity with the parameters while migration.
Here the code I need to migrate the python method with the default & optional parameters with different datatypes into the java method:
def connect_network(self,
bssid=None,
proto="http",
check_redirect_code=True,
redirect_code='302',
portal_url=None,
subscriber_portal='scg',
expect_href_list_zd_sp='google',
check_user_block=False,
redirect_url='',
tnc_content="",
path="/tmp/"):
pass
Here is my example code which I tried in java equivalent:
public class LinuxClientUtils {
public void DefaultNameParameter1(HashMap<Integer, String> params){
System.out.Println(params.toString());
}
public void DefaultNameParameter2(Map.Entry<String, String>... params){
System.out.Println(params.toString());
}
public void DefaultNameParameter3(Optional<String> name, Optional<String> age){
System.out.Println(name.toString());
}
}
I will import that Java library in the robot framework and call the method like this,
*** Settings ***
Library test.LinuxClientUtils
*** Test Cases ***
Testing
[tags] service
[Documentation] Add Network
Default Name Parameter3 req_network_id=89
Still, None of the methods didn't work.
I have tried few Methods from the following URLs Link-1
Link-2 But I am unable to figure it out from those links.
I'm new to JAVA programming and haven't been able to fix this one. Any help would be great, thanks.
Create a new class for a parameter object. It will have each of the parameters as a field.
The constructor of this parameter class has no parameters. Instead, each field has a default value. (null and false are automatically assigned by default for object and boolean fields, anyway.)
Your function will just take a parameter object as a single parameter.
public class A {
static class ParameterObject {
public ParameterObject(){
//empty
}
private int x;
private boolean b;
private String s;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public boolean isB() {
return b;
}
public void setB(boolean b) {
this.b = b;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
}
public static void f(ParameterObject o){
//Do something with object
}
public static void main(String[] args) {
ParameterObject paramObj=new ParameterObject();
paramObj.setX(10);
f(paramObj);
}
}

How do I pass a method as a parameter in Java 8?

I don't understand how to use lambdas to pass a method as a parameter.
Considering the following (not compiling) code, how can I complete it to get it work ?
public class DumbTest {
public class Stuff {
public String getA() {
return "a";
}
public String getB() {
return "b";
}
}
public String methodToPassA(Stuff stuff) {
return stuff.getA();
}
public String methodToPassB(Stuff stuff) {
return stuff.getB();
}
//MethodParameter is purely used to be comprehensive, nothing else...
public void operateListWith(List<Stuff> listStuff, MethodParameter method) {
for (Stuff stuff : listStuff) {
System.out.println(method(stuff));
}
}
public DumbTest() {
List<Stuff> listStuff = new ArrayList<>();
listStuff.add(new Stuff());
listStuff.add(new Stuff());
operateListWith(listStuff, methodToPassA);
operateListWith(listStuff, methodToPassB);
}
public static void main(String[] args) {
DumbTest l = new DumbTest();
}
}
Declare your method to accept a parameter of an existing functional interface type which matches your method signature:
public void operateListWith(List<Stuff> listStuff, Function<Stuff, String> method) {
for (Stuff stuff : listStuff) {
System.out.println(method.apply(stuff));
}
}
and call it as such:
operateListWith(listStuff, this::methodToPassA);
As a further insight, you don't need the indirection of methodToPassA:
operateListWith(listStuff, Stuff::getA);
Your MethodParameter should be some interface you define with a single method. This is referred to as a functional interface. You can then pass your methods in. A quick demonstration:
public interface Test{
void methodToPass(string stuff);
}
[...]
public class DumbTest{
//MethodParameter is purely used to be comprehensive, nothing else...
public void operateListWith(List<Stuff> listStuff, Test method) {
for (Stuff stuff : listStuff) {
System.out.println(method(stuff));
}
}
public DumbTest() {
List<Stuff> listStuff = new ArrayList<>();
//fill list
operateListWith(listStuff, methodToPassA);
operateListWith(listStuff, methodToPassB);
}
}
The definition of MethodParameter is missing from your source code. To be used with lambda expressions, it must be a functional interface, for example:
#FunctionalInterface
interface MethodParameter {
String apply(Stuff input);
}
(The #FunctionalInterface annotation is optional.)
To use the method, you have call the method from the interface:
System.out.println(method.apply(stuff));
And thirdly, a method reference always needs a context. In your case you have to do:
operateListWith(listStuff, this::methodToPassA);
operateListWith(listStuff, this::methodToPassB);
You need to use method references.
You don't need to create a method like operateListWith, that's sort of the whole idea. Instead, you can operate on each value using forEach by doing something like this:
listStuff.stream.forEach(object::methodToPassA);
For example:
public class StreamExample {
public static void main(String[] args) {
List<String> list = Arrays.asList("Hello", "What's Up?", "GoodBye");
list.stream().forEach(System.out::println);
}
}
Output:
Hello
What's Up?
GoodBye
In your case, you can get the value inside Stuff using .map, and then operate on it using forEach, like this:
public class DumbTest {
public class Stuff {
public String getA() {
return "a";
}
public String getB() {
return "b";
}
}
public String methodToPassA(Stuff stuff) {
return stuff.getA();
}
public String methodToPassB(Stuff stuff) {
return stuff.getA();
}
public DumbTest() {
List<Stuff> listStuff = Arrays.asList(new Stuff(), new Stuff());
listStuff.stream()
.map(this::methodToPassA)
.forEach(System.out::println);
}
public static void main(String[] args) {
DumbTest l = new DumbTest();
}
}

Initialize Empty HashMap

I come from writing a lot of JavaScript, so bear with me.
I've got 3 HashMaps, which i reference in a method in a different class. My code (very simply) looks like so:
public class MainClass {
private HashMap<String,Nation> randomHashMap = new HashMap<String,Nation>();
DifferentClass d = new DifferentClass(this);
} //with getters/setters
public class DifferentClass {
private MainClass mc;
public void randomMethod() {
System.out.println("randomHashMap is " + (mc.getRandomHashMap() == null));
} //returns null
public DifferentClass(MainClass c) {
this.mc = c;
}
}
However, when I call them in my other method, they're null.
How do I create a new, empty HashMap?
You need to initialize your MainClass mc variable before using it in the DifferentClass#randomMethod method. Also, make sure you're using the mc variable instead of the MainClass.getRandomHashMap() method (by your actual code, we don't know how it behaves). Your code will look like this:
public class DifferentClass {
private MainClass mc = new MainClass();
public void randomMethod() {
//assuming getRandomHashMap is the getter of randomHashMap attribute (and non static)
System.out.println("randomHashMap is " + (mc.getRandomHashMap() == null));
}
}
public class MainClass {
private HashMap<String,Nation> randomHashMap = new HashMap<String,Nation>();
DifferentClass d = new DifferentClass(this);
public HashMap<String,Nation> getRandomHashMap() {
return this.randomHashMap;
}
} //with getters/setters
The code you posted is in fact perfectly all right as far as field initialization. I made an SSCCE from it with minimal intervention:
class Nation{}
public class MainClass {
private HashMap<String,Nation> randomHashMap = new HashMap<String,Nation>();
DifferentClass d = new DifferentClass(this);
public Object getRandomHashMap() {
return randomHashMap;
}
public static void main(String[] args) {
new MainClass().d.randomMethod();
}
} //with getters/setters
class DifferentClass {
private MainClass mc;
public void randomMethod() {
System.out.println("randomHashMap is " + (mc.getRandomHashMap() == null));
} //returns null
public DifferentClass(MainClass c) {
this.mc = c;
}
}
and it prints
randomHashMap is false
which proves that randomHashMap is indeed non-null.

How to have a method have different input types java

I have a program on my computer that simulates a server on the internet and the fake server needs to be able to send multiple data types to some classes. Like for instance at one point of the program the server needs to send an int to a class then convert that int to a string and send it to another.
Basically what I am asking is if a method can have multiple data types for an input(Does this make sense? if not ill try to explain better). Is there any way to do this without creating many different methods?
Edit: Also is there a way to tell the difference between the types passed in (to prevent errors)
You can have a method which takes Object which is any type. In Java 5.0 and later primitives will be auto-boxed and passed as an object as well.
void method(Object o);
can be called using
method(1);
method("hello world");
method(new MyClass());
method(null);
If I understand correctly, you're asking if a method foo() can have multiple different inputs for its parameters
That way foo(Integer i) and foo(String s) are encased in the same method.
The answer: yes, but it's not pretty
foo(Object o)
Is your method declaration
Now you need to sort out the different types of possibilities
if(o instanceof Integer){
stuff();
} else if (o instanceof String){
moreStuff();
}
Just chain those else/if statements for the desired result.
What you want are Generic methods or classes.
to check what type an object is you'll have to use the 'instanceof' method
you can either make an entire class generic or just a single method, an example of a generic class:
package javahowto;
public class Member<T> {
private T id;
public Member(T id) {
this.id = id;
}
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
public static void main(String[] args) {
Member<String> mString = new Member<String>("id1");
mString.setId("id2");
System.out.printf("id after setting id: %s%n", mString.getId());
//output: id after setting id: id2
Member<Integer> mInteger = new Member<Integer>(1);
mInteger.setId(2);
System.out.printf("id after setting id: %d%n", mInteger.getId());
//output: id after setting id: 2
}
Now you now what to look for I'm sure you'll find the best solution to your problem.
check out:
http://download.oracle.com/javase/tutorial/java/generics/index.html
http://en.wikipedia.org/wiki/Generics_in_Java
...
Well I have also wondered and wrote below block. I think instanceof better but I tried getclass.
public static void main(String[] args){
System.out.println(method("This is a test"));
}
private static String method(Object o){
System.out.println(o.toString());
String status = "";
String className;
String[] oList = {"Double","Integer","String","Double","Float","Byte","Short","Long","Character","Boolean" };
for(int i = 0;i<oList.length;i++){
className = "java.lang." + oList[i];
Class testClass;
try {
testClass = Class.forName(className);
if(o.getClass().equals(testClass)){
status = "Your object is " + oList[i];
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return status;
}
You could use the "hashed adapter" pattern.
Public interface Adapter {
Public void handle(object o);
}
Public class StringAdapter implements Adapter {
Public void handle(String st) { // stuff ...
}
Public class IntegerAdapter implements Adapter {
Public void handle(Integer intgr) { // stuff ...
}
Private static final Map adapters = new HashMap();
Adapters.put(string.class, new stringAdapter());
Adapters.put(Integer.class, new IntegerAdapter());
Public void handleMe(Object o) {
Adapters.get(o.getClass()).handle(o);
}
Ive always liked this more than the ol' cascade of ifs and else's.
On my iPad so sorry about formatting and terseness and speellling.

java - an enum question

I have encountered a weird problem in my app (java).
I have an enum. Something like that
public enum myEnum implement myIntrface{
valueA(1),valueb(2),valuec(3),valued(4)
private int i;
// and then - a constructor
public MyEnum(int number){
i = number;
}
private MyObj obj = new MyObj;
// getter and setter for obj
}
and in another class I have this
MyEnum.valueA.setObj(new Obj(...))
in briefe - I have an enum with a private instance member that has a set and a get.
So far so good -
The only thing that amazes me is that later on I look at the value of the MyEnum.valueA().obj is null.
there is nothing that updates the value to null, I have even gave it a default value in the constructor and I still see it null later.
any suggestions?
Enums should be un-modifiable classes so you shouldn't really be doing this. If your looking to modify the state of a type based object like an enum you should use an final class approach with embedded constants. Below is an example of a class based approach with a modifiable name an a un-modifiable name...
public final class Connection {
public static final Connection EMAIL = new Connection("email");
public static final Connection PHONE = new Connection("phone");
public static final Connection FAX = new Connection("fax");
/**/
private final String unmodifiableName; //<-- it's final
private String modifiableName;
/*
* The constructor is private so no new connections can be created outside.
*/
private Connection(String name) {
this.unmodifiableName = name;
}
public String getUnmodifiableName() {
return unmodifiableName;
}
public String getModifiableName() {
return modifiableName;
}
public void setModifiableName(String modifiableName) {
this.modifiableName = modifiableName;
}
}
The purpose of enums is to represent constant values. It does not make any sense to set the fields of a constant value.
You should declare your fields as final, and use the constructor to initialize all of them.
For reference, the following code works as expected:
public class Test {
public static enum MyEnum {
valueA(1),valueb(2),valuec(3),valued(4);
private int i;
private Object o;
private MyEnum(int number) {
i = number;
}
public void set(Object o) {
this.o = o;
}
public Object get() {
return o;
}
}
public static void main(String[] args) {
System.out.println(MyEnum.valueA.get()); // prints "null"
MyEnum.valueA.set(new Integer(42));
System.out.println(MyEnum.valueA.get()); // prints "42"
}
}
the cause of this problem is the db40 framework . It loads an enum from the db using reflection. This is well documented .
http://developer.db4o.com/Forums/tabid/98/aft/5439/Default.aspx

Categories