Using links to static and non-static methods with interface - java

Why I can call non-static method length() from class String, but I can't call non-static method lengthHelper( String line ) from my class ExpressionHelper?
public static void main(String[] args) {
String[] lines1 = {"H", "HH", "HHH"};
System.out.println(sum(lines1, String::length));
System.out.println(sum(lines1, s -> s.length()));
System.out.println(sum(lines1, ExpressionHelper::lengthHelper)); //wrong
}
interface Expression {
int length(String line);
}
static class ExpressionHelper {
int lengthHelper(String line) {
return line.length();
}
}
private static int sum(String[] lines, Expression func) {
int result = 0;
for (String i : lines) {
result += func.length(i);
}
return result;
}

String::length is an instance method of String. It requires an instance of String to run, which you are providing, because you are passing elements of lines1 to it.
ExpressionHelper::lengthHelper is an instance method of ExpressionHelper. In addition to the explicit String line argument, it requires an instance of ExpressionHelper to run, which you are not providing.
If you made lengthHelper a static method in ExpressionHelper, then you would be able to call it without an instance of ExpressionHelper.

In addition to the answer from khelwood:
If you change your code like this:
public static void main( String[] args )
{
final var expressionHelper = new ExpressionHelper();
String[] lines1 = {"H", "HH", "HHH"};
System.out.println(sum( lines1, String::length ) );
System.out.println(sum( lines1, s -> s.length() ) );
System.out.println(sum( lines1, ExpressionHelper::lengthHelper) ); //wrong
System.out.println(sum( lines1, expressionHelper::lengthHelper) );
}
it works also with ExpressionHelper::lengthHelper (although I should write better ExpressionHelper.lengthHelper() or ExpressionHelper#lengthHelper to avoid further confusion …)
Yes, I know, in this context it is nasty to name the variable same as the class, only having the first letter as lower case: it does not support readability.
But now expressionHelper is that instance of ExpressionHelper that #khelwood mentioned as missing in their answer.

Related

Variable (Function type) argument count and variable return type

I have the following question- I have to write one method, which will take variable amount of Function arguments and, based on that, will return the needed type. The problem is, that the functions from arguments are run in order:
public class Main {
public static void main(String[] args) throws Exception {
//Lambda expressions which will be taken as arguments in method.
Function<String,List<String>> flines = e->{
};
Function<List<String>,String> join = e ->{
};
Function<String,List<Integer>> collectInts = e->{
};
Function<List<Integer>,Integer> sum = e->{
};
// end of lambdas
String fname = System.getProperty("C:/LamComFile.txt");
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines, join);
List<Integer> ints = fileConv.convertBy(flines, join, collectInts);
Integer sumints = fileConv.convertBy(flines, join, collectInts, sum);
System.out.println(lines);
System.out.println(text);
System.out.println(ints);
System.out.println(sumints);
List<String> arglist = Arrays.asList(args);
InputConverter<List<String>> slistConv = new InputConverter<>(arglist);
sumints = slistConv.convertBy(join, collectInts, sum);
System.out.println(sumints);
}
}
As You can see, I need to create a class, which will have one method (overloading is not allowed) and based on what that method will receive, it has to return the correct type.
I have the beginning of the InputConverter class, but I have no idea how can make the next Functions get the arguments from the ones before.
public class InputConverter<T> {
private T obj;
public InputConverter(T obj) {
this.obj = obj;
}
public <what goes here?> and_here convertBy(Function<In,Out>... funcs){
}
}
I assume that I can do something like this?
if(funcs.length()==1){
what? = funcs[0].apply(this.obj);
return what?
}
You can't express that in Java's type system. Accept the need for something else. For example, you could just write f1.andThen(f2).andThen(f3).andThen(f4)....

Recursively reversing a sentence using void reverse() method (Java)

The tester class is:
public class SentenceWithReverseTester
{
public static void main(String[] args)
{
String[] list = new String[]{"aba",
"Madam, I'm Adam",
"nut",
"A man, a plan, a canal, Panama",
"wonderful",
"Go hang a salami, I'm a lasagna hog",
"race car",
"1",
"",
"zero",
"#!:"} ;
for (String line : list) {
SentenceWithReverse sentence = new SentenceWithReverse(line) ;
sentence.reverse() ;
System.out.println(line + " reversed becomes........") ;
System.out.println(sentence.toString()) ;
System.out.println("----------------------------") ;
}
}
}
And for the reverse method I have:
public void reverse()
{
String s = super.toString();
if(s.length() > 0)
{
String first = s.substring(0,1);
String remaining = s.substring(1, s.length());
SentenceWithReverse shorter = new SentenceWithReverse(remaining);
shorter.reverse();
System.out.println(shorter + first);
}
}
I'm not getting the result I want, and I'm not sure what I'm doing wrong here.
You should make reverse() actually return a String, rather than void, so that you can use the result of the reversal. So change void to String in the method's declaration. Then you'll need a couple of return statements inside the method - one for the base case and one for the recursive case.
In the recursive case, the return statement will be something like
return shorter.reverse() + first;
that is, you take the reverse of the shorter sentence, and put the first character back at the end.
In the base case, that is, where the input to the method is "", you can just write
return "";
I'll leave it to you to figure out where to insert these two return statements, within the logic of your method. Good luck.
You're not assigning any member fields in your reverse method. You don't show what fields you have, but I would guess you have a single String field that is returned from toString. You should assign the shorter + first to it where you have the System.out.println call.

Accessing a private variable from another class

NOTE: I have looked at the other posts, but I'm still quite lost.
This is the code for a private variable that I have in one class:
private int readFile( String fileName)
{
try
{
File f = new File( fileName );
Scanner input = new Scanner( f );
while( input.hasNextLine( ) )
{
String s = input.nextLine( );
String[ ] sArr = s.split( " " );
String animal = sArr[ 0 ];
double cost = Double.parseDouble(sArr [ 1 ] );
boolean penNeeded = Boolean.parseBoolean( sArr[ 2 ] );
boolean available = Boolean.parseBoolean( sArr[ 3 ] );
Pet p = new Pet( animal, cost, penNeeded, available );
if (count < animalList.length )
{
animalList[count] = p;
count++;
}
}
input.close( );
}
catch( Exception e )
{
System.out.println("Error reading the file:");
System.out.println( e );
e.printStackTrace( );
}
return count;
}
I need to access it in this piece of code located in another class:
static public void processTransaction( String fileName, PettingZoo pz )
{
try
{
// variable should be accessed here
}
catch( Exception e )
{
System.out.println("Error reading the file:");
System.out.println( e );
e.printStackTrace( );
}
}
How can I do this? I think that I need to use a modifier of some sort, but I don't know how which one or how to implement it.
You cannot directly access private variables from another class. That's the whole point of declaring it private. What you need to do is use setter and getter methods in class A, then call the get method from class B.
If you want access to a private variable, you can use getter and setter methods.
Example:
private int variable = 5; //<--- your private variable of class A
// a public method (into the same class A)
// that allows the sharing of your private variable
public int getVariable() {
return variable;
}
Now you can call the method getVariable() from an other class (B) and take the value of the private variable (of class A).
As per your comment you can access the private int readFile(String fileName) method by changing the modified of the method. Change the modifier of the method to public or protected. Also since the accessing method is static you need to change the method as static.
So change it as
public static int readFile( String fileName)
{
}
In the processTransaction method invoke it as,
ClassName.readFile("file_name.extn");

package rjava jcall error in R

I want to use R to input a parameter into Java, for example "1000". Then method of StringToNum process and output its return to R,namely 1000. Seems it is the work of .jcall(), but I dont know how to do with its parameters.As I dont know Java, Could you please help me?
Thank you very much!
Java code
package com.mingdong.rcalljava.test;
import java.io.PrintStream;
public class StringToNum
{
private String inputString = null;
public StringToNum(String inputString)
{
this.inputString = inputString;
}
public StringToNum()
{
}
public int convertStringToInt()
{
if (this.inputString == null) {
this.inputString = "100";
}
return Integer.valueOf(this.inputString).intValue();
}
public static void main(String[] args)
{
StringToNum stringToNum = new StringToNum();
int num = stringToNum.convertStringToInt();
System.out.println("num:" + num);
}
}
R code
library(rJava)
.jinit()
.jinit('D:/Eclipse/dailyjob/javaProject/TestRCallJava.jar')
## .jaddClassPath("D:\\Eclipse\\dailyjob\\javaProject\\TestRCallJava.jar")
inputString <- .jnew("java.lang.String","1000")
inputString %instanceof% "java.lang.String"
StringToNum <- .jnew("com.mingdong.rcalljava.test.StringToNum")
StringToNum %instanceof% "com.mingdong.rcalljava.test.StringToNum"
.jcall(StringToNum,returnSig= "V", "main",inputString )
Error in .jcall(StringToNum, returnSig = "V", "main") :
method main with signature ()V not found
There are two issues. On the Java side in main you call the constructor new StringToNum() which does not exist. The main method should rather look like:
public static void main( String[] args ) {
StringToNum stringToNum = new StringToNum( args[0] );
int num = stringToNum.convertStringToInt();
System.out.println("num:" + num);
}
Maybe this solves already your problem. However, in general you call static methods in Java not on the object but on the class. If you'd call the main method from Java you'd have to call
StringToNum.main( "1000" );
instead of calling
StringToNum obj = new StringToNum( "" );
obj.main( "1000" );
You should also avoid to call the low-level functions (indicated by starting with a .) of the rJava package. So as indicated in rJava .jcall return type issue the proper call would be
J("com.mingdong.rcalljava.test.StringToNum")$main( "1000" ) # untested

reflection static method argument string

public class Star{
public static ArrayList initdata(String pattern) {
ArrayList data = new ArrayList();
if (pattern != "") {
ModelCollection mc = Star.find(pattern, 0);
Iterator dataIterator = mc.iterator();
while (dataIterator.hasNext()) {
Star star = (Star) dataIterator.next();
data.add(star.getName());
Debug.trace("StarName" + star.getName());
}
}
Collections.sort(data);
return data;
}
}
I want to invoke method initdata using reflection, I tried to write something like this , but it does not work:
Class c = Class.forName("com.cubiware.fyretv.application.model.Star");
par[0] = String.class;
Method mthd = c.getMethod("initdata", par);
ArrayList output = (ArrayList) mthd.invoke(null, null);
try
ArrayList output = (ArrayList) mthd.invoke(null, (String)null);
It's not good idea to pass null, when method expects Object...
May be this will help
Calling Java varargs method with single null argument?
First, Your check seems weird to me: try if (pattern != null) instead of if (pattern != "").
Why don't you pass the par array, you have illegal argument exception I think. try passing arguments array.
Object[] args = {"someString / maybe null"};
ArrayList output = (ArrayList) mthd.invoke(null, args);
Obviously, your invoke call is similiar to
initdata(null);
Now, inside initdata you do not filter the case where pattern == null which leads us to a call
Star.find(null, 0);
We do not know the implementation of this method - if we're lucky, we get an empty collection. Otherwise, I expect a NullPointerException either in Star.find or later at mc.iterator()
$ javac -cp dp4j-1.2-SNAPSHOT-jar-with-dependencies.jar -Averbose -All Star.java
Star.java:12:
import com.dp4j.*;
public class Star {
public Star() {
super();
}
public static ArrayList initdata(String pattern) {
return null;
}
#Reflect()
public static void main(String[] args) throws java.lang.ClassNotFoundException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException, java.lang.reflect.InvocationTargetException, java.lang.IllegalArgumentException {
final java.lang.reflect.Method initdataWithStringMethod = Class.forName("Star").getDeclaredMethod("initdata", .java.lang.String.class);
initdataWithStringMethod.setAccessible(true);
initdataWithStringMethod.invoke("", new .java.lang.Object[1][]{null});
final java.lang.reflect.Method printlnWithStringMethod = Class.forName("java.io.PrintStream").getDeclaredMethod("println", .java.lang.String.class);
printlnWithStringMethod.setAccessible(true);
printlnWithStringMethod.invoke(System.out, new .java.lang.Object[1][]{"Varargs + reflection? No problem"});
}
}
public static void main(String args[]) {
^
$ java Star
Varargs + reflection? No problem

Categories