Java can't find public static method - java

I'm working on a programm where a two lists are created and they have to be compared to find if there are two RECURS that are the same. I'm testing if it works (and have to use these methods) but I keep having the same problem; cannot find symbol.
public class Duplicate {
public Duplicate(){};
static ArrayList<Recurs> findDuplicate(ArrayList<Recurs> l1, ArrayList<Recurs> l2){
ArrayList<Recurs> l3 = new ArrayList<>();
for(int i=0; i<l1.size(); i++){
for(int j=0; j<l2.size();j++){
if(l2.get(i).equals(l1.get(j))){
l3.add(l1.get(i));
}
}
}
return l3;
}
}
This code is supposed to work. By the way, I've programmed a class called Recurs, which supposedly also works (I made another test and that worked ok where I created an equals method).
The problem comes now.
public class Test {
public static void main (String[] args){
Recurs o = new Recurs(3, "a");
Recurs e = new Recurs(2, "b");
Recurs m = new Recurs(4, "a");
Recurs n = new Recurs(2, "b");
ArrayList<Recurs> l1= new ArrayList<>();
l1.add(o);
l1.add(e);
ArrayList<Recurs> l2= new ArrayList<>();
l2.add(m);
l2.add(n);
ArrayList<Recurs> l3 = new ArrayList<>(findDuplicate(l1, l2))
}
}
I create a test where it is supposed to show me that this part is working, but i've got a problem at the last line of code, because it tells me it cannot find findDuplicate.
I'm new at using Java, if someone finds the problem, could they also point out the reason why it is happening?

Static methods "belong" to the class they are written in.
Here:
findDuplicate(l1, l2)
tries to call a (static) method in the Test class! Because it is an unqualified call, so the compiler will look inside the class that call takes place (which is Test). But there is no findDuplicate() method in the Test class!
Instead, it comes from the Duplicate class, so you need:
Duplicate.findDuplicate(l1, l2)
( alternatively, you could do a static import of that method, but for newbie learning things, I recommend to avoid doing that )
And of course, the method must also be visible to your Test class. So either the two classes should be in the same package, or as mentioned in various comments, that method needs the public modifier.

Without any modifier, your method will be only accessible to its own class, subclasses and the package. To make it accessible to your test, you could make it public but it is customary for test classes to share the same package as the classes they test by adding
package reverse.domain.name.app;
above both your class and your test class.
Secondly, your method is static, which means it is associated to the class, not its instance. this means that you should refer to it by its classname:
Duplicate.findDuplicate()

Related

Why Must this method be static(Java)?

For some background, I'm currently on chapter 8 in my book, we finished talking about arraylists, arrays, if statements, loops etc. Now this part of the book talks about call by reference,value and some other pretty neat things that seem odd to me at first.I've read What situation to use static and some other SO questions, and learned quite a bit as well.
Consider the following example my book gave (among many examples)
There is another reason why static methods are sometimes necessary. If
a method manipulates a class that you do not own, you cannot add it to
that class. Consider a method that computes the area of a rectangle.
The Rectangle class in the standard library has no such feature, and
we cannot modify that class. A static method solves this problem:
public class Geometry
{
public static double area(Rectangle rect)
{
return rect.getWidth() * rect.getHeight();
}
// More geometry methods can be added here.
}
Now we can tell you why the main method is static. When the program
starts, there aren’t any objects. Therefore, the first method in the
program must be a static method.
Ok, thats pretty cool, up until now I've just been really blindly putting public in front of all my methods, so this is great to know. But the review small problem on the next page caught my attention
The following method computes the average of an array list of numbers:
public static double average(ArrayList<Double> values)
Why must it be a static method?
Here I was like wait a sec. I'm pretty sure I did this without using static before. So I tried doing this again and pretty easily came up with the following
import java.util.ArrayList;
class ArrList
{
private double sum;
public ArrList()
{
sum = 0;
}
public double average(ArrayList <Double> values)
{
for(int i = 0; i < values.size() ; i++)
{
sum+=values.get(i);
}
return sum / values.size();
}
}
public class Average
{
public static void main(String [] args)
{
ArrList arrListObj = new ArrList();
ArrayList<Double> testArrList = new ArrayList<Double>();
testArrList.add(10.0);
testArrList.add(50.0);
testArrList.add(20.0);
testArrList.add(20.0);
System.out.println(arrListObj.average(testArrList));
}
}
TLDR
Why does my book say that public static double average(ArrayList<Double> values) needs to be static?
ATTEMPT AT USING STATIC
public class Average
{
public static void main(String [] args)
{
ArrayList<Double> testArrList = new ArrayList<Double>();
ArrayList<Double> testArrListTwo = new ArrayList<Double>();
testArrList.add(10.0);
testArrList.add(50.0);
testArrList.add(20.0);
testArrList.add(20.0);
testArrListTwo.add(20.0);
testArrListTwo.add(20.0);
testArrListTwo.add(20.0);
System.out.println(ArrList.average(testArrList));
System.out.println(ArrList.average(testArrListTwo)); // we don't get 20, we get 53.3333!
}
}
It doesn't.
The only method which needs to be static is the initial main() method. Anything and everything else is up to you as the programmer to decide what makes sense in your design.
static has nothing to do with public accessors (as you allude to), and it has nothing to do with the technical operation being performed. It has everything to do with the semantics of the operation and the class which holds it.
An instance (non-static) method exists on a particular instance of a class. Semantically it should perform operations related to that specific instance. A static method exists on a class in general and is more conceptual. It doesn't do anything to a particular instance (unless it's provided an instance of something as a method argument of course).
So you really just need to ask yourself about the semantics of the operation. Should you need new instance of an object to perform an operation? Or should the operation be available without an instance? That depends on the operation, on what the objects represent, etc.
If it is not static, then any other class that wants to use this method must first create an instance of this object.
From some other class:
Average.average(new ArrayList<Double>()); // legal only if static
new Average().average(new ArrayList<Double>()); // necessary if not static
// and only makes sense if Average can be instantiated in the first place
It's legal to make it an instance (i.e. not static) variable, but the method is actually harder to understand. If it is static then whoever reads the code knows it does not use any member variables of the class.
// In the class body
int x = 0; // member variable
public static double average() {
x = x + 1; // illegal
}
The less something can do, the easier to understand what it does do.
Static methods like the area, average are usually utility functions. You don't need any object to use an utility function. For example consider Math.pow you don't need to instantiate any object to use the power function, just use Math.pow(10.0, 2.0) to get (10.0)^2
In short :
Static method means class method, that is no instance of that object is needed to invoke.
whereas your average method is an instance method, you need an object to invoke that method.

creating arrays on-demand in java

I consider myself an intermediate Java programmer having been at it for a year and a half and having some experience in other languages. However I have run into an issue that I feel I need an experts help on.
As I understand it arrays when created by java exist somewhat outside of where they were created i.e. if you create an array called s in one class and another called s in a second class then try to use both those classes as part of a program you will run into problems with them overwriting each other.
However this brings me to an interesting dilemma. What if one wanted to create a unique array on-demand for an infinite number of sets of user input. i.e. is it possible to have the user enter a string value for use as the array name or have a generic value that then gets a number or letter appended to it. This is more a theoretical issue (there being other ways to accomplish the same thing) but any insight would be greatly appreciated.
i.e. is it possible to have the user enter a string value for use as
the array name or have a generic value that then gets a number or
letter appended to it.
The user should not need to care about your array names. The name of an array should neither be visible to the user, nor should it affect your application in any way.
If you want to allow the user to create collections of elements that he can store under a FriendlyName you could use a (Hash)map for that:
Map<String, Integer[]> userDefinedArrays = new HashMap<>();
userDefinedArrays.put("NameTheUserSelectsForThisArray", new Integer[]{1,2,3});
The "Key" of this map will be the FriendlyName provided by the user - he still does not know, that the actual map is called userDefinedArrays - or even someMapThatHoldsSomeThingsTheUserWantToUse.
The name of a actual variable needs to be set during designtime and is fixed (at least in java)
if you create an array called s in one class and another called s in a second class then try to use both those classes as part of a program you will run into problems with them overwriting each other.
No! Each Variable declared exists inside it's own scope! You can change the value of an array inside it's scope, and also reuse the same name inside different scopes - it doesn't matter. If you try to redeclare a variable already existing withing the current scope your compiler will warn you! - you simple can not do that.
Example:
class MyApplication{
public static void Main(String[] args){
Integer[] arr1;
Integer[] arr1; //Compiler error!
}
}
but:
class MyApplication{
public static void Main(String[] args){
Integer[] arr1;
Integer[] arr2;
}
}
or
class MyApplication{
public static void Main(String[] args){
foo();
bar();
}
public static void foo(){
Integer[] arr1;
}
public static void bar(){
Integer[] arr1;
}
}
is fine. arr1 just exists within the scope of either foo() or bar().
As I understand it arrays when created by java exist somewhat outside of where they were created i.e. if you create an array called s in one class and another called s in a second class then try to use both those classes as part of a program you will run into problems with them overwriting each other.
I think maybe you are misunderstanding. This will not happen unless you do it intentionally like yshavit points out in your comments. A member of a class named S in the class Cat, will not point to a member named S in the Dog class. You would have to go out of your way to do this.
In short, this will not happen by accident most of the time if you are instantiating your classes without passing references between them when you do.
What if one wanted to create a unique array on-demand for an infinite number of sets of user input.
You may want to use an ArrayList
ArrayList<String[]> myList = new ArrayList<String[]>();
Or a hashmap
Map<Integer,String[]> myMap = new HashMap<Integer,String[]>();
Which one you use depends on what you are using it for. If you need faster access to arbitrary elements use a map. If you plan to access them iteratively, an ArrayList will work fine.
is it possible to have the user enter a string value for use as the array name or have a generic value that then gets a number or letter appended to it. This is more a theoretical issue (there being other ways to accomplish the same thing) but any insight would be greatly appreciated.
In this case you want to use the hashmap solution, You can choose the key type of a map in java quite easily.
You will want to read this
http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
or this, to get started.
http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html
Two different class you're talking about is ClassOne & ClassTwo in my example. As you told, there is some kind of conflict while keeping the field name same. I've used arr for both classes. The reason to make MyArray super class is just code reuse. Why I used abstract MyArray class & why I used public static field isn't our matter of discussion. In TestApp, I've used arr of both classes ClassOne & ClassTwo without any problem.is it possible to have the user enter a string value for use as the array nameIMHO it may be possible using Reflection API or Dynamically Typed Language can do it. I'm not much sure about that.
class ClassOne extends MyArray {
public static int[] arr = new int[5];
}
class ClassTwo extends MyArray {
public static int[] arr = new int[5];
}
abstract class MyArray {
public static void setValue(int arr[], int index, int value) {
arr[index] = value;
}
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
public class TestApp {
public static void main(String[] args) {
ClassOne.setValue(ClassOne.arr, 1, 30);
ClassTwo.setValue(ClassTwo.arr, 1, 50);
ClassOne.printArray(ClassOne.arr);
ClassOne.printArray(ClassTwo.arr);
ClassTwo.printArray(ClassOne.arr);
ClassTwo.printArray(ClassTwo.arr);
}
}

Why can't I instantiate outside any method in java?

Please ignore my arrogance......learning java these days, i came across this perfectly same question for my problem : Why can't I instantiate and create Object without main method? (Stack Overflow Error)
Expecting a possible downvote too...but please go through my question once!!!!
Code that i was trying :
public class Arrayprg{
Arrayprg ag = new Arrayprg(); //ignore this for a while and go thru code please
public static void main(String []args){
System.out.println("Hello Array");
new Arrayprg().declarearray();
}
public void declarearray()
{
int[] arr;
arr = new int[11];
new Arrayprg().assignarr(arr);
}
public void assignarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
arr[i] = i;
}
new Arrayprg().printarr(arr);
}
public void printarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
System.out.println(arr[i]);
}
}
}
Thinking logically, going through the code you'll see lots of new arrayprg()....what i thought of was to instantiate outside of methods and calling all methods through it there after, but i guess it is not allowed in java.
Whats causing my Problem
Going by the solution in quoted question, as it explain that below thing happens :
Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
Explanation given in that question
.....it is initialized whenever an instance of the class is instantiated. This will never terminate until you run out of memory and get the stack overflow. Run it with a debugger for a clearer view.
My Question
so i have Arrayprg ag = new Arrayprg(); in my program which is creating a loop every-time i create an instance but why is this called when i am calling the functions through new Arrayprg().
What i mean is that when i am calling the function through new Arrayprg() inside the methods why is Arrayprg ag = new Arrayprg(); getting called and creating the loop of error for Stackoverflow?????
This will cause a StackOverflowError.
The line you tell us to ignore, interestingly, is the culprit. When you instantiate a new Arrayprg then any object initializers are called, including new Arrayprg() which will then recursively try to keep invoking constructors without end. Remove that line, or put it in a static initializer. Better yet, just don't create that Arrayprg outside the main method as your Arrayprg does not need an instance of Arrayprg itself,
I would be more clear but I don't know what you're trying to achieve.
Solution : Change this line:
Arrayprg = new Arrayprg(); //ignore this for a while and go thru code please
to:
static Arrayprg a = new Arrayprg();
And you will no longer get your infinite recursion problem as now it will only create one instance of it shared between all instances - rather than each instance immediately creating a new one.
The Explanation
As part of constructing an Object in Java all member variable initializers, initializer code blocks, etc are all called as well as the constructor itself.
So in order to create a new Arrayprg one of the things it does is look for member variables that need initializing and initialize them.
In this case it finds Arrayprg a = new Arrayprg();, so in order to initalise the field a, it tries to create a new Arrayprg().
But that new Arrayprg() goes through the exact same process again, and again, and again, etc.
There are a number of ways to fix this - including:
Pass in the Arrayprg as a parameter to the constructor - so a new one doesn't need to be created.
Make the Arrayprg static - so only a single one needs to be created once rather than creating a new one each time
Lazy initaliziation on the Arrayprg so that you only create it the first time you try and access it rather than when the parent Arrayprg is created.
Why it doesn't happen in a method call:
The important thing that causes the recursion here is that the call happen during the creation of a new object. If trying to create a new object involves creating another copy of the same object then you will end up with infinite recursion which will then cause the failure.
So you can create a new object anywhere you like - so long as it is not inside the creation of itself.
class A {
A a = new A(); // Recursion
}
class A {
A() {
A a = new A(); // Recursion
}
}
class A {
A getNewA() {
return new A();
// This is fine as it doesn't happen during creation of an A
}
}
class A {
A() {
getNewA();
// Recursion as calling getNewA creates a new A, which calls getNewA, which....
}
A getNewA() {
return new A();
// This is fine on its own but is broken if called from the constructor
}
}
class B {
A a = new A();
// This is fine as B is not A, so you can create a new A within B.
}
Let's step through this visually.
Arrayprg = new Arrayprg();
So what do you need to create an object of type Arrayprg? Well you need to create it's fields.
Arrayprg = new Arrayprg();
And once again, you're telling the JVM to give you another Arrayprg object. By definition, this means making another Arrayprg object.
This is giving you a StackOverflowException.
Solution?
You shouldn't really be nesting types like this. It's pointless. You're inside the class already, so use it's methods.
public void declarearray()
{
int[] arr;
arr = new int[11];
assignarr(arr);
}
Follow this pattern, and you'll eliminate the need for the Arrayprg field.
Every time you create an instance of Arrayprg, you call this line: Arrayprg = new Arrayprg();, this means every time you create one, it creates another and another and another etc. You can instantiate objects there, but instantiating another object of the same type causes your infinite loop.
Also, in your methods (declareArr, assignArr etc) you can remove the 'new Arrayprg().' and just call the functions on the existing object.
In a class you can create objects outside any method, object cannot be of the same class.
It is meaningless. Take it as a rule.

Is static bad? How to remove static variables?

I have some code that I am working on. It's basically takes in user input and creates a directed graph. One person can travel one way, the other person the opposite. The output is the overlap of where they can visit.
I have most everything working the way that I want it to, but I am concerned with the use of static that I have. I don't seem to fully understand it and no matter where I look, I can't find out its exact use OR how to get rid of it.
Could someone please help me to understand what static is and why it would be helpful?
Also, would it be better to move most the code from MAIN to helper methods? If I do this I have to move all my variables from main to the top of the class and then they all have to be declared as static?!
The reason everything has to be static is because you aren't creating any objects. If you were to create an object by calling new in your main method, you could use non-static variables on that object. This isn't really a good place to give you a tutorial on why you might want to use object-oriented design; you can find one of those online to read (a commenter above gave a possible reference). But the reason everything has to be static is because it's all just running from the main method, which is always static in java. If you were to call new somewhere, you could use non-static variables.
Static makes a method or a variable accessible to all the instances of a class. It's like a constant, but for classes. To make it more easy to understand some code will do the work:
public class Example {
public static int numero;
}
public class Implementation {
public static void main (String args[]) {
Example ex1 = new Example();
Example ex2 = new Example();
Example.numero=10;
System.out.println("Value for instance 1 is: " + ex1.numero);
System.out.println("Value for instance 2 is: " + ex2.numero);
}
}
Running the follwing code will output:
Value for instance 1 is: 10
Value for instance 2 is: 10
Because you set the static variable numero (number in italian) to 10.
Got it?
It looks like a lot of your static methods (findNodeInList, etc) all take the ArrayList (which represents a map) as their first argument. So instead of having it static, you could have a class Map, which stores a list of nodes and has methods on them. Then the main method would read the input, but not have to manage any nodes directly. e.g:
class Map {
ArrayList<Node> nodes;
public void addNode(Node n) { nodes.add(n); }
public int findNodeInList(String s) { ... }
...
public static void main(String[] args) {
Map peggyMap = new Map();
Map samMap = new Map();
// Read the data
samMap.add(new Node(...));
}
}
This keeps all the stuff to do with nodes/maps well encapsulated and not mixed in with stuff to do with reading the data.
Static is useful if you going to be using the class/method throught out your program and you don't what to create a instance every time you need to use that method.
For ex
public class StaticExample {
public static void reusable() {
//code here
}
}
It means you can use it like this
StaticExample.reusable();
and you don't have to create an instance like this
StaticExample staticExample = new StaticExample();
staticExample.reuseable();
I hope this help you decide whether to use static or not.

What are some best practices and tricks when passing values from a main() to an Array Stack in a different class?

I am trying to pass values from my private static void main(...) into a class that has an array stack initialized in the constructor. I was wondering how to take the values I assign to a variable in the main() and push that value onto the array stack within this innerClass?
I know that the array stack works, I have implemented this class before without a problem, but I was only using the arrayStack() I had created and a main(). The addition of the third class is confusing me.
Without getting too deep in my code, I was hopping someone could explain (or point me to some resources) to me how to pass arguments to a stack that is initialized in a constructor, with arguments from the main() method of a different class (same package)?
Example of where I'm trying to get values to:
package program2;
public class Exec {
public Exec(DStack ds) {
/*I have initilized an arrayStack to hold doubles (i.e. DStack).
* I can use ds.push()/pop()/top() etc.
* I cannot take the value from Calculator.java and push that value
* here, which is what I need help understanding?
* */
ds.push(Calculator.i); //I would expect an error here, or the value stored in
//Calculator.i to be added to the stack. Instead program
//terminates.
}
}
Where I would like to take the values from:
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
i=9; //I'm expecting that by using Calculator.i in the Exec class that
//I should be able to push 'i' onto the stack.
}
}
This question goes along with a question and answer I was able to get working yesterday here: Get answer from user input and pass to another class. There are three differences, one, I am no longer selecting an answer from the menu and performing an action. Two, I would like know how to get items on a stack versus comparing the String in a series of if/else statements. Lastly, I would like to know a little more detail about the nuts and bolts of this action.
You seem to completely misunderstand how an application works. When you launch your program, java executes your main method. All its instructions are executed in sequence until the end of the method is reached. If you haven't started any other thread from this method, when the last instruction in the main method has been executed, the program terminates.
In this case, the main method contains only one instruction:
i = 9;
So this instruction is executed, and since it's the last one, the program terminates. You don't even reference the Exec class anywhere, so this class isn't even loaded by the JVM.
If you want to use the Exec class, then you have to do something with is somewhere in the program. For example, you could do
i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack);
Note that storing something in a public static variable in order for some other object to be able to get this value is a very poor form of parameter passing. If an Exec object needs a value to work, then it should be an argument of its constructor:
public Exec(DStack ds, double value) {
ds.push(value);
}
and in the main method, you would use a local variable and not a public static variable:
double i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack, i);
If I understand your question correctly, you should create an instance of the Exec class. You can also create an instance of DStack within your program and pass it the Exec constructor after pushing the double value onto the stack.
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
DStack dStack = new DStack();
dStrack.push(i);
Exec exec = new Exec(dStack);
}
}
I think you are confusing the concept of class vs. instance. You don't pass values to classes, you pass values to instances (static fields are sometimes called class variables and can make things confusing, but ignore that for now).
In a nutshell, a class is the code for that class you wrote. An instance is the actual thing that was spawned from that definition of class and actually does stuff. So the number one trick is to "instanciate" your class and create an instance. Then you pass whatever values you want to pass it like below:
class Foo {
public static main(String[] args) {
Bar bar = new Bar(); // <-- now you have an instance called bar
bar.arrayStack.push(args[0]); // <-- Now it's passed!
}
class Bar {
ArrayStack arrayStack;
Bar(){
arrayStack = new ArrayStack();
}
}

Categories