Actual and Formal arguments differ in length - don't know why - java

I'm a beginner Java programmer, and I have two simple files to solve a simple math problem. One of them calls the other, which calculates the factorial of the number (e.g. 4! = 24). For some reason, I can't call the Factorial constructor.
Here is the calling class:
package Permutations;
import Permutations.Factorial;
public class Permutations {
public static void main(String args[]) {
System.out.println("There are 10 students. Five are to be chosen and seated in a row for a picture. How many linear arrangements are possible?");
System.out.println(new Factorial(10) / new Factorial(5));
}
}
Here is the Factorial class
package Permutations;
public class Factorial {
public long Factorial(int num) {
long result = 1;
for(int i = num; i > 0; i--)
result *= i;
return result;
}
}
Here is the error:
Permutations\Permutations.java:7: error: constructor Factorial in class Factoria
l cannot be applied to given types;
System.out.println(new Factorial(10) / new Factorial(5));
^
required: no arguments
found: int
reason: actual and formal argument lists differ in length
Permutations\Permutations.java:7: error: constructor Factorial in class Factoria
l cannot be applied to given types;
System.out.println(new Factorial(10) / new Factorial(5));
^
required: no arguments
found: int
reason: actual and formal argument lists differ in length
2 errors
I could change it to a static method, but then I would have to call it with Factorial.Factorial(num) rather than new Factorial(num), which would be inconvenient.
I have no idea why this is happening. Please help!
Thanks.
EDIT
Thanks for the answers. I've figured out what I've done wrong.

To begin with, what you have written is not a constructor. Constructor don't have return type.
So, in absence of constructors, your class has defined a default constructor that takes no arguments (which is the one the compiler dutifully tells you to use, since you try to create a new instance).
Solutions:
use a static method instead of trying to use instance. Seems the most practical approach
if you must use a class because it is homework, define both the constructor and a getFactorial method. The getFactorial may have a return type, and provide you the value that you want. You will have to use it in something like that
Factorial fac1 = new Factorial(5);
System.out.println("Factorial " + fac1.getFactorial());
or even
System.out.println("Factorial " + (new Factorial(5)).getFactorial());
Usually the first version is prefered for readability.

There is no constructor in your class that takes a long argument. You are mistaken by the fact that this method is a constructor:
public long Factorial(int num)
Constructors don't have a return type. As you have mentioned a return type to above signature, hence it has become a normal method and not a constructor.
And when there is no constructor written in class, then compiler provides a no parameter constructor and hence it is throwing an error with reason:
reason: actual and formal argument lists differ in length

Constructors cannot have user defined return type:
They can be just:
public constructor(parameter p){
// TO DO SOMETHING
}
And you cannot pass value in System.out.println() as new Something(); . Only methods can be passed like that which have some return type.

When you declared
public long Factorial(int num)
, this isn't a constructor for Factorial, since it's typed as long. A constructor would have to be declared as follows:
public Factorial(int num)
Since you haven't declared a constructor, the only existing constructor is the default one, which takes no arguments, and so when you call
new Factorial(10)
you get an error, since new Factorial takes no arguments with the only existing constructor.
Edit: Also, even if you fix that, you can't take
new Factorial(10) / new Factorial(5)
because division isn't defined on factorials.

First please refer to the Java Code Conventions for naming packages and classes and methods.
Second you mixed up constructor and methods of a class. A constructor has the same name as the class and no return value. It is used with the new keyword to generate an instance of the class.
You have written a method called "Factorial" with the return type int (see coding guidelines why you should use lower case). Since your class is missing a constructor Java has added a default one with no parameters. But you try to call an constructor with an int parameter. This is why you get the error.
To call your method Factorial on the object Factorial you would need to generate a new instance and call the method with the int param. Like this:
int fact = new Factorial().Factorial(5)
However for your example an object creation is not needed so maybe go for a static method factorial instead.

Related

How compiler is determining which constructor to use if both take one variable of same kind (int and Integer) [duplicate]

This question already has an answer here:
why java supports function overloading for primitive data types? [duplicate]
(1 answer)
Closed 5 years ago.
I have a package myPackage which contains 2 classes. First one has 2 public constructors that take a numeric value. First one takes an int and the second one takes Integer. As far as I know they both are the same, just one of them is a primitive type.
When I make an object reference in the other class and run it, in result it calls a constructor that takes the int value.
My question: How it is determined which constructor is called in this case?
P.S. Sorry if this question is too simple. I'm just starting to learn Java.
package myPackage
public class myPackageClass{
public myPackageClass(int var){
System.out.println("Constructor + int value["+var+"]");
}
public myPackageClass(Integer var){
System.out.println("Constructor + Integer value["+var+"]");
}
}
the test file
package myPackage
public class testClass{
public static void main(String ... arg){
myPackageClass var2= new myPackageClass(1);
}
}
}
and the output :" Constructor + int value[1] "
They are not exactly of the same type. 1 is of type int, but new Integer(1) would be of type Integer. So if you would do new myPackageClass(new Integer(1)) the output would be Constructor + Integer value[1]
Other options of passing an Integer instead of int are: new myPackageClass((Integer)1) and new myPackageClass(Integer.valueOf(1))
First it will lookup after one constructor with the same parameter (myPackageClass(int) in your case).
Then, if no constructor is found, then will lookup for one with Box/Unbox parameter ( myPackageClass(Integer) )
You can see the algorithm here : jls-15.12.2
if you create the integer like this : Int i = new Integer(1); The second method will be invoked. If you create the integer like this Interger i = 1; if it is within range -128 ~127 the first method will be invoked else the sencond will be involed. If you use the constrctor directly like this A(1); the first method will be invoked

Array Containing Methods/Functions for Argument Passing

I have a method that selects between the arguments of an array and returns a specific one. For instance, here is that method:
private <T> T selectOnType(T[] selection, T defaultOp){
switch(this.type){
case Resources.TEXT:
return selection[Resources.TEXT];
case Resources.LISTEN:
return selection[Resources.LISTEN];
default:
return defaultOp;
}
}
How can I construct an array full of method references (i.e. function pointers) in order to be able to pass that array into this method above?
I tried doing such things as:
java.util.function.Function<Void, Void>[] array = {ClassA::method1, ClassA::method2};
(where method1 and method1 take no arguments and return void)
But that throws a compiler error saying:
incompatible types: invalid method reference but expected no arguments. found: java.lang.Void reason: actual and formal argument lists differ in length
I have been playing around with lambdas such as:
() -> ClassA.method1()
But I haven't been able to get it to work. Does anyone know what I am doing wrong and know a solution to this problem?
EDIT:
I have seen this on Stack Overflow, but this is for C# and I haven't figured out how to mimic it in Java.
Example:
Let's say I have a Word class:
public class Word{
private final String text;
private int listenCorrect = 0, textCorrect = 0;
public Word(final String test){
this.text = text;
}
public void incListenCorrect(){
listenCorrect++;
}
public void incTextCorrect(){
textCorrect--;
}
}
And finally I have a Main class. Inside the action method (in the Main class) I want to have an array with these two methods in it in order to select between them if the type (shown below) is either listen or text:
public class Main{
int type = 0;
public void action(){
Word word = new Word("Hello");
// 'Functions' is used to represent something I tried above (just for demonstration)
Function[] array = {word::incListenCorrect, word::incTextCorrect};
Function picked = selectOnType(array, word::incTextCorrect);
picked.call();
}
/*
* Resources is another class that contains the following values:
* public static final int TEXT = 0;
* public static final int LISTEN = 1;
*/
private <T> T selectOnType(T[] selection, T defaultOp){
switch(this.type){
case Resources.TEXT:
return selection[Resources.TEXT];
case Resources.LISTEN:
return selection[Resources.LISTEN];
default:
return defaultOp;
}
}
}
A Function is a method that takes one argument and returns a result. You're using methods that take no arguments and do not return results. You can't use Function for this (using Void isn't a way to get around this), but the java.util.function package contains a number of classes for different common combinations (methods that take no arguments but return a result, methods that take one or two arguments and don't return a result, methods that take primitive arguments or return primitive results that won't work in a Function because the types aren't class types, etc.).
There isn't a class in java.util.function for a functional interface with no arguments and no result, but Runnable can be used for that.
You need to make sure you use the correct interface.
Note: I was assuming method1 and method2 are static methods, so that they don't take any arguments, even a hidden "instance" argument that instance methods take. If they're instance methods, then things have to be done differently.
Now that you've clarified that they're instance methods, things are different--but it depends on how you get the method. If you say
Word::incListenCorrect
since you're using the class name, you need to provide the instance as an argument. Therefore, Word::incListenCorrect returns a functional interface for a method that takes one argument, such as Consumer<Word>, and you have to pass the Word as the argument when you call the method with .accept(). But:
word::incListenCorrect
is very different. Now, the word instance becomes "baked into" the method reference, so it doesn't need to be passed as an argument. In this case, therefore, you'll still need the interface that takes no arguments and does not return a value, which is Runnable. When you say
Runnable r = word::incListenCorrect;
r.run();
where r is a Runnable, it will automatically use word as the instance for the instance method, since word became part of r when you assigned the method reference to it.

Method reference to local class constructor

There are several similar questions on SO about method reference to local class constructor, but I'd like to clarify slightly other thing. Consider following piece of code:
static Callable gen(int i) {
class X {
int x = i;
public String toString() { return "" + x; }
}
return X::new;
}
...
System.out.println(gen(0).call());
System.out.println(gen(1).call());
Obviously this will printout
0
1
It turns out, that X class has constructor of the form ...$X(int) (you can find it via X.class.getDeclaredConstructors()).
But what is interesting here, is that returned lambdas (or method references) aren't simple reference to constructor ...$X(int) like, for example, Integer::new. They internally invoke this constructor ...$X(int) with predefined argument (0 or 1).
So, I'm not sure, but looks like this kind of method reference is not precisely described in JLS. And there is not other way except this case for local classes, to produce such kind of lambdas (with predefined constructor arguments). Who can help clarify this?
To be precise:
where is in JLS such kind of method reference described?
is any other way to create such method reference to arbitrary class constructor with predefined arguments?
You are focusing too much on irrelevant low level details. On the byte code level, there might be a constructor accepting an int parameter, but on the language level, you didn’t specify an explicit constructor, hence, there will be a default constructor without any arguments, as with any other class.
This should become clear when you write the pre-Java 8 code:
static Callable<Object> gen(int i) {
class X {
int x = i;
public String toString() { return "" + x; }
}
X x=new X();
…
You instantiate X by its default constructor, not taking any arguments. Your local class captures the value of i, but how it does so on the low level, i.e. that X’ constructor has a synthetic int parameter and the new expression will pass the value of i to it, is an implementation detail.
You can even add an explicit constructor as
X() {}
without changing anything.
Obviously, you can also write the expression new X() inside a lambda expression here, as expressions don’t change their semantic when being placed inside a lambda expression:
return () -> new X();
or use it’s short-hand form, the method reference
return X::new;
There is nothing special about it, the behavior is understandable even without referring to the specification, if you forget about the distracting low level details. X may capture as many local variables as you like, the constructor’s number of parameters doesn’t change (on the language level).
This behaviour is defined in the JLS section §15.13.3:
If the form is ClassType :: [TypeArguments] new, the body of the invocation method has the effect of a class instance creation expression of the form new [TypeArguments] ClassType(A1, ..., An), where the arguments A1, ..., An are the formal parameters of the invocation method, and where:
The enclosing instance for the new object, if any, is derived from the site of the method reference expression, as specified in §15.9.2.
The constructor to invoke is the constructor that corresponds to the compile-time declaration of the method reference (§15.13.1).
Although this talks about enclosing instances, captured variables and parameters are not mentioned in §15.13.3.
As for your second question, you need to manually capture and change the parameter:
static Callable gen(int i) {
final int i1 = someCondition() ? i : 42;
class X {
int x = i1; // <-
public String toString() { return "" + x; }
}
return X::new;
}

Multiple sub-class that similar but different

I've 2 similar classes, one that receives 1 parameters (lets says int type) and the other receives the same type of parameter twice. For both input I need to have the same check (and throw exception if data isn't good) and both classes will have some functionality.
I thought of creating supertype that will have 2 constructors, one with 1 parameter, and the other one with 2 parameters. That will work but the question, what should be done in case there was the option of having three or more parameter.
So I thought to try here if there is any better option.
Thanks.
What should be done in case there was the option of having three or more parameter?
Try with Varargs that took an arbitrary number of values required you to create an array and put the values into the array prior to invoking the method/constructor.
Read the chapter here on Varargs from Eclipse.
Java Variable Arguments
arargs is a helper syntax and it enables use of variable number of arguments in a method call. In method definition variable aruguments are indicated by elipsis (…) and is called as variable arity method and variable arity parameter in java language specification. While invoking the varargs method we can use any number of arguments of type specified and separated by comma.
Varargs Sample
public class VarArgSample {
static int sum(int i, int... marks) {
int total = 0;
for (int mark : marks) {
total = total + mark;
}
return total;
}
public static void main(String[] args) {
// invoking with variable arguments
System.out.println(sum(1, 2, 3));
// same invocation using an array
int arr[] = { 2, 3 };
System.out.println(sum(1, arr));
}
}
How Varargs Works?
When invoking with variable arguments, compiler matches the argument list from left-to-right with the formal parameters. Once initial set of parameters are matched, then whatever arguments are remaining are constructed as an array and passed to the method.
In the given example, value ’1′ is passed as argument for variable ‘i’ then there are no other arguments remaining except varargs. So the remaining values ’2, 3′ are constructed as array and passed as parameter. This is how the dynamism is achieved.
solution
In your case there was the option of having three or more parameter then simply try with
MyClass(int i, int j, int... k){}

Invoking statically imported method with explicit type parameters

This is the follow up of my question here: Weird Java generic.
If I have a code like this:
Casts.<X, T> cast(iterable[index]);
Can I add a static import and do:
<X, T> cast(iterable[index]);
Eclipse doesn't allow this. But after seeing so many bugs with static import in Eclipse, I'm not that certain.
No, you can't : I just confirmed this via some test code.
PS > javac -version
javac 1.6.0_04
Casts.java
public class Casts
{
public static <From, To> To cast(final From object)
{
return (To)object;
}
}
Test.java
import static Casts.cast;
public class Test
{
public static void main(String[] args)
{
final Integer integer = new Integer(5);
// This one compiles fine.
final Number number = Casts.<Integer, Number>cast(integer);
// This one fails compilation:
// PS> javac Test.java
// Test.java:11: illegal start of expression
// final Number number = <Integer, Number>cast(integer);
// ^
// Test.java:11: not a statement
// final Number number = <Integer, Number>cast(integer);
// ^
final String string = <Integer, String>cast(integer);
}
}
No
If you want to provide an explicit type parameter when calling a generic static method, you must prefix the method with the class name, even if the method is statically imported.
Java grammar allows type arguments only with typename specified. See corresponding section in JLS https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-MethodInvocation
I'm pretty sure the answer is no--if you want to use a generic method call, you need an object to call it on (foo.<T>doSomething()). If the method is static, you need the class ( Foo.<T>doSomething() ).
This is even true if you're calling the method from elsewhere in the class itself. If you are working in a non-static method (i.e. in an instance method), you would call this.<T>doSomething().
As far as I've read, a shortcoming of the static import mechanism is that you must specify the calling object/class if you wish to provide formal parameters. In this example, it's not very clear why there are two generic parameters, but if you wish to avoid having to specify the calling object/class you can type hint through a cast of the arguments as such:
public static <E> E foo(E e) {}
Number n = foo((Number)3);
With the type hint, the type inference will return an object of type Number, instead of Integer as it would have reasoned otherwise.

Categories